【DroidKaigi 2017】大規模アプリのリノベーション
発表者
- Ryo Kitamura
- hatena
大規模なアプリとは?
- はてブ クライアント
リファクタリングしたい
- 単純にコードがあ大きい + 設計が統一されていな
- 将来のセキュリティが心配
- 片手間でやっていた頃もあった
- 設計を十分に撮る時間がなかった
- 置き換え切れない!
- リファクタリングに専念する期間が必要
- リノベーション
ドメイン知識の獲得
画面を知る
- 歴史とと主に画面が増えた
- どの画面から起動され、どんな画面が出るかを知る
- 外部アプリから起動されたとき用の画面
- ログインしていると内容が変わる画面
- エラー時の画面
- スクリーンショット撮りまくって
Graphviz
で繊維を可視化- 大きすぎるので紙に印刷してみんなで見た
- 画面の詳細を詰める
- 画面名
- 本来の適切な名前はこうじゃないか?
- Model
- 本当はこういう名前じゃないか?
- View
- 画面名
- 画面情報をドキュメント化
- githubにあげて検索できるようにする
デザイン意図の確認
- 画面一覧はデザイナも見る
- 各部のデザインの理由を知る
- 必要ないところは削る
- 準備の段階として必要
- よく見ると似たものばかり、時間のフォーマットが違う…
- でも理由はある
- 理由を知っていくことで、各Viewに名前をつけていくことができる!
設計
- ライブラリ選定
- アーキテクチャの決定
- サンプルアプリの作成
- ドキュメント作成
- 組み込む
ライブラリ選定
- 使っても良さそうというのをあげていく
- 設計で変わるため各地絵するのが目的ではない
- とにかくあげまくる
アーキテクチャの決定
サンプルアプリの作成
- 出来上がった設計を試す & 修正
設計
主なライブラリ
- Dagger2
- Realm
- Retrofit2
- …
主なレイヤー
- MVVM
前提
- 下のレイヤーは上のレイヤーは知らない
- レイヤーの処理を外に漏らさない
- 下のレイヤーが上のレイヤーに結果を伝える時はObserbableを使う
- Dagger2でinjectする
- インスタンス生成
- 楽
Repository
- EntryRepositoryならEntryに関わる処理を担当する
- Interfaceとその実装を用意する
- テストが用意
- Repositoryを提供するDaggerのModuleを同じパッケージにもつ
Interactor
- 内部にRepositoryを持つ
- 必ずRxで返す
- 変更可能な状態を持たない
- キャッシュなどの役割はRepository
- スレッドを決定する
- 最後には必ずメインスレッドに戻す
- Interactorを組み合わせない前提の設計
ViewModel
- 内部にInteractorを持つ
- ViewはViewModelのことを知っている
- ViewModelはViewを知らない
- Activity FragmentもViewとみなす
- 内部に通知用Observableを持つ
- 状態が変わると通知
- Databindingで自身がLayoutoにセットされることも想定
- (ある程度は) 使い回される前提
ViewModelの回想
- ViewModelは階層を持つ (ことがある)
ViewModel Navigator
- 繊維を表すクラス
- ViewModelの中で作らず、外部から渡される
- onClick自党の繊維で使われる
設計のドキュメント化
- 作る前に攻勢をドキュメント化するう
- 人の入れ替わりに備える
- 設計をブレさせない
- この設計になった理由も書く
- 納得してもらうため
- 概要、説明、サンプルコード、規約…
着手
- 進め方
- 画面毎にタスクを切る
- ひとつ完成するのに時間がかかる
- 見積もりにくい、分担しにくい
- Repository -> Interactor -> Videmodelと進めていく
- 画面毎にタスクを切る
- 置き換えかた
- いきなり全部変更しない (破綻する)
- RxJava2かは後回し (簡単ならやる)
- 移行用パッケージに一時的なクラスを作る (移行後に消す)
- Componentも少しずつ移動してく
リリース
- 1、2週間ごとに様子を見てやる
まとめ
- 着手前にドメイン知識を得る
- レイヤーごとに分けて下からやっていく
- 見積もる
- 長くても2週間ごと
- 設計はプロダクトによって千差万別
- 良い設計を部分的に取り入れる
- 完璧にするのは困難なので妥協点を見つけてやっていく