Flutter 限られた期間の中、未経験者込みチームでリリースするために使用したアーキテクチャと解説
初めに
- 仕事で限られた期間でリリースするために作成したテンプレートプロジェクトがあったが、特に何か発表とかも出来ず放置されてた
- ちょうどFlutter大学のアドベントカレンダーがあったので供養するかとなった
- 実際に使用したものは都度アップデートされていいようになった気はするものの、こっちは全くメンテもしてないので今見たらおかしいところもあるかもしれない
- メンテする気力もないので多少大目に見てください😅
- 技術というよりはメンタル寄りの話になります
という感じです。
使ったテンプレートがこちら
気を付けたところ
- とにかくわかりやすく作る
- ルールをしっかりと定めてやりたいことに対するアンサーを用意してあげる
- page,screen,screenEntityに責務を分ける事でチーム開発を容易にする
- 各開発者のレベルに合わせた仕事を振る
- 全て自分が尻を持つつもりで設計・開発・実装を行う
とにかくわかりやすく作る
未経験者込みなども関係なく大事な話になってくると思うのですが
とにかくわかりやすく作ることは非常に重要です。
かのGoogleもこのように言っています。
優れたコードを書くことは、コードがコンパイルされたり、テストのカバレッジが100%に達したりしても終わりではありません。 コンピューターが理解できるものを書くのは簡単ですが、人間とコンピューターの両方が理解できるものを書くのはずっと難しいのです。 Code Healthを意識したエンジニアの使命は、まず人間のために書き、次にコンピュータのために書くことです。
※こちらから引用したものを雑に翻訳したもの
せっかく優れたコードであってもコメントが足りずに人間にとってわかりにくい状況であったり
テクニカルに書きすぎてメンテする側の人間が理解できないと本末転倒と自分は解釈しています。
その他詳しい内容をまとめてくれている記事があったのでリンクを置いておきます。
ルールをしっかりと定めてやりたいことに対するアンサーを用意してあげる
今回私が作ったテンプレートではどのように対応したかというと、
- プロジェクト内にしっかりドキュメントを作成する
- コードのベースとなる箇所にはサンプルコードもセットで用意する
というようなところを意識しました。
では実際どのような方法をとったかというと
1.のアプローチとしてreadmeの拡充を努めました。
基本的にreadmeさえ見れば全部わかるような形に書くことが理想としており
- makefileなどのスクリプトルール
- 開発環境・環境構築方法
- ログ出力
- アーキテクチャ
- 参考資料
- GitFlow
- プルリクエスト
というような項目を用意しました。
更に各項目のより詳しい内容についてはdocumentディレクトリを作成し、
この中により詳細な内容ドキュメントを作成してreadmeからリンクで飛べる形にしました。
これにより困ったことに対する答えが簡単且つ明確に用意することができたのかなと思っています。
また、
開発環境については環境問題でバグが起きてしまうことも無くしたかったので
VSCode以外禁止というアプローチも取りました。
結果環境周りでのバグは起きなかったですが
経験者のみで開発する場合などはそれぞれ好みなどもあると思いますし、
ここまでのアプローチは難しいと思います😅
2.としてはこのようにテンプレートサンプルを用意して
このような形で作れば大丈夫だよーという例を作成するようにしました。
(実際はここに色々なパターンが増えたりしたようなイメージをしてもらえればと思います😅)
また、
コードのアプローチとしては親配下にグローバルなローディングインジケータを用意し、
loadingStateUpdater()にriverpodを突っ込めばよしなに更新してくれる形をとり
Riverpod周りの複雑性を吸収させる形を取りました。
実際のコードは以下です。
こちらはあくまでわかりやすさを重視するためにとったアプローチで
未経験者がいないのであればやらない方が良かったと思います😅
理由としてはわかりやすさを重視してloadingStateUpdaterを作成したものの
loadingStateUpdater起因のバグも発生する要因になるので
もう少し時間があれば普通にRiverpod使ったと思います。
この辺は反省ポイントでもありますね......
page,screen,screenEntityに責務を分ける事でチーム開発を容易にする
こちらは主にpresentation層の話になるのですが、
宣言的UI時代の今、明確にこうやった方がいいというような
ベストプラクティスが完全に定まっているわけではないというのが大きいと思っており、
まずはここのルール決めを明確に決めることで開発を容易にすることにしました。
どういう形で責務分担させる形にしたかというと、
-
page
- 画面の基幹となるコンポーネント
- AsyncValueなどのProviderを集約するStateHolderのような役割
- ViewEntityに情報を詰めてScreenに橋渡しする
-
screen
- 静的なUIコンポーネント
- screenはscreenEntityのみの引数を持ちscreenEntityから動的な情報を受け取る
- 引数をscreenEntityのみにすることでUIの引数が山のようになってしまうことを防ぐ
-
screenEntity
- pageとscreenの橋渡しするクラス
- screenの情報が集約されているのでバリデーションロジックなども持つことができる
-
usecase
- UIが持つusecase
- Riverpodで作られている
- 画面が持つusecaseはpageに集約させる
というような形で責務分担をしている。
このように責務分担することで
- UI作成担当はUI作成に
- ロジック担当はusecaseやscreenEntityでロジック作成に
- UIとロジックが完成すればそれをpageで繋ぎこむ
という形でそれぞれがやりたいことに集中しやすくなっています。
また、
責務が明確に分離されていることによって各テストも容易な構成になっています。
各開発者のレベルに合わせた仕事を振る
これもまぁ当たり前の話ではあるのですが、
今回は特に期限が限られている中でやり切る必要があったので
- 初学者
- 主にUI作成を担当
- 簡単な画面から画面を作ることに慣れてもらいFlutterのUI開発を知ってもらう
- 中級者
- API周りの開発を担当
- Riverpod周りの学習を主にやってもらう
- 上級者
- 全体設計・レビュー・補助・開発リードを担当
- 初学者の補助も担当してこぼれ球を拾っていく
という形でそれぞれの役割を最初に設定
役割以外の仕事もやらないとみんなつまらなくなってしまうと思うので
余裕が出たらできる範囲で他の仕事もやってもらうなどももちろん行ってました。
全て自分が尻を持つつもりで設計・開発・実装を行う
ここが重要ではあるのですが特に潤沢な状態ではない開発をやり切るには
自分が全て終わらせるという意気込みが大事です。
そんなん無理じゃん!!!
って思うかもしれないですが
土台が無理ゲーの場合ある程度のパワープレイは必要になりますし、
それ以上に潰れないメンタルが大事になってきます。
なので
- 現状の状態で終わらせるにはどうすればいいかを考える
- 自分は絶対に潰れないこと
- タスクを先回りして振り続け、絶対にエンジニアの手を止めないようにする
- 要件定義も全部前もって終わらせてエンジニアには開発にのみ集中してもらう
- ガントチャートも開発スタート時点で全部振り切ってしまい、全体に大まかな流れを周知しておく
あとはとにかくみんなで頑張るしかないので頑張りましょう。
意外となんとかなるもんです。
あとはチーム内で気軽に質問しやすい空気作りとか
できるだけ楽しく開発できる環境作りとかそういうのも大事ですが
言い出すとキリがないのでその辺はチーム開発論とか色々あると思うので
色々書籍とか読むのもいいかもしれません。
終わりに
というわけでテンプレートの供養と
どういうことを大事にして開発してたかの解説でした。
限られたリソースでどうにかやりくりするのはあるあるだとは思うので、何かの参考や誰かの役に立てば幸いです。
Discussion
🍏