DroidKaigi 2022 で気になるセッション

こんにちは。with で Android エンジニアをしている @maxfie1d です。 今年も DroidKaigi の季節がやってきました!ということで本記事では with の Android チーム的に気になるセッションを紹介したいと思います。

DroidKaigi とは

DroidKaigi はエンジニアが主役の Android カンファレンスで、2015 年から毎年開催されています。近年はオンライン開催が続いていましたが、今年はオフライン会場があります。 with からは @maxfie1d が参加します。

当日は恐らくこんな感じの名札を提げているはずです。

Android エンジニア3年目にして今年初めてプロポーザルを出しました。悔しいことに採択には至りませんでしたが、また来年チャレンジしたいと思います(過去には with のエンジニアが登壇したことがあります)。

また DroidKaigi では毎年公式アプリが公開されています。こちらは OSS になっていて、その年ごとの最新の技術が目白押しなので非常に勉強になります。私は以下 2 つの Issue でコントリビュートさせていただきました。

github.com

github.com

play.google.com

DroidKaigi は非常に実践的で内容が充実しているので、アーカイブ配信後には参加しなかったメンバーを含め Android チーム全員で視聴するようにしています(ウォッチパーティーと呼んでいます)。

気になるセッション

タイムテーブルを見て、気になるなと思ったものをまとめました。(順序は開始時刻順です。)

Jetpack Compose で Material Design 3 (Yuki Anzai)

with では 記事執筆時点で Material 2 を使用していますが、近々 Material 3 の Compose 実装が Stable になれば具体的な移行計画を検討する予定にしています。本セッションで Material 3 の知見を増やせればと思います。

「アプリのブランドカラーを保持しつつ Dynamic Color に対応する方法」が特に気になっています。

droidkaigi.jp

Prepare your project for KMM (Oussama Ben wafi)

近年身近なプロダクトでも KMM(Kotlin Multiplatform Mobile)Flutter が採用されるようになり、マルチプラットフォーム技術がすぐそこまで来ているなと感じます。候補者の方とカジュアル面談をしていも必ずといっていいほど話題に挙がります。記事執筆時点で with では iOS/Android 間で共有しているコードはありませんが、共通化できたら面白いだろうなと日頃から夢を見ています。

KMM は依然として Beta 段階ですが、マルチプラットフォーム技術として最も有望視しているので注目していきたいと思います。

droidkaigi.jp

アプリエンジニアと QA チームがデバッグ機能の改善に取り組むぞ! (Satoru Komai)

たいていのアプリにはデバッグのための機能が備わっていると思うのですが、with にも通称デバッグメニューが存在しています。機能としては、ログイン、サーバーの切り替え、各種フラグの編集等をサポートしています。

セッションの説明文で指摘されているように、デバッグ機能はエンジニアが必要だと思ったものが無秩序に追加される傾向にあるので気付いたら複雑で使いづらいものになってしまうという問題があると思います。

QA チームも巻き込んでデバッグ機能を改善した事例が聞けるということで、非常に参考になりそうだと思いました。

ちなみにこちらが with Android 版のデバッグメニューです。使いやすくて期待される機能が搭載されているかというと正直微妙なので、改善したいなと思っています。

droidkaigi.jp

プロダクトで安全に DataStore 移行する (Go Takahana)

with では最近 DataStore を使用し始めました。セッションの説明文で指摘されているように「移行しなくても不便がない」というのがあり DataStore への完全移行の予定は今のところありません。しかしながら、SharedPreferences のコードを残しておくのも将来的に負債になりそうなので理想的には早めに移行を済ませたいところです。

このセッションでは実践的な DataStore 移行のテクニックを学べればと思います。

droidkaigi.jp

All your Compose @Previews to screenshot tests without instrumentation (David Vávra)

with では Showkase を使って UI カタログを作成し、手軽に UI を確認できるようにしていますがスクリーンショットテストを含む UI テストは行っていません。

かつてスクリーンショットテストは高コストというイメージがありましたが、Compose 時代になって手が届きやすくなったのかなという印象があります。このセッションを見て with にも導入できそうか検討したいと思います。

droidkaigi.jp

はじめようビルドメトリクス (こまたつ)

with では 2022 年にマルチモジュール化を行いました。理由の 1 つとしてビルドパフォーマンスの向上があったのですが、作業を行う中で「そもそも Gradle ってどんな風にビルドしているの?」「どこがボトルネックになっているの?」という疑問が湧いてきました。

いろいろ調べていく中で Gradle のビルドの仕組みや流れを理解できただけでなく、工夫をしないと想像以上にビルドに無駄な時間がかかってしまうということが分かりました。ビルドパフォーマンスが悪いとチーム全体のパフォーマンスに大きく影響するため、地味に重要なポイントなのではないでしょうか。

ビルドパフォーマンス向上の第一歩は計測することだと思うので、このセッションは参考になりそうです。

droidkaigi.jp

おわりに

以上気になるセッションについてまとめました。

個人的な話になりますが、私は 2020 年に新卒で Android エンジニアになりました。エンジニアになったはよいものの、コロナ渦のためオフラインで技術カンファレンスが開催できない期間が続きました。しかし今回の DroidKaigi はオフライン会場があるということで参加が非常に楽しみです。本記事で取り上げなかったセッションももちろんのこと、どっぷりとAndroidの世界に浸かってきたいと思います✌ 終了後には参加レポートを書きます。

参考: with では上長の許可があれば技術カンファレンス等に自由に参加でき、参加費も補助されます。もちろん業務として扱われます。(制度は変更になることがあります)。

リンク

with の Android チームにおけるモジュール分割の取り組み

はじめに

こんにちは。with で Android エンジニアをしている石田です。Android エンジニアになって丸 2 年が経ち、時の流れはあっという間だなと思う今日このごろです。

with の Android チーム(以下 with-android)では新機能の開発に加えて日々積極的に技術的負債の解消に取り組んでいます。 2022 年度はマルチモジュール化に取り組みはじめました。おそらく 1 年間くらいかかるであろう長期の取り組みになりますが、本記事ではその途中経過を考察を交えてご紹介したいと思います。

公式のモジュール分割ガイド

先日公式にて Guide to Android app modularization というモジュール分割に関するガイドが公開されました。これによりモジュール分割も Android 開発において当たり前のことになっていくのかなと思います。 このガイドでは 推奨アーキテクチャ における推奨モジュール構成が分かりやすく詳細に説明されています。

例えばモジュール分割によってのみ達成できる利点として以下の 3 つが挙げられています。

  • Reusability (再利用性)
  • Strict visibility control (厳格な可視性の制御)
  • Customizable delivery (カスタマイズ可能なデリバリ)
    • ※with-android では現在 Dynamic Feature を使用していません

また、モジュール分割によっても達成することができる利点として以下の 5 つが挙げられています。

  • Scalability (スケーラビリティ)
  • Ownership (オーナーシップ)
  • Encapsulation (カプセル化)
  • Testability (テスタビリティ)
  • Build time (ビルド時間)

このようにモジュール分割をすることには非常に多くの利点があり、その名前以上に大きなパワーを持っていると言えると思います。ある程度の規模のコードベースの Android アプリではやらない手はないかなと思います。反対にモジュール分割における落とし穴の記載もあるので注意しておくとよさそうです。

nowinandroid はちょうどこの公式ガイド通りのモジュール構成になっているので、実際のコードで確認したい場合はこちらを参照するとよさそうです。

以下、本記事における「マルチモジュール」とはこの公式ガイドにあるようなモジュール構成を指すものとします。

with-android におけるこれまでのモジュール構成

モジュール分割に着手する前の with-android のモジュール構成を説明します。 with-android ではクリーンアーキテクチャを意識した 標準的な MVVM を採用しています。モジュール構成も MVVM をそのまま表現した形になっていて、ざっくりいうと data, domain, presentation といったモジュールが存在するだけでした(実際のモジュール数は約 20 個)。

■ domain モジュール: モデル、リポジトリ、ユースケース など
■ data モジュール: API、エンティティ、永続化 など
■ presentation: UI、ViewModel、遷移 など
※ 図の矢印は依存の方向を示しています

モジュールの数は最小限で with-android の歴史とともにそれぞれのモジュールの肥大化が問題となっており、そろそろ何とかしたいなという状況でした。

モジュール分割に踏み切った理由

モジュール分割による利点は上で紹介した公式ガイドの通りなのですが、with-android において重要なポイントは次のようなものが挙げられると考えました。

ビルド高速化

Gradle には キャッシュや Incremental build の仕組みがあるので一概には言えないですが、1 つ 1 つのモジュールサイズが大きいことはビルドパフォーマス低下を招きます。 ちょっとコードを変更しただけなのにビルドに時間がかかると待ち時間が発生するだけでなく、作業の集中力が切れてしまう原因にもなります。 マルチモジュール化によりビルドの並列性が向上し、ビルドの高速化が期待できます。

厳格な可視性の制御

Kotlin には package private がありません。クラスの可視性を狭いスコープに閉じ込めるにはモジュールを分ける必要があります。 マルチモジュール化によりモジュールの外から見える必要のないクラスを非公開にすることができます。

目的のコードを早く見つけられる

モジュール分割を細かく行っていないと Android Studio 上ですべてのモジュールを読み込む必要があります。すると目的のコードを見つけるのに時間がかかるので気持ちよく開発することができません。Project View にも大量のコードのリストが並ぶことになり、視覚的にもノイズになります。 マルチモジュール化により、作業中のモジュールが依存しているモジュールだけを読み込んで作業できるようになります。

再利用性

with-android ではまだ至っていませんが、マルチモジュール化により with の一部の機能だけ(例えばトーク機能のみ)を切り出したミニアプリを作ることができるようになります。今後のサービス成長の中でアプリの機能は増え続けることが予想されるため、素早い開発サイクルを回すためにも近々実現したいと考えています。

モジュール分割作業

ボトルネックはどこか

with-android の場合、一番のボトルネックは presentation モジュールが巨大であることです。計測したところ presentation モジュールの全体に対するコード行数の割合は 7 割であり、ビルドコスト も Build Analyzer によると 7 割を占めていました。

presentation モジュールに問題が集中していることが分かったので、presentation モジュールを共通機能(core)と個別機能(feature)で分割していくことにしました。このあたりは公式ガイドと同じ方針です。

domain や data モジュールも同様に分割していきたい気持ちはありますが、まずは presentation モジュールの分割に集中することにしました。

実際の作業

施策の実装で既存機能に改修を入れるとき、新規機能を作るとき、手が空いたときなど様々なタイミングでモジュール分割を行っていきました。with-android は 4 名のチームですが、分担するとコンフリクトが起きやすくなったりなどの影響がありそうだったので筆者がほとんどの作業を行いました。

肝心のどうやるかですが、presentation モジュール内のクラスの依存関係はこれまで特にルールが存在していなかったためある程度の複雑度があり、残念ながら自動でモジュールを分割するといったことは不可能であると考えました。よって Kotlin, XML, リソースなどを手動で移動していきエラーが出た箇所をよしなに修正するという作業を繰り返しました。

Android Studio(IntelliJ)には 依存関係分析機能 があり、あるクラスがどのクラスに依存しているか(またはどののクラスから依存されているか)を調べることができます。 特に複雑な部分ではこの機能を使いながら紐解いていきました。

Code > Analyze code > Dependencies...
Code > Analyze code > Backward dependencies...

モジュール分割を進めていくと画面遷移をどうするかという問題が発生するのですが、今のところは遷移用のインターフェースを介して遷移するというシンプルな方針を取っています。

結果

作業前後のモジュールサイズの変化を可視化してみました1。 1つ1つの円がモジュールに相当し、面積はモジュールサイズを表しています(簡単のために モジュールサイズ = Kotlin の LOC としています)。 色が黄色に近いものほど大きいことを表しています。

【Before 2022/03】

半年前はモジュールが 約 20 個で、上部にある黄色の presentation モジュールが圧倒的に大きいことが確認できます。この状態が半年間で次のように変化しました

【After 2022/08】

前後で比較すると以下のことが言えます。

  1. モジュール数が約 2 倍に増えた (約 20 個 → 約 40 個)
  2. モジュールサイズの差が小さくなり、バランスが良くなった
  3. 依然として presentation モジュールが最も大きい

いかがでしょうか。作業途中ではありますが前後で比較するとそこそこモジュール分割の度合いが改善されたのが確認できると思います。

モジュール分割作業を進めていく中で思ったこと

  • モジュール分割作業は自動化が難しく手作業になるため、根気のいる作業になります。担当者を交代しながら集中的に作業するのがよさそうだと思いました。
  • internal が付いていることで「あ、このクラスはこのモジュールだけで使うんだな」ということがひと目で分かるようになり、妙な安心感があるなと感じました。また普段から Visibility を意識する癖がついたように思いました。
  • 日々の開発の中でビルドが明らかに早くなったと感じる場面が多々あり、開発がしやすくなったなと思いました。
  • 頭で分かっていてもついつい NG な依存関係を作ってしまっている部分がありました。そこで module-graph-assert という Gradle プラグインを導入してモジュール依存関係のルールを強制するようにしました。 これは最初にやっておけばよかったと後になった後悔したことの 1 つです。
  • モジュールの数がかなり増えたので、build.gradle の記述を Composite build で共通化する必要がありそうだなと思いました。

まとめ

本記事では with-android におけるモジュール分割の取り組みについてご紹介しました。まだ道半ばではありますが、その効果にはかなり満足しています。より綺麗で快適なコードベースを目指して残りの作業も行っていきたいと思います。モジュール分割作業完了後は with の一部の機能だけを切り出したミニアプリを実現していきたいと思っています。

参考リンク


  1. 図は R の packcircles というライブラリで作成しました