Slide 1

Slide 1 text

クックパッドアプリの マルチモジュール化への取り組み こやまカニ大好き

Slide 2

Slide 2 text

自己紹介 こやまカニ大好き(@nein37) ● 技術部 モバイル基盤G ● Android テックリード ● クックパッドアプリの技術選定 ● 社内の全Androidプロジェクトの技術的なサポート

Slide 3

Slide 3 text

今日話す内容 ● マルチモジュール化とは ● なぜマルチモジュール化するのか ● クックパッドアプリにおけるマルチモジュール化 ● 現在のクックパッドアプリの状況

Slide 4

Slide 4 text

マルチモジュール化とは

Slide 5

Slide 5 text

こういうやつ :app :feature_1 :feature_2 :feature_3

Slide 6

Slide 6 text

クックパッドアプリでいうと… :app :検索 :編集 :料理きろく ※実際のモジュール構成とは異なります

Slide 7

Slide 7 text

なぜマルチモジュール化するのか

Slide 8

Slide 8 text

時代の流れ ● 新機能の開発にモジュール化が必須/推奨されている ○ Instant App ○ Dynamic Feature(Dynamic Delivery) ○ Wear OS / Android TV / Android Things ● ビルドシステムのサポートも進んでいる ○ Android Plugin for Gradle v3 から高速化 ○ モジュールの並行ビルドにも対応

Slide 9

Slide 9 text

InstantApp ● Instant App では base + feature の合計サイズに 4MB 制 限が適用されるため、アプリとコードを共有するためには feature のモジュール化がほぼ必須

Slide 10

Slide 10 text

DynamicFeature ● Dynamic Feature を実装するためには専用の設定が入っ たモジュールが必須

Slide 11

Slide 11 text

その他

Slide 12

Slide 12 text

クックパッドアプリの(旧)構成 ● ファイル数およそ 2,800 ● 総行数およそ 280,000 ● 完全なモノリシックアプリ ● 2013年から引き継がれてきた秘伝のソース ● ほとんどの箇所でレイヤーアーキテクチャ未導入

Slide 13

Slide 13 text

クックパッドアプリのビルド遅い問題 ● クリーンビルド 5〜8分 ● 差分ビルド 2〜3分 ● InstantRun がうまく動作していない

Slide 14

Slide 14 text

クックパッドアプリのビルド遅い問題 ● なぜマルチモジュールでビルドが高速化するのか ○ 変更がないモジュールの成果物をキャッシュしてくれる ○ モジュールビルドの並列実行もできる ○ Android Developersにもライブラリモジュール作れと書いてある

Slide 15

Slide 15 text

理由まとめ ● モノリシックではできないことが増えていく ● 自分のプロダクトで最新技術が試せないのは悔しい ● ビルドがとにかく遅い遅すぎる →マルチモジュール化やっていくぞ!

Slide 16

Slide 16 text

クックパッドアプリにおけるマルチモジュール化

Slide 17

Slide 17 text

最初の一歩として考えていたこと ● 新しい library モジュールを作成し、一部の機能を移す ● app モジュールに library モジュールを参照させる ● これを繰り返せばマルチモジュール化できるぞ ● 簡単なところからコツコツ切り出していこう!

Slide 18

Slide 18 text

つまりこう :app :app :feature_1 :feature_2

Slide 19

Slide 19 text

実際にやったこと ● まずは library モジュール(※)を作成し、全ての機能を移 す ● app モジュールに library モジュールを参照させる ※ legacy モジュールと呼んでいる

Slide 20

Slide 20 text

つまりこう :app :legacy :app

Slide 21

Slide 21 text

実際に出来上がったもの ● 4日間かけて巨大なPRを生成(初回は失敗) ○ File Changed 3,820 ○ +100,025 ○ -99,572

Slide 22

Slide 22 text

なぜそんなことをしたのか ● アプリモジュールが大きいままだと細かく機能を切り出すモ チベーションが生まれない ● 巨大なライブラリモジュールを作ることで上層、下層両方を モジュールに切り出しやすくなると考えた ○ legacy モジュールに依存させておけば上層のモジュールも切り出しやすく なるのでは?

Slide 23

Slide 23 text

こうしていきたい :legacy :app :legacy :app :feature_1 :feature_2 :ui :common

Slide 24

Slide 24 text

マルチモジュール化爆発ポイント ● DataBinding が爆発 ○ AGP 3.2 beta にして解決(v2 でも良さそう) ○ ライブラリモジュールの application ID は必ず別のものにする ● アプリバージョンや BuildConfig への参照が爆発 ○ app module 側の定義は legacy から参照できない ○ legacy 側で Interface を定義して app 側で実装を注入 ○ BuildConfig への依存は減らしていったほうが良い ● test / androidTest が爆発 ○ 上記のアプリパラメータ Interface を Mock したりいろいろ ● Fabric など一部のライブラリが爆発 ○ CustomApplication クラスや application ID に強く紐付いた処理は app 側に持ったほうが良い

Slide 25

Slide 25 text

成果 ● 差分ビルドが爆速化 ○ 差分ビルド時間が 3分 → 30秒 ○ InstantRun もまともに動作するようになった ○ マルチモジュール化の前に行った flavor / buildType 整理の効果もある

Slide 26

Slide 26 text

現在の状況(マルチモジュール化からおよそ1ヶ月)

Slide 27

Slide 27 text

現在は ui モジュールも分割済み ● 現在は ui モジュールも分割済み ○ ui -> library -> app という構成 ○ アプリ全体のデザインリソースを整理しつ つ移動 ○ 汎用 CustomView も移動 ● 画面毎のデザインリソースは ui に は含めない ○ module のビルドキャッシュが有効になる 範囲で考える :legacy :app :ui

Slide 28

Slide 28 text

依存定義を buildSrc + Kotlin で記述 ● buildSrc ディレクトリにソースを置くと自動的にコンパイル して build.gradle で読めるようにしてくれる ● buildSrc の中身は Kotlin で書ける

Slide 29

Slide 29 text

依存定義を buildSrc + Kotlin で記述 ● dependencies で利用するときに補完してくれる ● 参考記事

Slide 30

Slide 30 text

legacy からの切り出しはまだまだ進行中 ● InstantApp や DynamicFeature 導入はまだまだ遠い ● 現在は認証・通信周りを切り出す作業中 ● 各機能へのレイヤーアーキテクチャ(VIPER)導入も進行 中

Slide 31

Slide 31 text

ビルド周りの最適化も進行中 ● まだ並列ビルドがうまく動いていない ● AppBundle によるリリースなどもこれから ● ビルド周りだけでも改善できるところはいっぱいありそう

Slide 32

Slide 32 text

まとめ

Slide 33

Slide 33 text

まとめ ● クックパッドアプリはまだマルチモジュール化の最初の一歩 を踏み出した段階 ○ 最初の一歩は大きく踏み出したほうが楽しい ● ビルド時間は本当に高速化したので良かった ● これからもどんどんモジュール切り出し&ビルド高速化して いくぞ!