Androidアプリのマルチモジュール化

はじめに

初めまして、ジモティーで Android アプリを担当している谷です。

最近マイクラにハマってしまい、やることが無限すぎて困っています。

今回は弊社の Android アプリをマルチモジュール化したのでそのお話をしたいと思います。

導入の背景

まずは弊社の Android アプリの現状の構成について説明します。

弊社の Android アプリは MVVM + CleanArchitecture を取り入れ、3層のレイヤードアーキテクチャで構成しています。

  • Presentation 層
  • Domain 層
  • Data 層 (Infra層)

上記を1つのモジュール内で管理しており、各層はパッケージで切り分けているため、参照の方向に強制力はありませんでした。

なので、実装担当者が参照の方向に気をつけながら実装する必要があり、本来の目的以外のところに注意を払う必要があり、厳しいさを感じてました。

そこで、マルチモジュールを取り入れることで、アーキテクチャをモジュールで表現することができるようになると考えて、上記課題を解決できるのではないかと思い導入を決めました。

また、各モジュールの依存関係を整理していくことで、ビルド時間の短縮の短縮も見込める可能性があるため、その点でも開発生産性の向上に期待できそうというのも決め手の一つとなりました。

分割方針

長い歴史のあるアプリで、コードベースも巨大なため、1回で理想的な形に変更できないと判断しました。

そこで、以下の点を考慮して方針を決めました。

  • 学習コストを低くする
  • 今後より改善しやすい構造であること

特に 学習コストを低くする という点を意識するために、現状のアーキテクチャ構造に近くなるようにモジュールを分割する形としました。

イメージ図

パッケージ構成

最終的なパッケージ構成は以下です。

モジュールには * をつけています。

(data パッケージ内の entity は CleanArchitecture 上の entity ではなく、 Gson によるレスポンスのマッピングを行うクラスを格納するモジュールとしての命名となっています。命名ミスっているので本当は変更したいところですが。。。)

├── app*
├── data
│   ├── repositoryimpl*
│   ├── data*
│   ├── entity*
│   ├── mapper*
│   ├── network*
│   └── database*
├── domain
│   ├── repository*
│   ├── model*
│   └── usecase*
└── utility*

解説

全てを説明するのは難しいため、ポイント部分の解説です。

  • 基本構成は app / domain / data としました。

  • app モジュールには Application クラスが入っており、全てのモジュールを参照する形になっています。

    • 本来、Application クラスを分離するべきですが、Application クラスを一時的なデータの保存場所として使っており、修正するには時間がかかりそうだったためこの形にしました。
  • utility モジュールは全モジュールが共通で使う、以下のようなクラスを格納しています。

    • util
    • helper
    • constant (定数などを定義しているクラス)

マルチモジュール化の結果

  • ⭕️アーキテクチャを仕組みで表現できるようになった

    • 適切な依存関係を設定することができるようになったため、アーキテクチャの強制力を働かせて開発を進めることができるようになり、実装者が意識しないといけない部分が減ったため、開発生産性が向上した。
  • ❌一方で、ビルド時間の短縮に対しては効果が薄かった。

    • フルビルド時のビルド時間が若干増加してしまいました。

工夫した点

  • マルチモジュール化によりどのくらい改善が図れたかを調べるため、gradle-profilerを使用して計測を行うようにしました。

    • マルチモジュール修正頻度よりも多く計測を行う必要はなさそうと判断したため、計測頻度は1週間に1回行うようにしました。
  • マルチモジュールの移行率を計測することでモチベーションを上げるようにしました。

    • 最初はちょっとずつそれぞれのモジュールへ移行していたのですが、数が膨大だったため、少しずつでも移行されている実感を得られないと続かないだろうと考えて計測を行うようにしました。 (チームの方にも手伝っていただき、移行が加速しました!)
  • ConventionPlugin導入

    • モジュールを作成する中で同じプラグインやライブラリを記述していく必要があり、それぞれのライブラリの管理に関してのオーバーヘッドが発生することが想像されたので、共通で使える形にしたいと考えて導入しました。
  • モジュールの作成手順の作成

    • 今回のマルチモジュール化では、学習コストを低くするというのも大事な要素だったので、モジュールの手順書を作成して、チームに展開後、作成した手順書を使ってハンズオンを行いました。

残課題

  • Application クラスを application モジュールとして切り出すことができなかったので分離を進める。
    • 画面上で生成したインスタンスの一時保存クラスとして Application クラスを使用してしまっているため、修正工数がかなりかかってしまうのと、安全にマルチモジュール化が行えないと判断して、app モジュールはそのままにするという形にしました。

最後に

今回はジモティーの Android アプリのマルチモジュール化について紹介させていただきました!

移行したばかりでまだまだこれからという状況ですが、日々改善していければと思います!