アプリケーションエンジニアの id:funnelbit(北村) です。先日 DroidKaigi 2017 で「大規模アプリのリノベーション」というタイトルで発表させていただきました。
大まかな内容としましては以下のようなものです。
1. ドメイン知識を得る
まずは現状のアプリケーションの解析からスタートします。実装済みの画面を洗い出し、現状を把握します。各画面や View に正しい名前付けを行います。
2. ライブラリと設計を決定する
次にライブラリ、設計を決定します。はてなブックマークの Android 版では MVVM を採用しています。また Repository, Interactor, ViewModel, View といったレイヤー分けを行っています。この設計につきましては様々な議論があるところかと思います。これが唯一無二のものであると主張するつもりは毛頭ありません。ただし現状では、この設計でうまく開発していくことができています。必要なコードはスライドにすべて書いてありますので、興味のある方はぜひご覧ください。
3. サンプルアプリケーションの作成
設計がある程度確定したら、サンプルアプリケーションを作成します。このアプリケーションは、API を叩いてそれをリスト表示するといった流れを表した、小さなアプリケーションです。時間がなくて発表できませんでしたが、実際はログイン状態によって UI を変更したり、Realm を盛り込んでみるなどの試行錯誤もここで行っていました。
サンプルアプリケーションは github 上で管理します。設計に問題があれば、プルリクエストで修正します。その際、ドキュメントの修正も合わせて行います。
4. 設計のドキュメント化
次に設計をドキュメント化します。いつでも最新の設計情報を見れるように配慮します。こうすることで設計をぶれないものとします。また今後引き継ぎがあったとしてもドキュメントがあれば比較的スムーズに対処できるはずです。
5. 着手
ドキュメント化が完了したら、実際にリファクタリングを進めていきます。作業の流れとしてはレイヤーの最も下の者から順番に進めていきます。つまりまずは Repository を一通り作成し、次に Interactor を、その次に ViewModel を、といった具合です。
コードの置き換えは必ずステップごとに行うようにします。例えば Repository が RxJava2 を使っているが、Repository を利用したいクラスの内部が RxJava1 だった場合、一時的に Repository に RxJava1 用メソッドを生やす事が考えられます。Dagger2 の Component を移行したい場合も同様で、いきなり新 Component で inject することはせずに、新 Component にゲッタを生やし、旧 Component 利用クラスは 新 Component のインスタンスを受け取り、ゲッタ経由で必要なインスタンスを受け取れるようにしておきます。
着手する時はまず見積もりを行うようにし、何時までに完了するのかを明確にします。もしも見積もりをオーバした場合、なぜそうなったのかを分析し、改善して次のイテレーションに進みます。
6. リリース
リリースは1〜2週間毎に行うようにします。問題が発生したときに原因究明をやりやすくするためです。タスクの見積もりもこのリリースサイクルを基準に行われます。
まとめ
こうしてみると、準備に相当な労力を割いている事がお分かりいただけるかと思います。実際に準備にはかなりの時間を掛けており、傍から見ると過剰にも映るかもしれません。しかし大きなアプリケーションに手に入れるには、これぐらいの準備が必要なのだと思います。実際に綿密な準備をしたことによって、スムーズにリファクタリングを進めることができています。
ドイメイン知識獲得や、設計の確定をチーム全員で行ったのも正解でした。みんなで模索した結果なので、誰もが自信を持って進めていくことができます。
リノベーションはまだ道半ばなので、完了するまでこの方針が本当に正しかったのかは分かりませんが、きっとやり遂げられるのではと感じています。そして新しいコードベースをもとにして、今後のアプリの成長に繋げれていけたらなと思います。