Slide 1

Slide 1 text

Androidアプリをいつまでも楽しく開発 し続けるための取り組み Cookpad.apk #4

Slide 2

Slide 2 text

自己紹介 こやまカニ大好き(@nein37) モバイル基盤部所属 社内全Androidプロジェクトの開発効率化と技術サポート minSdkVersion 上げたりモジュール分割したりしてます 2

Slide 3

Slide 3 text

android-cookpad アプリのこ れまでの歩み 3

Slide 4

Slide 4 text

2012年にAndroidアプリをリリース ● 一つのチームでアプリを開発 ● 当初はほぼWebViewで構成されたアプリ ○ コンテンツの更新や新機能をすばやくユーザーに提供することを目的としていた ○ 探すと当時のインタビュー記事が出てくる ○ https://el.jibun.atmarkit.co.jp/rails/2012/10/html5-d1ba.html ● JavascriptInterface を利用 ○ Javascript からネイティブ実装を呼び出すための仕組み ○ この時入った仕組みの一部はいまだにクックパッドアプリで利用されている ● 課題 : WebViewによるテスト、不具合検知の難しさ 4

Slide 5

Slide 5 text

2014年にフルリニューアル ● ネイティブアプリとしてリニューアル ● ネイティブ実装によるユーザー体験の向上、メンテナンス性の向上 ● 当時は Android Developers の実装ガイドなどが充実していなかったため、 書いた時期や開発者によって実装スタイルがバラバラ ● このころまでは一つのチームで開発を行っていた ● 課題 : いつ/どの機能がリリースされるのか周知することが難しい 5

Slide 6

Slide 6 text

モバイル基盤誕生 ● 各部署のメンバーが担当する機能の開発を行う方式へ ● CI整備やリリース作業などどの部署にも属さない役割のカバーや全体的な効率 化のためにモバイル基盤グループが誕生 ● アプリの状態監視や各機能のバグ修正も行っていた ● 課題 : リリースごとに各部署の調整が必要になっていて高コスト 6

Slide 7

Slide 7 text

フルリニューアル後リリースフローを整備 ● アプリの運用ルールを整備  ○ 2週間毎のリリース ○ 開発・テスト・リリース後監視フローの整理 ○ リリーマネージャ・監視の手順化・持ち回り ● 課題:各施策・各部署の連携と開発リソース調整 7

Slide 8

Slide 8 text

モバイル基盤の役割の明確化 ● モバイル開発に関する課題を解決する部署へ ● バグ調査やリリースまわりの調整から開発しやすさの向上へ ● Danger などのコードレビュー負荷軽減 ● CI・開発環境の改善 ● ビルド時間の計測・改善に向けた努力 ● リリースに関する負荷の軽減 8

Slide 9

Slide 9 text

楽しいAndroid開発#とは 9

Slide 10

Slide 10 text

Androidアプリの開発 ● ユーザーに価値を届けるための開発 ● 最小のコストで機能開発/バグ修正を行う ● 最小のコストでユーザーの手元に届ける ● コスト=時間+手間 10

Slide 11

Slide 11 text

時間がかかると楽しくない ● ビルド時間が長い ● CIの待ち時間が長い ● 変更がマージされてから リリースまでの時間が長い 11

Slide 12

Slide 12 text

● コードをどこに書けば良いのかわからない ● コードをどう書けば良いのかわからない ● 認証処理・ユーザー状態の判定が難しい ● 古いJavaコード触りたくない ● 意味不明なビルドバリアント 手間がかかると楽しくない 12

Slide 13

Slide 13 text

モバイル基盤部の役割 ● 時間と手間を最小限にするために取り組む ● アプリ開発を魅力的なものにする ● ユーザーに新しい価値を 素早く届けられるようにする ● モバイル基盤部の目標にも「生産性について」 という項目があり、機能開発にかかる時間を 最小化することを明確に目標にしている 13

Slide 14

Slide 14 text

実際の取り組み(時間) 14

Slide 15

Slide 15 text

ビルド時間の削減 ● ビルドの時間が遅いと全てが遅いので優先度は高い ● まずは測定するところから始める ○ ビルド時間を可視化できると成果がでたときにも嬉しい ● 差分ビルド時間の最小化にフォーカスする ○ 開発者の手元の作業によって大きく変動するので細かい数値は追わないほうが良い ○ 一定期間の傾向としての増減で見ている 15

Slide 16

Slide 16 text

ビルド時間の削減 ● ビルド時間を短くするためにできることは公式に書いてある ○ https://developer.android.com/studio/build/optimize-your-build ● モジュールを分割してキャッシュを有効利用する ○ Gradleキャッシュへの理解を深める ● Apply Changes がまともに動くようにする ○ https://developer.android.com/studio/run#apply-changes ○ 使えない場面のほうが多いが使えたほうが良い場面はもちろんある ○ debug build variant がまともに動くようにする 16

Slide 17

Slide 17 text

ビルド時間の削減 ● minSdkVersion を上げる ○ 過去のOSバージョンをサポートするためにやっている処理が不要になるビルド時間を短縮 ○ 特に minSdkVersion 21 未満の場合に有効 17

Slide 18

Slide 18 text

ビルド時間の削減 ● PCのスペックを上げる ○ モバイル開発者は全員 MacBook Pro ○ CPU 2.4GHz 8コア/RAM 32GB ○ 実際の計測結果などを Gradle build scan で 記録に残しつつ必要スペックを決めている ○ 検証手順もきちんと残す 18

Slide 19

Slide 19 text

ビルド時間の削減 ● ビルド時間の改善は影響の大きそうなところから崩していく ● 後はひたすらモジュール分割とGradle/Gradle Plugin の改善についていく ● アプリの仕様やマシンの見直しも必要ならやっていく 19

Slide 20

Slide 20 text

CI待ち時間の改善 ● 最近 CodeBuild に切り替えた ○ https://techlife.cookpad.com/entry/2020/01/30/100000 ● CIビルド時間はまだ改善の余地がありそう ● ジョブの分割によって問題のある箇所がわかりやすくなった 20

Slide 21

Slide 21 text

リリース待ち時間の改善 ● 毎週リリース ○ これまでは重要な施策がある場合そちらを優先して スケジュールを調整していたため、 実際にリリースされるタイミングは不透明だった ○ https://techlife.cookpad.com/entry/2018/09/14/090000 ● リリースフローの(半)自動化 ● 問題発生時のフロー整備 ○ 緊急リリースorリリーススキップの判断基準 ○ 実際の緊急リリース作業のドキュメント化 21

Slide 22

Slide 22 text

実際の取り組み(手間) 22

Slide 23

Slide 23 text

アーキテクチャ/コードベースの改善 ● 無法状態(+若干のMVP) -> VIPER ○ 現在画面のおよそ35%がVIPER化されたコード ○ サンプルコードを含むドキュメントを整備 ● 既存画面のVIPER化よりも共有コードの改善を優先 ● Kotlin 化は昨年後半でかなり進み現在半分以上が Kotlin 23

Slide 24

Slide 24 text

レガシーコードの改善 ● DIの(再)導入 ○ 以前 Toothpick を導入していた ○ Toothpick のコード生成が失敗することがあった ○ (特に)シングルトンインスタンスの管理が分散 ● KOINを導入 ○ これまでのシングルトンインスタンス管理もすべて DIに寄せる ○ DIの利用方法・モジュール分割時の記述方法をドキュメント化 ○ 新規のコードではKOINの利用を推奨(レビュー時の指摘/お手本PR) 24

Slide 25

Slide 25 text

レガシーコードの改善 ● 認証・通信処理の改善 ○ 最初は認証モジュール・通信モジュールで分離していた ○ 通信途中での再認証など特殊な処理が多いため、認証・通信モジュールにした ○ Kotlin の internal と組み合わせて可視性を最適化 25

Slide 26

Slide 26 text

レガシーコードの改善 ● アプリケーション初期化処理の改善 ○ ApplicationInitializer というクラスがアプリ内の初期化処理を行っていた ○ シングルトンインスタンスの初期化など処理順を意識する必要があった ○ 「depends on XXX」 という真偽不明のコメントにより触れない処理たち ● 初期化処理を KOIN で行えるものは KOIN で行う ● 無理なものはきちんとカテゴリごとに整理してこまかくコメント 26

Slide 27

Slide 27 text

レガシーコードの改善 ● その他の取り組みなど ○ Cookpad.apk や 技術ブログで随時共有しています ○ https://techlife.cookpad.com/entry/2019/10/21/144205 ○ https://techlife.cookpad.com/entry/2020/01/16/090000 ○ https://cookpad.connpass.com/event/137772/ 27

Slide 28

Slide 28 text

リリース デバッグ ビルドバリアントの整理 ● モジュールによる設定解決 ○ 接続先設定などのモジュール化 ○ デバッグ機能のモジュール化 ○ モジュールの依存解決によって アプリの設定・機能の切り替えを行う ● 実装方法は2種類 ○ 同一パッケージ/同一クラスにコードを配置 ○ インターフェイスを共通モジュールにおいて 実装だけを切り替える 28 App_Release App_Debug Feature_Debug Feature_Release Settings_Release Settings_Debug Settings_Base Libraries Features

Slide 29

Slide 29 text

まとめ 29

Slide 30

Slide 30 text

まとめ ● アプリ開発にかかる時間と手間を最小化することで 楽しく開発を続けることができる ● クックパッドではモバイル基盤が業務として 時間と手間を最小化に取り組んでいる ● これからも引き続きユーザーに価値を届けるための開発を サポートしていく 30

Slide 31

Slide 31 text

おまけ 31

Slide 32

Slide 32 text

minSdkVersion 23 のお知らせ ● クックパッドアプリでは3月からminSdkVersion を 23 にします ○ AppCompat v1.1.0 が 5.x 端末でクラッシュする問題 ○ 5.x で `android:foreground` 使えない問題 ○ Drawable への tint 適用時の挙動などが 5.x で異なる問題 ○ Samsung 5.x 端末での kotlinx.coroutines クラッシュ問題 など 32