2024年12月25日水曜日

リモートワークに対する備忘録

数年前にリモートワークが始まったが、僕の所属している企業でも段階的にリモートワークが廃止されていく雰囲気である。
リモートワークについての感想を書いている記事があったので、自分もまとめておこうと思った。
数年後には、当時は良かったとか、色々美化されると思う。自分も記憶を改竄することだろう。過去は美化されがちなので。
実際に起こったことも忘れるが、当時の感情も忘れがちなので、事実を感情などを交えつつ備忘録を残しておこうと思う。
僕は、IT企業で働くエンジニアで、メンバーを経験してマネージャーもやって転職もしている。それぞれの立場から見えるものも変わる部分もあるのでそこも記載してこうと思う。

リモートワークの社会的変遷

まずは、Covid-19が流行した後のリモートワークの状況についてChatGptに教えてもらいました。

新型コロナウイルス感染症(COVID-19)の流行に伴い、日本ではリモートワーク(テレワーク)が急速に普及しました。2020年4月の緊急事態宣言時には、多くの企業が出勤者数の削減を求められ、リモートワークの導入が進みました。労働者にとっては、通勤時間の削減やストレスの軽減、業務効率の向上などのメリットが報告されています。


しかし、リモートワークには課題も存在します。社内でのコミュニケーション不足や、勤務時間とプライベートの区別がつきにくいといったデメリットが指摘されています。また、労働時間が減少する人が多い一方で、増加する人もおり、二極化の傾向が見られます。


2023年5月8日に新型コロナウイルス感染症が5類に移行した後、企業の働き方にも変化が生じました。リモートワークと出社を組み合わせたハイブリッド勤務が一般的となり、出社頻度が週5日以上の労働者が6割以上を占めるようになりました。これは、2022年の同時期と比較して、平均で週に約1日出社日数が増加したことを示しています。


さらに、リモートワークの頻度にも変化が見られます。2024年の調査では、「フルリモート」が2.9%、「週4日」が7.4%、「週3日」が18.8%、「週2日」が34.4%、「週1日」が36.5%となっており、2023年と比較すると、「フルリモート」や「週4日以上」の割合が減少し、「週1日」の割合が増加しています。これは、他者との接触を最小限にする働き方から、ハイブリッド型の勤務形態へとシフトしていることを示唆しています。


このように、COVID-19の影響により、日本の労働者の働き方は大きく変化しました。リモートワークの導入により、柔軟な働き方が可能となった一方で、コミュニケーションの課題や労働時間の管理など、新たな課題も浮上しています。今後は、これらの課題に対応しつつ、労働者がより効率的かつ健康的に働ける環境の整備が求められます。

リモートワークの実施状況とは以下のようです。

年度 テレワーク導入企業の割合 テレワーク実施者の割合

2017年 13.9% -

2018年 19.1% -

2019年 20.2% -

2020年 50.3% 28.5%

2021年 57.0% 22.7%

2022年 56.6% 20.2%

2023年 50.0% 19.3%

だいたい実感とも合っているので、まあ正しそうです。


リモートワークのメリット

リモートワークでは通勤がないとか作業に集中できるとか色々メリットがあげられますが、個人的には以下だと感じます。

家族とすごす時間が増える

リモートワークが当たり前になる以前は、世間一般には遅めに出社して終電まで働くような生活でした。夜は家にいないのが当たり前です。
リモートワークが突然増やされることで、子供を保育園に送っていくだけでなく、お迎えも行けるようになりましたし、夕食も一緒に食べるようになりました。
僕のように家にいないのが当たり前な生活をしていた人たちでも嫌々働いていた人はいたと思います。ただ、僕や僕の周りは好きでそうしていた人が多かったと思います。働きたいから働いていたわけです。
深夜にする雑談とか楽しかったですし。
そんな僕が子供と夕飯を食べたり、一緒にお風呂に入ったり。もちろん週末は遊ぶしお風呂にも入れていましたが、過ごす時間の濃さが段違いであったと思います。
会社には何の関係もないし利益にも結びつかないですが、子供がまだ小さい家庭では、給料が多少増えてもリモートワークが出来ない会社に転職することは、あまりないのではないかなと思います。
また、個人的には体験していませんが、故郷(外国含む)に帰って仕事をすることもできるのは大きなメリットだなと感じます。他のチームの人だったりすると、プライベートなことを話す時間的な余裕がなかったりしますが、そうすると帰国していることに気がつかなくて、しばらく経ってから知るようなこともありました。それくらい働く場所を意識しなかったです。

作業に集中しやすい環境を整えやすい

デスクやモニターも自分で選べますし、音楽をかけたりとか色々出来ますし、自分のお気に入りの空間を作ることができます。
スペースが許せば会社のデスクよりも広い机で作業している人もいると思います。
また、服装もリラックスできる格好ができますし、靴も履かなくていいので足が臭くなることも無くなりました。これは個人的には地味に嬉しいです。自分のもですが、他の人の匂いを感じないというのは、地味にストレスが減った気がしています。
作業者としては自分の蔵書にすぐにアクセスできるというのもメリットの一つと感じました。
会社で働いている時には、家にある本に書いてることを見ながら作業したいとか、ちょっと確認したいとかがあっても無理でした。
家にいれば、当たり前ですが、それらにすぐにアクセスできますし、プライベートで利用しているパソコンから電子化された書籍にアクセスすることも容易でした。
今は、ChatGptがいますから、蔵書へのアクセスは必ずしも必要ない気もしているので、メリットとしては薄れたかもしれません。

遠方の人が採用できる(遠方の引っ越せる)

よく言われるメリットですが、僕のチームや部署では実際に遠方の方を採用したり、遠方に引っ越した方がいます。
遠方であるということは、デメリットではあります。気軽に集まれませんからね。
ジュニアレベルの人で遠方に住んでいる人をわざわざ採用するかというとそうでもないのではないかと思います。
実際に遠方に住んでいるから不採用になったという人はいなかったんじゃないかとは思います。
ただ、遠方に住んでいるけどぜひ採用したい人をコストをかけて採用プロセスに乗せるようになった結果として、遠方に住んでいる人たちの能力は、総じて高いと感じます。完全に個人の感想ですが。

その他のメリット

オフィスを持たないことによるコストの削減などもあるとは思います。ただ会社組織としてのメリットというのはそれほどないのかもしれないです。リモートになって利益率が上がったってニュース見ませんしね。
転職のし易さ、リモートワークが転職する時には有利に働く部分はあるとは思います。実際にオフィスに行かずに面接をして採用というのが大半でしたから。
ただ、個人的にそれほど大きなメリットには感じていません。
オフィスに面接に行かなくてもいいとか隙間時間に面接ができるとかメリットはあるかもしれませんが、それって面接の数を多くこなせるとか転職までの期間を短くできるなどが得られる利益だと思います。ただ、そんなに素早く沢山面接して、できるだけ早く転職することにあまり意味はないと感じます。
数ヶ月から1年とか2年かけて転職活動してでも、きちんと条件などが自分に合うところを見つける方が重要なので、転職のしやすさというのは個人的にはあまり意味のあるメリットではないと感じます。

リモートワークのデメリット

デメリットにつてもあげていきます。

コミュニケーションの難易度が対面よりも高い

リモートワークになってから、今も感じることですが、コミュニケーションは難しくなりました。
コミュニケーションといっても、日常会話とか仲良くするとかそういうことじゃないです。
業務におけるコミュニケーションは、認識のずれの修正や相互の合意形成です。
対面であれば、ホワイトボードを使ってすぐに伝えられることがリモートワークだと伝わらなかったりします。
自分が図を書くのが得意で、対面であれば、相手にも加筆を頼んで相互に認識のずれを修正していけますが、リモートワークだと書き手は一方的になりがちで、共同編集は非常に難易度が高いです。ずれが実際に修正されたのかの確認は対面よりも手間がかかる印象です。
また、コミュニケーションが苦手な人同士で会話していてもZOOMなどで話をされると周りは全く気がつきません。オフィスであれば、揉めてそうな気配に気がついた人が間に入ったりも出来ますが、それがないため、一度揉めると揉め事の深刻度が増す傾向があると感じます。

運動不足が深刻になる

運動しろよ。って話なんですが、あきらかに太った人が増えました。
社会的に健康寿命は減ったと思います。
この数年で足腰が弱り、介護を必要とする年齢が下がるのではないかと思います。
すぐには影響を感じませんが、数年後に影響が顕在化しないかと憂慮しています。

世の中で話題になる点:生産性とイノベーション

生産性

生産性については、そもそも計測の仕方が難しいと思います。
エンジニアの目線だと、コードが書きやすい環境の方が生産性が高いと主張したくもなりますが、コードを沢山書いたからといって、売り上げが上がる訳じゃないですからね。
重要なのは売り上げや利益の増加であり、エンジニア的生産性がいくら向上したところで、会社としての生産性とは、相関も因果もないと思います。
管理職目線だと、リモートワークだとサボっている人がわからないという意見を目にしたこともありますが、管理職の人は誰がサボっているかなんとなくわかると思いますし、オフィスにいたからといって、尻を叩けばみんな働くかというとそうでもないと思います。
リモートワークでもオフィスでも、大事なのは自走できる人を採用することであり、細かく指示をしないと業務が滞る人は、リモートワークでもオフィスでも業務が滞ると思います。
作業者はリモートワークの方が生産性が高いと言いがちで、管理者はオフィスの方が生産性が高いと言いがちだと思います(印象)。
個人的には、上記のことから、どっちもどっちで、リモートでもオフィスでも日本の企業の生産性は海外と比べて低いので、視点を変えて教育に力を入れるとか、人を入れ替えて知識の共有を進めるとか、他の打手を考えた方がいいんじゃないかなと思ったりはします。

イノベーション

イノベーションについても同様にリモートワークかオフィス勤務かは関係がないと感じます。
対面の方がイノベーションが起こりやすいという意見が見られましたが、そもそも昔からほとんどの企業がイノベーション起こせてなくねぇか?というのが個人的に感じるところです。
そもそものイノベーションの数自体が少ないと思うので、オフィスにいようがリモートワークしようが、イノベーションはほとんど起こりません。それが現実だと思います。
アメリカ企業では、イノベーションが日本よりも起きていたと思うので、彼らのオフィス回帰の主張には共感するところがありますが、日本はもともとイノベーション起こせてないからな。と思ってしまいます。
リモートかオフィスかではなく、こちらも他の打手を考えるべき課題だと思います。

オフィスに戻ったら、イノベーションが起こるのでは?とか売上が上がるのでは?と経営者が安直に考えているとたら、そうはならないと思うので、解決すべき課題が隠蔽されそうで不安にはなります。

今後について

オフィス勤務環境の悪化

もともと日本のオフィス環境は、アメリカの大手ITよりは悪いものでした。
単純に土地の問題があると思いますが、オフィス設計という意味で、社員が会社にいたくなるような設計思想みたいなものは強くないと感じます。
リモートワークになって、オフィスがなくなり、コストがある程度は削減できたと思います。
オフィスに回帰した時に、わざわざ大きなコストをかけて出社が楽しくなる仕組みを用意する企業がどれほどいるのかは疑問です。
また、一人の空間になれた人たちが、オフィスに集まったときに、匂いや音の問題で揉めはしないかと心配しています。
固定席があれば、人間関係ができることで許容できることもあると思いますが、フリーアドレス制だと、人間関係が構築されない状態で、受け入れ難い勤務スタイルの人と隣り合うわけで、揉め事が増えなくてもストレスは増えそうです。
10年後はわかりませんが、数年はオフィス環境は悪化した状態が続くのではないかと思います。そうならないように祈るばかりです。

今の気持ち

内容を読むと、リモートワークにメリットが多く、オフィス勤務には意味がないと考えている人の文章みたいだなと感じましたが、個人的にはオフィス勤務の方が好きです。
確かに、リモートワークは多くの恩恵を僕の人生にもたらしたと感じます。
子供と過ごす時間は他に変え難く、子供の年齢が低いうちに多くの時間を過ごせたことは、僕の人生には明らかなプラスでした。
しかし、オフィス勤務でも良いことはあったなと思い返したりもします。
通勤は散歩みたいなものでいい気分転換になります。東京は街路樹が多く四季の空気を感じて、朝時間に余裕がある時や夜に東京を1駅分くらい歩くのは、ちょっとした楽しみでもありました。
オフィスでは色々な人と会話しながら、ものづくりを進めていくのは楽しいものです。
メンバーやプロジェクトがカチッとハマって、どんどんプロダクトが気持ちよく作られていく体験は、やはりリモートワークでは実現が不可能であると感じます。
緊密なコミュニケーションと成果物のこまめな共有が、成果が形になっていくことを実感させてくれますし、それらを一緒に作っている仲間の存在を意識できるのは、オフィスに集まって働く楽しさだと思います。(オフィス勤務は、こういう楽しさを作るための必要条件であり、十分条件ではありませんが。。。)
ただ、会社としての課題は売り上げを伸ばすことだと思うのですが、その改善には寄与しないのではないかと予想しています。
日本経済が右肩下がりなこともあり、オフィスに集まったけど売上は上がらずリストラが始まる。というような未来はあり得るものだと思います。
そうならないようにリモートかオフィスかに関係なく、売上を上げていきたいものです。

2023年5月5日金曜日

ソフトウェア開発における品質に対する態度の違いは顧客のニーズにあるのだろうと思った

 日本のソフトウェアを作る企業や企業内のソフトウェアを開発する部署に所属した経験から、品質に対する態度の違いみたいなものがあり、それがどうして生まれるのかについて思うところがあったので、記録しておく。

ここでの品質と言っているのはいわゆる品質保証でQAなどと呼ばれる部分だ。ソフトウェアの読みやすさとかそういった観点での品質もあるとは思うが、最終的な製品の品質の部分に対して考えてみる

開発手法自体は、大きく分けると2通りの開発手法があると思う。リーンソフトウェア開発とウォーターフォール開発だ。開発手法が違えば品質に対する考え方も取り組みも違ってくる。

ウォーターフォール開発の品質への取り組み

ウォーターフォール開発の場合は、計画重視の開発サイクルが特徴だと思う。プロジェクトの初期段階で厳密な要件定義と設計を行い、段階的に開発を進める。品質保証は、各フェーズの終了時に行われることが一般的であり、その過程で問題が見つかった場合は、適切な修正が行われる。
この各フェーズでの品質の保証というのが特徴的だと思う。製造業と同じように各工程で完璧なものを作れば、最終的に完璧なものができると言う考え方だ。
当たり前だが、完璧なものを作るのは無理なので、当然不具合がある。不具合があれば、工程を遡ってやり直せば良いのだが、そうはならない。
なぜ、そうはならないかというと、企業がなぜウォーターフォール開発を選択しているかに関係すると思う。ウォーターフォール開発を選択する企業はスケジュールを非常に重視する。理由はハードウェアのリリースだったり、ユーザー企業の都合だったりとさまざまだと思うが、スケジュールは死守されるものだ。そのためスケジュールが立てられるように見えるウォーターフォール開発を選択するのだと思う。これは、ソフトウェア開発を必要としている顧客からのニーズである。

リーンソフトウェア開発の品質への取り組み

リーンソフトウェア開発では、顧客価値の最適化を重視し、継続的な改善とフィードバックの活用が特徴だと思う。開発チーム全体で品質保証の役割を分散し、短いサイクルでリリースと検証を行う。これにより、顧客とのコミュニケーションを重視し、適応的な開発を実現する。
リリースサイクルは毎日で、検証を毎日行う。テストの自動化もマニュアルのテストもするが、リリースサイクルを短くすることで、最終的にユーザーが利用する物が高品質になることを目指している。
短いサイクルで品質を保証していくというのが特徴的だと思う。毎日リリースするので、細かい不具合は出るが、大きい不具合は見つかったらすぐに修正(リバート)される。品質が保証されずに安定しているとは言えないとも思う。場合によってはユーザーの活動が丸一日止まるようなこともある。そのため、ほとんどの場合、コンシューマー向け製品で採用されている方法だと思う。企業相手では、丸一日サービスが停止するような状況は到底受け入れられないサービスレベルだと思う。

両方を経験しての比較として

両者を経験したことがあるが、顧客のニーズが違うというのが最も大きな違いだったと思う。
ウォーターフォール開発の場合は、ハードウェアを作っている製品開発者などが顧客であり、ハードウェアが関係するので、リリース時期が動かせないのだ。
リーンソフトウェア開発は、いわゆるWeb系企業で、これらの企業の顧客は一般人で、リリースしたものが直接顧客に届くのが一般的だと思う。そして一般の人にはリリース時期を確約することはほぼないと思う。これは、どんな製品でもそうだが、ソフトウェア開発が直接的に製品になっている場合もリリース時期を確約をすることはまずない。

開発現場からするとどちらの方が働きやすいかと言ったら当然リーンソフトウェア開発なのである。
どんな開発者でも品質の保証など出来ないし、努力はするが保障というのは難しいのである。
リーンソフトウェア開発でも毎日完璧を求められることもあるとは思うが、ほとんどの場合は、一般のユーザーがほとんど無料で利用しているので、不具合が発生することはある程度織り込まれている。顧客との期待値の調整がすでに行われていて、結果として毎日のリリースなどが可能になっていると思う。
ウォーターフォール開発の最も深刻な問題は、保証できないものを保証しようとしているところだと思う。企業のニーズ(スケジュール死守)があるとはいえ、出来ないことを約束している点に問題があると思う。製造業においても不具合というのはあると思う。だが、製造ラインを動かす前に仮組みをして問題が発生すすれば、何処かの工程からやりなおすはずだ。
設計に問題があっても、必ずしも設計からはやり直さず、製造工程でなんとかすることもあるとは思う。
だが、ソフトウェアの不具合を製造工程で吸収するというのは、不可能だろうと思う。逆はあったとしても。そのため完璧なものが求められるが、最終的な製品になっていない状況で完璧はあり得ないと思う。

日本のSIerは多重下請けとかの問題もあるし、最近では給料もWeb系の方が高くなっていると思う。メーカーのソフトウェア開発も似たような状況だと思う。顧客からのニーズに応えているだけといえば、そうであるが、結果として産業全体で不可能なことを実現するために多くのリソースを割いているようにしか見えない。

ソフトウェアをハードウェアの部品のように扱うのではなく、ソフトウェアとして利用するようにユーザー企業が変わっていかない限りはこういった状況は変わらないのだろうなと思う。


2019年12月25日水曜日

Flutter advent calendar 2019 まとめ

やり始めたから最後までやったけど、25個はネタが無かったです。
むりやり作った感のあるものも何個かあったなと。。。
とはいえ、調べたことの供養の意味もあったのでまあ良かったかなと。
https://adventar.org/calendars/4869

他には多言語対応や画面回転時の挙動とか調べたいなと思っていたりはします。
Nativeアプリをつくるなら、BLEやNFCをどうするのかとかも思いますが、そこまでやるならNativeのActivityなりを別途起動して対応したほうが現実的な気もしています。

まとめはFlutterについてちょっと感じたことをメモ程度にまとめようかと思います。

Flutterの良いところは、いろんなところで記述があるので、あえて良くないところを上げてみようかと。技術的な良くないところというよりは、将来的な運用も考えたときの不安ですね。

Dartが人気ないなーと感じてます。
Dartの言語としての人気は、お世辞にもあるとは言えないと思います。言語自体が良いかどうかは僕にはわかりませんが、人気がないということは、使っている人がいないということです。
https://redmonk.com/sogrady/2019/07/18/language-rankings-6-19/
ランキング的には圏外のようですね。。。Advent calendarも過疎ってましたし。
Flutterで利用したアプリが売上がたって、人を増やそうとした時に、人員の増加は他の言語などよりも厳しいのではないかと思います。人が少ないですから。
Dart自体は、独自の文法ということは無いです。個人的にはObjective-Cの方が難しい。。。実際に触ってみれば特に困る人は少ないと思いますが、過疎っているものに自分の時間を使うというのは、なかなか勇気がいりますしね。

Flutter自体の普及に関してもまだまだな感じはします。
Androidが出始めのころも、いまのFlutterとちょっと似ていて、Productionでの開発経験がある人は殆どいないけど、趣味で触ってみている人たちがたくさんいる感じでした。
実際に業務で、いろんな端末でいろんなバグを踏みながら開発をしていた人というのは、運良くAndroidの開発の案件が社内であって、運良く担当していたといった具合だったと思います。そのため、Androidの開発経験がある人を中途採用しようとしても、趣味でやってい人は見つかっても、業務経験がある人は殆ど見つからなかったと記憶しています。
Flutterの現状も、ちょっと似ているかなと感じるところがあります。
10年前くらいもBlog書いたり勉強会で発表したりとかのエンジニア文化はありましたが、今はもっとそれが活発なので、すごい流行っているように見えても、実はProduction環境ではそんなに使われていない。というのが現状かなと、特に定量的根拠はありませんが感じるところです。

開発元のGoogleがFlutterで儲ける気がなさそうというのもちょっと気になるところです。
Flutterの開発元はGoogleですが、GoogleのプロダクトでFlutterを利用しているものがあるかというと、パッとは思いつきません。
https://flutter.dev/showcase
ここにあるように、すでに様々なもので利用されてはいますが、GoogleがFlutterで儲けてはいないと思います。今後も儲ける気があるのかよくわかりません。
現状のツールやドキュメントやビデオなど、お金とってもいいレベルで揃えているのに無料です。ある日突然、Googleがもう辞める。って言い出さないか不安になります。
Open sourceだからみんなでメンテすれば大丈夫。というのは少々ナイーブで、現実には、お金を儲けているプロダクトの基盤になっている技術だから、企業がお金を出して雇っているエンジニアを使ってメンテするわけなので、Googleにはなにか儲ける方法も考えていただきたいところです。もしくは、儲かっているプロダクトで使ってほしいです。
Open sourceも当たり前ですが、万能じゃないです。様々なゲームアプリ(たぶんモンストも)で利用されているCocos2dxもhttps://takachan.hatenablog.com/entry/2019/11/30/234321
こんな状況のようです。
数年前に僕もCocos2dxを使ってゲームアプリをリリースしましたが、当時はCocos2dxも最新のLibraryを導入したり活発に開発されていたので、隔世の感があります。
Flutterはこうならないことを祈ります。


とはいえ、実際に触ってみた感触としては、Productionで利用できると思いましたし、実際に海外(主に中国?)では、使われているようです。
今、新しいNativeアプリ作るなら選択するかなと思います。
まあ、完璧なframeworkやlibraryなど無いので、何を使うかは、その時々のチームの人員などによって妥協しつつ決めていくと思うので、現実には常にFlutterがオススメというわけではなく、すべてのモバイル環境でカメラや指紋認証も使えるようになりつつあるWebでのアプリ作成も選択肢に入れていくとは思いますが。

1人 Flutter Advent Calendar 2019:#25 onActivityResult


Androidでは一般的な問題ではありますが、OSが勝手にActivityをkillすることがあります。
Androidであれば、状態を保存しておき、再構築するための仕組みが用意されていますが、Flutterにおいてはそれがありません。

OSにActivityがkillされた場合にFlutterのinstanceも開放されてしまいます。stateの管理をどうすればよいのか?
これについては、すでにissueが上がっていて
https://github.com/flutter/flutter/issues/6827
ここで、議論はされていますが、3年前から続いています。。。
特にこれといったスタンダートになっている解決策はないというのが現状だと思います。

ただ、基本的にFlutterでアプリケーションを作成して動作させていて、問題になることは、ほぼないと言って良いと思います。アプリが裏にいって、また最初からでもそんなに困るケースはまれですし、そういうもんだという前提で作ればどうにかなるかと思います。

問題になるのはFlutterアプリケーションがほかアプリとアプリケーション間連携を行うような場合などだけかと思います。
カメラで撮った画像を取り込むとか何かのSDKを組み込んで値をonActivityResultで取得するのを前提とした仕組みの場合でしょうか。

すでにissueが上がっていることは示しましたが、解決策がないので自分でなんとかするしかないです。

onActiivtyResultがcallされたタイミングではFlutterのインスタンスがまだないので、値を通知することも出来ません。
Flutterの準備が出来たタイミングでFlutter側から値を取得しに行くほうが良さそうです。
そうすればタイミングを考える必要もほとんどないので。

とりあえずサンプルを作ってみました。いつものmy_appで数字をcount upして、中央のbuttonを押すとFlutterとは関係のないAcitivytが立ち上がります。このActivityで数字を編集して、Buttonを押すともとのFlutterのActivityに値を渡すというものになります。

普通に実行すると

I/flutter android(15154): enter onCreate
I/flutter android(15154): exit onCreate
I/flutter (15154): enter main
Syncing files to device Pixel 4 XL...
I/flutter (15154): before getActivityResult
I/flutter (15154): exit main
I/flutter (15154): after getActivityResult
I/flutter (15154): before openOtherScreen
W/ActivityThread(15154): handleWindowVisibility: no activity for token android.os.BinderProxy@e3ade16
I/flutter android(15154): enter onActivityResult
I/flutter android(15154): exit onActivityResult
I/flutter (15154): after openOtherScreen
I/flutter (15154): before getActivityResult
I/flutter (15154): after getActivityResult

こんな感じです。
openOtherScreenをcallするとActivityが立ち上がるのですが、それの結果が戻ってくるのをawaitで待っています。
で、onActivityResultが終わった後にopenOtherScreenのreturnが来ているのが分かると思います。
FlutterとAndroidのActivityの間でデータのやり取りがスムーズに出来ています。

端末の設定でDon't keep activityを有効にして同じことをしてみると。

I/flutter android(15383): enter onCreate
I/flutter android(15383): exit onCreate
I/flutter (15383): enter main
Syncing files to device Pixel 4 XL...
I/flutter (15383): before getActivityResult
I/flutter (15383): exit main
I/flutter (15383): after getActivityResult
I/flutter (15383): before openOtherScreen
W/ActivityThread(15383): handleWindowVisibility: no activity for token android.os.BinderProxy@189e8ec
W/ActivityThread(15383): handleWindowVisibility: no activity for token android.os.BinderProxy@75ebc8e
I/flutter android(15383): enter onCreate
I/flutter android(15383): exit onCreate
I/flutter android(15383): enter onActivityResult
I/flutter android(15383): exit onActivityResult
I/flutter (15383): enter main
I/flutter (15383): before getActivityResult
I/flutter (15383): exit main
I/flutter (15383): after getActivityResult

openOtherScreenをコールして他のActivityが立ち上がって、裏に回ったFlutterのActivityが一旦destroyされているので、またonCreateから始まっているのが分かると思います。
ここで、「exit onActivityResult」の後に「enter main」が来ていることからもonActivityResultで取得した値を単純にFlutterに受け渡せないのが分かると思います。

なので、Flutterが起動し終わった後にgetActivityResultをFlutterからcallして結果を取得するようにしています。
こうすることで、外部アプリとの連携なのでデータのやり取りが可能かと思います。
まあ、platformのつなぎこみとかでタイミング問題が出る時には、だいたい待ち合わせを頑張るよりかは、値をpullしにいく仕組みにしておいた方が、見通しが良い気がしています

サンプルは以下です。
https://github.com/matsuhiro/on_activity_result_test

2019年12月24日火曜日

1人 Flutter Advent Calendar 2019:#24 無限scroll list + checkbox


FlutterのLIstViewは予めitemの数がわからなくても作成できます。
nullを返すまでは作り続けることができます。

checkboxをつけた時にどういった動作になるのかなどが気になりました。
内部ではWidgetがリサイクルされているので、checkboxのcheckがスクロールアウトしてもう一度表示したときには消えてしまいます。
checkされていたというデータをどこかに保存する必要があります。

例ではsharedPreferenceに入れてみました。
https://github.com/matsuhiro/scrollable_list_radio_test

適当にitemに表示する文字列をユニークキーにしていますが、ちゃんとItem用のデータ構造を作って、unique keyはindexにするとか決めたほうが良いとは思います。

ListViewでもFutureBuilderは、きちんと使えそうなので、DBから表示すべきデータを読み込んでから出すとか、通信の結果として得られたものを表示するとかも問題なく出来そうです。

FutureBuilderを利用しなくても、asyncでデータが得られたあとでsetStateすれば同じことはできますが、その場合にはcheckされていないものがcheckされた状態になる時に、checkboxのところだけ少しちらつく感じがするので、FutureBuilderを利用して全体的に差し替えた方が結果的にはきれいに表示される印象です。

Listに関しては、これが良い記事でした。実際に直面した課題の解決策は読んでいて面白いです。
https://note.com/kitoko552/n/n52cb06e79d49

2019年12月23日月曜日

1人 Flutter Advent Calendar 2019:#23 flare&lottie


Effectを再生するにあたって、AndroidやiOSをやっていた人ならば、Lottieを思い浮かべるのではないでしょうか?Flutterの場合はFlareというのがあります。

https://www.2dimensions.com/
再生用のlibraryによって使い方が異なるので、どっちが良いかと言うのは言えないですが、どちらも良く出来ています。

どっちも、再生用に利用されるファイルはJsonです。
サンプルを記載しておきますが、AndroidのSimulatorではLottieの再生は出来ませんでしたが、実機であれば問題なく再生されました。

Lottieについては、FlutterのPlatformVIewを利用しているようです。
そのため、iOSでは再生できるけどAndroidでは再生できないとかありそうです。
Flareの方は、dartで処理しているようだったのでそのようなことは無さそうです。

とはいえ、Flutterは内部ではSkiaを利用されています
https://skia.org/dev/flutter
skiaには
https://skia.org/user/modules/skottie
といった感じで、Lottie用のI/Fが用意?されているようです。(ただしフルサポートしていいるのはまだAndroidのみ)
そのため、こちらで再生する形のものを作った方が良いかも?

以下にサンプル上げておきます。
https://github.com/matsuhiro/flutter_flare_lotie

2019年12月22日日曜日

1人 Flutter Advent Calendar 2019:#22 animation


Animationをする場合に、途中で止めたくなることあるとありますかね。
ゲームだと当たり前に途中で止めることあるんですが、Flutterが想定しているようなアプリの場合はあまりないかも。

でも気になったので調べました。
stopで簡単に止まりました。再開しようと思ったら、forwardを呼び出せば再開します。
簡単でした。




レイアウトも動的に変わるし、とても簡単です。
コメント入れてありますが、試すときにはsdkのversionを2.2.2以上にしてください。
https://github.com/matsuhiro/animation_test

floatingボタンで開始/一時停止が行えます。

2019年12月21日土曜日

1人 Flutter Advent Calendar 2019:#21 通信状態監視


通信状態を監視して、状態を変えて、ユーザーに操作を促すとか普通にやりたくなると思います。
Snackbarだしたりとかとか。

それもFlutterだと簡単に出来ます。
Flutterのいいところは、誰かが作ったものがたくさんあるところですね。Androidとかも同じなんですが、導入までのハードルが低すぎて引きます。

https://pub.dev/packages/connectivity
というのを使ってみました。

これ使うと通信状態監視できます。
サンプルは以下です。
https://github.com/matsuhiro/flutter_connectivity_test
airplane modeとかにすれば、snackbar出てくると思います。

ちょっと工夫したところとしては、Snackbarを表示するところでしょうか?
setStateでUIが変わるんですが、そこでSnackbarを表示しようとするとエラーになるため、Delay 0秒で、UIの構築の次の処理に回しています。

2019年12月20日金曜日

1人 Flutter Advent Calendar 2019:#20 delayedで逐次処理


DartはSingle threadで操作しているので、どこかで重たい処理が走ったらCPUを専有してUIの更新が止まります。

ネットワーク通信とかでも止まりそうに思いますが、Socketからデータを読み出すまでは、待ち状態になってCPUが動いていないのでUIがブロックはされないようです。

でも、重たい処理をしたいこともあると思います。
Fileのコピーや動画のEncodeなどは、for 文で繰り返し行ったりすると思います。
そんな時には、Event loopに少しづつ処理をしてもらう感じにしたいこともあると思います。
そうすれば
「少しencode」→「UI更新」→「少しencode」→「UI更新」...
のようになって、UIをblockすることもないです。

AndroidだったらrunOnUiThreadとか便利なmethodがありますが、dartのIsolateにはそういった関数は無さそうでした。

似たようなことは、
Future.delayed(Duration(seconds: 0), doSomething);
のようにすれば、実現できそうです。
https://github.com/matsuhiro/flutter_async_test
サンプルです。
いつものやつですが、floatingボタンを押すと延々とcount upしていきます。

サンプルを動かしてもらえればわかりますが、duration = 0でひたすら動いていますが、timerも動いているので、UIがBlockされていません。

これが何をやっているかというとdoSomethingの処理をひらすらMain loopのqueueに入れていますが、TimerもMain loopのqueueに処理を入れているので、どちらも逐次処理されている感じです。

とはいえ、重い処理の場合はcomputeとかを素直に使うのが良いのかなと思います。
現実には、そこまで重い処理はC++で書くServer側に処理を任せるなど、dartにこだわらない選択をすることになるのかなと思ったりします。

2019年12月19日木曜日

1人 Flutter Advent Calendar 2019:#19 DevTool


FlutterはDevToolが充実していています。
AndroidやiOSならMarketでアプリの売上につながるから開発環境を整えるモチベーションもわかりますが、なぜFlutterでこんなに整っているのか。しかも無料。

Performanceを見るツールもありますが
https://flutter.dev/docs/development/tools/devtools/inspector
のにLayoutを調べる機能もあります。
Android Studioを利用しているならば⇧⌘A(Shift + command + a)で、「flutter inspector」で検索すると出てきます。

大体触れば何かが起こるので、だいたい分かると思いますが「Enable Select widget mode」はちょっと何が起こるのかすぐにはわからないと思います。
リンクをたどっていくと動画にたどりつくので見ればすぐに分かりますが、マウスで選んだ場所のWidgetがすぐに分かります。
https://youtu.be/JIcmJNT9DNI?t=361

AndroidでもLayout Inspectorがありますが、同じような機能です。

動画でやっているようなズルズルカーソルを動かすと選択されるWidgetが変わるようなことも実機でもできました。
指を置きっぱなしにして移動すれば実機上でどこに何があるのかわかります。

こんな機能、どこで使うんだろう。自分で作ったやつなら把握しているし必要ないだろうと思うかも知れないですが、人が作ったものをメンテする時には非常に役に立つと思います。
このUIを表示しているコードどこにあるんだろう。見つからない。。。とか、既存のアプリをメンテしている人ならよくあると思います。

Androidの場合、Layout Inspectorからidを見つけて、そのidから検索してとかを僕はしますが、FlutterならClick一つでcodeまでjumpするので、codeにたどり着くのが非常に早いですし、多少Layoutのcodeのネストが深くてもツールで追いかけられるのはすごいです。

2019年12月18日水曜日

1人 Flutter Advent Calendar 2019:#18 fps check


Flutterでは60fpsを目指しているとありますが、実際に60fpsがkeepされているかどうやったら分かるでしょうか?

Android StudioのでFlutter Performanceのwindowを開くのが最も良さそうです。
https://flutter.dev/docs/development/tools/android-studio#show-performance-data
ただ、release buildの時には当然使えません。

そんな時に大体のfpsを取ろうと思うとendOfFrameというのが使えると思います。
runAppの内部で行っていることをmainの中に書いて、WidgetsBindingにあるendOfFrameがfutureになっているので、thenで呼び出される関数を設定します。
これは、現在のframeの最後に呼び出されるだけで、毎frameごとに何回も呼び出されるものではないです。そのため、常に監視をしたい場合は、callbackの最後にもう一度設定をする必要があります。

https://github.com/matsuhiro/fps_check_test/blob/master/lib/main.dart#L3-L21

こんな感じ。

ただ、Flutterは、描画の必要がなければIdle状態になります。
ゲームのように常にEvent Loopが60pfsで動き続けているわけではないです。

実際に、Android studioで、Flutter Performanceのwindowを開くと描画がされていないときには、処理を行われていないことがはっきり分かると思います。

ここで示した例では、endOfFrameにcallbackを設定しています。そうするとidleになっていたものが起動されます。
そのため、Idleにならずに処理が続くことになります。
当然ですが、普通の状況では行うべきではないです。
release buildでfpsが知りたいときには使えるかもしれない程度で、実際にはこんな事しないでdebug buildでしっかりとperformanceのチューニングを行うのが良いでしょう。

サンプルです。

https://github.com/matsuhiro/fps_check_test

Flutter PerformanceはAndroid Studioの右下にあるのでclickすると見れます。
もしくは、⇧⌘A(Shift + command + a)で、「Flutter Performance」で検索してください。

2019年12月17日火曜日

1人 Flutter Advent Calendar 2019:#17 log


Flutterで適当にlogを出そうと思ったらとても楽で、printを使えばよいだけです。
それだけで、AndroidでもiOSでもログを見ることが出来ます。

ただ、これ、製品を作るときには困ります。
製品版では出したくないですよね。

Androidではproguradの設定で消したりtimber使ったりすると思います。
同じようにFlutterでも最初からLogについてはきちんと考えておいたほうが良いです。

print自体の制御をしたいと思っても簡単にprintの中身についてはわかりませんでした。
https://github.com/flutter/engine/blob/master/lib/ui/dart_runtime_hooks.cc#L200
このあたりで出力しているようなのですが、外部からの入力値によって出す出さないを切り替えるみたいな仕組みが無いような。。。うーん。

Flutterで利用するlogのツールとしては
https://pub.dev/packages/logger
が良さそうです。

特別なことはしておらずv,d,i,w,eと別れていて、使いやすいです。完全にログを出したくないと思えばLogFilterなどを作成して設定すれば良いです。
https://github.com/matsuhiro/font_log_test/blob/master/lib/main.dart#L11-L15
こんな感じで使えます。

といいえ、適当にprintだけ書いてそのままcommitしてしまうような事故もあるとは思うので、print自体をいじりたいもんです。


2019年12月16日月曜日

1人 Flutter Advent Calendar 2019:#16 cookbook


Flutterの記事はたくさんあるし、動画もあるしで、Flutterはドキュメントには事かきません。
日本語のドキュメントもあるし、日本語の本も何冊かあります。

なので、別に英語のドキュメントを頑張って読まなくても良いのかなとか思ったりもします。
ただでさえFlutterって公式のドキュメントが充実しているので、一つ一つ読んでいるとキリがないというのもありますが。

でも、Cookbookは一通り読んでおいたほうが良いのかなーとか思ったりもします。
こういう事言うと、「いや、これも。いや、あれも。」みたいな意見も出るでしょうけど、CookBookがいいなと思ったのは、テーマが具体的でこういうのってプロダクトで必要だよね。といったものがまとめられているという印象だからです。だからCookbookなのでしょうけど。

例えば
https://flutter.dev/docs/cookbook/images/cached-images
これとか、プロダクトで画像データのcacheとか絶対やると思いますし。

データの永続化だったり動画の再生だったりとかとか。いくつかの必要そうなテーマで短めに書かれているので読みやすいです。

FlutterのWidgetを一つ一つ見ていくのも面白いですが、実践的なものがよくまとまっているのはこれかなと。

githubにcodeもあればいいんですがね。自分で作れという話ではありますが、現在はないみたいです。

2019年12月15日日曜日

1人 Flutter Advent Calendar 2019:#15 click event


特定のWidgetをClickしたら処理をするのは当たり前ですが、その周りの余白だったりをclickした時になにか処理をしたい時にはどうすればよいか?

大抵は、Cancelのような挙動を設定したくなると思います。
Containerなどにもtapのイベントを設定することは可能です。GestureDetectorを利用して実装してみます。


https://github.com/matsuhiro/click_event_test/commit/39081b5a452cf23dd76f277c5b6919c1c4f8ca87#diff-fe53fad46868a294b309fc85ed138997R94-R132

これを適当なところにいれて表示させます。

Enable Debug paintをすると上のようになります。

Button以外の部分をtapすると「container tapped」と表示されるのが分かると思います。
Paddingの上をTapしても「container tapped」が表示されるので、だいたい想像通りに動作するようです。

ただ、Containerが何も描画していないとonTapが反応しません。
Event handingをしているのが、描画のObjectであるのが原因ぽかったです。
そのため、以下のようなコードだと
https://github.com/matsuhiro/click_event_test/blob/53596dfd7a6fd8e625ed8c27616be672f0a0b052/lib/main.dart#L94-L141
「inner container tapped」は出力されません。

「inner container tapped」のコードが記述されているのは、GestureDetectorとContainerを2重に入れ子にしたものの内側のGestureDetectorのonTapで表示させようとしています。
内側のContainerは何も描画していないので、onTapが反応しません。

そこで
https://github.com/matsuhiro/click_event_test/commit/8d44ed0b81a21374e5718249a3502ff4ccc0a3ac
このように透明な色を描画すれば「inner container tapped」が出力されて、ただの入れ物のContainerでもonTapを処理できるようになります。

サンプルは以下です。
https://github.com/matsuhiro/click_event_test

2019年12月14日土曜日

1人 Flutter Advent Calendar 2019:#14 qrcode


QR codeを読んだり表示したりってことがあると思います。

QRだけで検索するとreaderとgeneratorが両方引っかかります。
QR code readerもViewで大きさを変えられるものから、全画面のカメラになるものまでありました。

ただ、全体的に言えることは、ただただ簡単。ということです。
QR code readerって作るのこんなに簡単だったのかよ。。。
って思うくらい簡単です。

QR code 生成:https://pub.dev/packages/qr_flutter
QR code 読取:https://pub.dev/packages/flutter_qr_reader

が良いかなとか思いました。flutter_qr_readerの方は、サンプルアプリとか中国語でちょっと構えてしまいますが、別にコード読めばすぐ分かる感じでした。

当たり前ですが、Transformとかもきちんと動きますし、ほんとに簡単でした。


https://github.com/matsuhiro/qr_code_test
サンプルです。
カメラにアクセスするためのpermissionを取得する部分はQRコードとは関係ないけど必要なので入れました。

2019年12月13日金曜日

1人 Flutter Advent Calendar 2019:#13 storyboard

UI作っているとUIの部品を実機で見せたくもなります。
デザイナーなどに共有するために、いちいち専用アプリを作るのもだるいですし、実機で見せてコミュニケーション取りたいケースはたくさんあると思います。

そんな時にStoryboadというのが便利そうです。
https://proandroiddev.com/storyboarding-widgets-in-flutter-96d79d9a72f0

ただ部品を並べるための枠が用意されるだけなのですが便利です。

デザイナーなどとコミュニケーションするにも良いですし、エンジニアにとっても良いshowcaseになるります。


class TextStory extends Story {
  @override
  List get storyContent {
    return [
      Text('this is story sample'),
    ];
  }
}

のようにStoryを拡張したclassを作成して


class StoryBoardApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return Storyboard([
      TextStory(),
    ]);
  }
}

といあった感じでWidget作れば良いので、組み込みも楽ちんです。

サンプルは以下です。
https://github.com/matsuhiro/story_board_test

2019年12月12日木曜日

1人 Flutter Advent Calendar 2019:#12 font

Flutterでfontをカスタマイズするのはほんとに簡単です。
ちょっとpubspec.yamlに


fonts:
        - family: NotoSerifJP-Regular
          fonts:
            - asset: assets/fonts/NotoSerifJP-Regular.otf
        - family: KouzanSoushoOTF
          fonts:
            - asset: assets/fonts/KouzanSoushoOTF.otf


とかいて

           Text(
              msg,
              style: TextStyle(
                fontFamily: 'NotoSerifJP-Regular',
              ),
            ),
            Text(
              msg,
              style: TextStyle(
                fontFamily: 'KouzanSoushoOTF',
              ),
            ),


こんな感じで指定するだけです。

すごい。
文字列の描画自体はどうしているのかと気になりましたが、WebのコンテンツなどのようにPlatformViewで表示するのも良いのでは?とか思ったりもしますが、独自に
https://github.com/flutter/engine/tree/master/third_party/txt
このあたりのライブラリを利用して独自に描画しているようです。

調べといてなんですが、本やニュースなど文字そのものが商品と直結しているようなものでない限りは、フォントに関してカスタマイズするということはそんなにないかなーとは思います。

サンプルは以下においてます
https://github.com/matsuhiro/font_log_test

2019年12月11日水曜日

1人 Flutter Advent Calendar 2019:#11 webview


WebViewにもいくつかpackageがあります。
Flutterを利用しているとWebViewを利用したくなるケースというのはお知らせなどでしょうか。

アプリ開発の経験があれば、だれしもWebViewにいろいろ表示したいという要望が上がって、WebViewとChromeやSafariとの挙動の違いに苦しんだことがあると思います。

WebView自体はChromeとは違うアプリであるというのが理由ですが、WebのFrontendのエンジニアや非エンジニアからは、理解されずにバグ扱いされることもあったりすると思います。
https://flutter.ioをユーザーに提示するにあたって3パターンあると思いますが、
  1. Chromeを開く
  2. Chrome custom tabで開く
  3. WebViewで開く
ユーザーの体験で問題ないならば1がおすすめです。
とはいえ、アプリ遷移させたたくないという要望もあると思うのですが、そのときには2かなと言う感じで、どうしてもヘッダーなどをカスタマイズしたいとかがあれば3を選択するのが良いと思います。

ただ、これはエンジニア的な視点で、大体の場合は3を作ることになるのかなーとかいうのも思う所ではあります。(ログを取りたいとかJSのI/Fがほしいとか。。)
それぞれ、ライブラリがあって、
  1. https://pub.dev/packages/url_launcher
  2. https://pub.dev/packages/flutter_custom_tabs or https://pub.dev/packages/flutter_web_browser
  3. https://pub.dev/packages/webview_flutter
かなと思います。
2は、flutter_custom_tabsの方がoption設定が柔軟ですが、そんなにいじらないと思うので、flutter_web_browserで良いんじゃないかと思ったりします。


とりあえず全部使ったサンプルです

https://github.com/matsuhiro/flutter_webview_test


2019年12月10日火曜日

1人 Flutter Advent Calendar 2019:#10 flexのbaseline


FlexBoxっぽいFlutterですが、Flexのレイアウトなどの実装は何が使われているのでしょうか?
Chromeはblinkで、React nativeはYogaです。

https://flutter.dev/docs/resources/rendering
ここにあるようにFlutterでは、RenderObjectがレイアウトと描画の基本クラスのようです。
FlutterのFlexの内部をみるとcreateRenderObjectでreturnしているのはRenderFlexです。
RenderFlexにperformLayoutがあって、ここでレイアウトを決めています。
他の種類のRenderXXXでも、performLayout内部でレイアウトが決められています。
ここからもわかるようにFlutterではレイアウトの仕組みも1からDartで実装しているようです。
そうしないとWebで実行とか出来ないわけですから、当たり前といえば当たり前かも知れません。

正直、これを読んだところで何が分かるというわけでも無いかなと思います。
全体的に眺めていて、目に止まったのはbaselineの計算部分でした。

例えば、RenderFlexの中にgetDistanceToBaselineという関数呼び出しがあります。alignmentをbaselineに設定した時に位置の計算に利用されます。
Reactだと以下のように出来ます。
https://snack.expo.io/BJfcbjDsH
gの下の部分が画像やViewよりも下に来ているのが分かると思います。

このように文字と他の要素をbaselineで揃えたいという要望は普通にあると思います。

これ、Flutterでどうやるのか?

rowに素直に並べてalignにbaselineを設定すると以下のようになります。
https://github.com/matsuhiro/flex_baseline_test/commit/043dfd7f9cd73cd0e8068fddf45923b3cd94629a

全然違いますね。

Flutter自体にはBaselineクラスというのがあるので、すべての要素を囲ってbaselineを0にすればそれっぽくはなります。
https://github.com/matsuhiro/flex_baseline_test/commit/804261a3453c7a8c2c2153c0535f214c2caee9ab

baselineの値を0ってなんでしょうね。baseline関連はdocumentもすごい充実しているわけではなかったです。

baseline関連はまだ発展途上なのかもななどとも感じます。

2019年12月9日月曜日

1人 Flutter Advent Calendar 2019:#9 flexで画像をcenterに


アプリを作成しているときには、大抵の場合は、画像自体も表示してほしいアスペクト比になっているたりすると思います。
とはいえ、画像を加工したりは普通にしたくなるとは思います。
中心に合わせて拡大したり、画像全体が表示されるようにしたりなど。

その場合にFlutterでどうするのかというとImage.assetのfitにcoverを指定したりすれば簡単に出来ます。
画像の表示をするだけならこれだけで十分ですし、SVGを表示したいと思った場合も、flutter_svgを利用すれば、変数にfitがあるので、それを指定すれば十分です。

その他にやりたくなりそうなのは、Containerの背景に画像を指定しようとした場合とかでしょうか。
その場合は、BoxDecorationとDecorationImageを利用すれば可能です。

この例ではjpegを背景としてchildにsvgを表示させています。
https://github.com/matsuhiro/flutter_image_test/blob/master/lib/main.dart#L121-L136

BoxDecorationはshapeで円に切り抜きなども出来るので、やってみます。
そうするとsvgの画像がはみ出しています。

こういった時にはClipOvalなどのClipXXXを使うのが良いかと思います。
https://github.com/matsuhiro/flutter_image_test/blob/master/lib/main.dart#L154-L170
SVGも含めて全体をclipする感じです。

コードの全体はここにあります。

https://github.com/matsuhiro/flutter_image_test