kobakei's blog

プログラミングの話や技術系イベントの話をゆるく書くブログです

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を書きます。大体上に同じです。

アプリケーションクラス

これはアプリケーションのパッケージの直下に置きます。