Androidアプリのパッケージ構成の個人的ベストプラクティス
以前Androidのパッケージ構成について考えてみたという記事を書いたんですが、書いたときから結構時間が経って考え方が変わった箇所もあるので、再度まとめようと思います。
前提
アプリケーションのアーキテクチャには、MVVM with data bindingを採用しています。また、モデルは階層化アーキテクチャ(っぽい何か)を採用しています。
結論
こんな感じになりました。ここでは以下で説明する順に並べていますが、Android Studio上ではアルファベット順に並びます。
com.example.myapp |- di | |- scope | |- model | |- entity | |- usecase | |- repository | |- dao | |- net | |- ui | |- base | |- util | |- view | |- foo | |- bar | |- ... | |- service | |- receiver | |- App.java
各パッケージ
di
Dagger 2のComponent / Moduleをここに置きます。
scope
DaggerのScopeアノテーションを自作したときはここに置きます。
model
Modelの各クラスがここに入ります。
entity
データオブジェクト
usecase
ビジネスロジックを表すクラス。1つの処理で1クラス。例えば、「サインインする」というビジネスロジックには、SignInUseCaseというクラスを作成します。
repository
オブジェクトのCRUDを提供するクラス。対応するエンティティごとに1クラス。後述のdaoとnetパッケージのクラスを抽象化するクラスです。
dao
データベース(主にSQLite)にクエリを投げてレコードを取得し、エンティティに変換するクラス。もちろんその逆(データベースへのWrite)も行います。
net
サーバーと通信してレスポンス(主にJSON)を取得し、エンティティに変換するクラス。もちろんその逆(POST / PUT / DELETEメソッドのAPIコール)も行います。
ui
UIそのものと、UIに関連するロジックをここに書きます。
MVVMの場合、VとVMをここに書いていきます。なぜビューとビューモデルでパッケージを分けないかというと、大体のビューは対応するビューモデルがいるので、パッケージを同じにしておいたほうが開発するときに作業しやすく、あとから見やすいためです。同じ理由で、Activity、Fragment、Adapterも同じパッケージに置きます。ちなみに、モデルは複数の画面から呼び出されることが多いので、独立したmodelパッケージ以下に配置しています。
base
BaseActivityやBaseFragmentなど、ベースクラスを置きます。
util
ビューやビューモデルで共通に利用するユーティリティを置きます。Data bindingのBindingAdapterなどもここに置きます。
view
カスタムビューをここに書きます。
それ以外
画面単位でパッケージを作成します。例えば、ユーザー登録画面ならsignup、商品の購入画面ならpurchaseなど。その画面のActivity, Fragment, ビューモデルがすべてそこに入ります。
service
AndroidのServiceをここに書きます。model以下でもいいような気もしますが、ライフサイクルを持つという点ではActivityに近いので、あえて独立させました。
receiver
AndroidのBroadcastReceiverを書きます。大体上に同じです。
アプリケーションクラス
これはアプリケーションのパッケージの直下に置きます。