$30 off During Our Annual Pro Sale. View Details »

cookpad.apk#5

Kyohei Kato
June 24, 2020
430

 cookpad.apk#5

Kyohei Kato

June 24, 2020
Tweet

Transcript

  1. クックパッドアプリに
    おける DI の歴史
    @ksfee684

    View Slide

  2. 自己紹介
    ● 加藤 恭平(@ksfee684)
    ● モバイル基盤部所属
    ● Android アプリプロジェクトの開発効率化、基盤技術開発

    View Slide

  3. ● クックパッドアプリの DI フレームワークの変遷
    ● クックパッドアプリにおける各 DI フレームワークの解説
    ○ 選定理由
    ○ 利用方針
    ■ フレームワーク移行に伴った変更
    アジェンダ

    View Slide

  4. 今日はなさないこと
    ● DI フレームワーク利用方法の説明
    ● DI フレームワークの必要性
    ● DI フレームワークごとの比較
    ○ 選定理由で少し出てきますが、全体通して比較はありません

    View Slide

  5. DI フレームワークの変遷
    RoboGuice
    (? ~ 2018)
    Toothpick
    (2018 ~ 2019)
    KOIN
    (2019 ~ 2020)
    Dagger
    (2020 ~)
    移行を担当
    見直し
    見直し

    View Slide

  6. RoboGuice (?~2018)

    View Slide

  7. RoboGuice
    ● https://github.com/roboguice/roboguice
    ○ Google Guice をAndroid に転用したもの
    ● リフレクションベースの DI フレームワーク
    ● 恐らくクックパッドアプリに入った最初の DI フレームワーク

    View Slide

  8. 利用方針
    ● 主にインスタンス生成を省略するために利用
    ● Activity や Fragment から値を注入
    ● DI フレームワークの利用ルールはなく、開発者の裁量にあわせて利用
    ○ 複雑に絡み合うオブジェクトの依存関係

    View Slide

  9. RoboGuice の課題点
    ● 当初はリリースされるはずであった RoboGuice4 に乗り換える予定だった
    ● 雰囲気が怪しくなり乗り換えを考え始める

    View Slide

  10. Toothpick (2018~2019)

    View Slide

  11. Toothpick
    ● https://github.com/stephanenicolas/toothpick
    ● アノテーションプロセッサを利用した DI フレームワーク
    ● 依存グラフを持つ Scope が木構造のような親子関係を持つ
    ○ ApplicationScope, ActivityScope

    View Slide

  12. Toothpick の選定理由
    ● 移行にあたって利用方針の見直しは行われないことに
    ● 乗り換え先として Dagger, Toothpick が上がる
    ○ 元々 RoboGuice を上手く活用できておらず、 Dagger の複雑さと学習コストに対して得られるも
    のが少ない
    ○ 縦横無尽な利用方法を整備する上では Dagger の方が強制力がある
    ○ Toothpick の方が移行が容易
    ● 構造がシンプルで移行が比較的容易な Toothpick を選定

    View Slide

  13. Toothpick の課題点
    ● アノテーションプロセッサを利用するようになりビルド時間が増加
    ● 移行当初 Toothpick がまだ発展途上で不安な箇所がいくつかあった
    ○ アノテーションプロセッサによるコード生成

    View Slide

  14. KOIN (2019~2020)

    View Slide

  15. KOIN
    ● https://github.com/InsertKoinIO/koin
    ● Kotlin ベースのジェネリクスと Delegated Properties を利用した DI フレームワーク
    ● 依存グラフは実行時に Map 上で構築される
    ○ Lazy Properties として Map に対してオブジェクトをリクエストする

    View Slide

  16. KOIN の選定理由
    ● アノテーションプロセッサを利用しない DI フレームワークを探し始める
    ○ 移行の容易さ、DI フレームワークの利用の見直しも同時に行う
    ● KOIN, Kodein, Dagger が候補に上がる
    ● 導入のしやすさが決め手に
    ○ 巨大な Map 構造を築くだけで、初学者にも理解しやすい
    ○ パフォーマンス面も申し分なし
    ○ アノテーションプロセッサによるコンパイル時間の増加を回避できる
    ○ Kotlin コードが拡充しつつあった

    View Slide

  17. 移行に合わせた利用方針の見直し1
    ● Toothpick 移行時に先送りになっていた利用方針の見直し
    ○ 複雑に絡み合っていたオブジェクトの依存関係を整理
    ○ VIPER + レイヤードアーキテクチャ上で DI フレームワークを活用する
    ■ マルチモジュールも意識した構成に

    View Slide

  18. オブジェクトの依存関係の整理
    ● 単純にオブジェクト生成を省略していたものは DI フレームワークの利用をやめる
    ○ DI フレームワークを利用するオブジェクトのルールを設定
    ● 縦横無尽に注入される Context をやめる
    ○ ApplicationContext? ActivityContext?
    ● xxHolder の削除
    ○ シングルトン制約を DI フレームワークが担うように

    View Slide

  19. VIPER + レイヤードアーキテクチャにおける利用
    ● VIPER + レイヤードアーキテクチャの上で扱うオブジェクトの生成を DI フレームワークを介して行うよ
    うに
    ● オブジェクト間はすべてインタフェースを介して会話
    ○ オブジェクト生成をすべて任せることで、実体を知らずに済むように
    ○ テスト実行時にオブジェクトのすり替えが可能に

    View Slide

  20. RecipeDataSource
    VIPER + レイヤードアーキテクチャにおける利用
    ServerRecipeDataSource
    RecipeContract.View
    RecipeActivity
    RecipeContract.Interactor
    RecipeInteractor
    RecipeContract.Presenter
    RecipePresenter
    RecipeContract.Routing
    RecipeRouting
    VIPER
    レイヤード
    アーキテクチャ

    View Slide

  21. RecipeDataSource
    VIPER + レイヤードアーキテクチャにおける利用
    Mock
    RecipeContract.View
    RecipeActivity
    RecipeContract.Interactor
    RecipeInteractor
    RecipeContract.Presenter
    RecipePresenter
    RecipeContract.Routing
    Mock
    VIPER
    レイヤード
    アーキテクチャ

    View Slide

  22. KOIN の課題点
    ● 依存グラフが不十分でもコンパイル時に気づくことができない
    ○ リリース後に Crashlytics で実行時エラーに気づく
    ○ 開発者がアプリ実行まで問題に気づけず生産性が落ちる
    ● クックパッドアプリと Scope の相性が悪い
    ○ ライフサイクルとのひも付きが不十分

    View Slide

  23. Dagger (2020~)

    View Slide

  24. Dagger
    ● https://github.com/google/dagger
    ● アノテーションプロセッサを利用した DI フレームワーク
    ● Google によってメンテナンスが行われている Android 公式フレームワーク

    View Slide

  25. Dagger 選定理由
    ● 課題を解決するために残された最後の手段
    ○ コンパイル時の依存グラフチェック、依存注入タイミングの改善
    ● KOIN 導入段階で利用方針を整理したため Dagger の機能を活用できるようになった
    ● Hilt の導入
    ○ 移行開始当初存在を知らなかった

    View Slide

  26. 移行に合わせた利用方針の見直し2
    ● KOIN で自由に依存注入していた箇所をなくす
    ○ エントリーポイントを Activity, Fragment, Service, BroadcastReceiver に限定
    ○ グローバルな値として参照していた箇所を排除

    View Slide

  27. View Slide

  28. そして次の時代へ…

    View Slide

  29. Dagger Hilt
    ● 実は移行を進めているタイミングで知らなかった …
    ● 更にアノテーションプロセッサによるコードジェネレーションが強まる
    ○ アノテーションだけつければ良くなる時代へ
    ○ 初学者の学習コスト軽減
    ● クックパッドアプリを題材に移行を試みたブログを書いたのでよければ
    ○ https://ksfee.hatenablog.jp/entry/2020/06/17/033304

    View Slide