はじめに
アーキテクチャについて学んだことを個人的にまとめました。「アーキテクチャ?何それ??」状態の方にとって少しでも参考になれば幸いです。
また、間違っている部分があればご指摘いただければと思います。
この記事で分かること
- アーキテクチャとは?
- UIレイヤー・ドメインレイヤー・データレイヤーの概要
- その他、大切なこと
※細かい話は省いていますので、詳しくは公式ドキュメントなどをご覧ください
アーキテクチャってそもそも何?
- 「堅牢で高品質なアプリを作るための設計」みたいなイメージ
- アーキテクチャがしっかりしてないと、修正やテストがしにくかったり、思わぬところに変更の影響が出てしまったり…など、余計な労力がかかる
推奨されるアプリアーキテクチャ
- 推奨されるアプリアーキテクチャは、下記の矢印のような依存関係を持つUIレイヤー・ドメインレイヤー(※必須ではない)・データレイヤーに関心の分離を行う
UIレイヤー
- UIはUiStateをただ単に視覚的に表したもの
- UiStateの変更は、即UIに反映される
- ViewModelはState Holder
UiState
-
data class
やsealed class
でカプセル化する
data class NewsUiState(
val newsItem: List<NewsItemUiState>,
val userMessages: List<Message>
)
- 不変
- これにより、状態を読み取りそれに応じてUI要素を更新する単一の役割に集中できる
- UI自体がUiStateを直接変更してはいけない
ドメインレイヤー(※必須ではない)
- ビジネスロジックだけを含む
- データの表示や保存・取得はどーでもいい
- (ビジネスロジック:イベントやデータ変更の処理方法)
- UseCaseで構成される
- データをキャッシュする必要がある場合はドメインレイヤーではなく、データレイヤーに配置した方が良い
UseCase
- メリット
- ビジネスロジックをカプセル化し、UIの複雑さを軽減
- 複数のViewModelで使用されるロジックを、単一のUseCaseに抽出することで重複回避
- (従来はUtilに置かれていたが、それはあまり好ましくない)
- ViewModelのテストが楽
- RepositoryじゃなくてUseCaseのみに依存するため
- (ViewModelが複数のRepositoryに依存すると複雑なロジックが含まれる可能性があり、不必要に大きくなってしまう)
-
invoke
関数を使うことで、1つのことだけを行うように強制できる- ユースケースの呼び出しが簡潔になる
class FormatDateUseCase() {
operator fun invoke(date: Date): String {
return myformatter.format(date)
}
}
class MyViewModel(formatDateUseCase: FormatDateUseCase) : ViewModel() {
init {
val today = Calendar.getInstance()
val todaysDate = formatDateUseCase(today)
}
}
データレイヤー
- 1つ以上のDataSourceと相互作用できるRepositoryで構成される
- データレイヤーへのエントリポイントは常にRepository
- 公開されるデータは不変
DataSource
- アプリが機能するために必要なデータを提供する責任を持つ
- ただし、直接DataSourceにアクセスしてはいけない(必ずRepositoryを通る)
- ネットワークやローカルデータベースなど、1つのデータソースのみを操作する責任を持つ
- DataSourceでAPIを叩いたりする
Repository
- 主な特徴
- アプリ内にデータを公開
- データを一元化
- 複数のDataSource間の競合を解決
- 他の部分からデータのソースを抽象化
- ビジネスロジックを含む
- その他
その他、大切なこと:Entities
- レイヤーごとにモデルを作成しよう!!
- レイヤー間の変更を他のレイヤーに伝播させないようにするため
- これをしないと、修正範囲が広くなってしまう
- Entity
- 何かの状態を表す概念のこと
- そのレイヤーで必要なものだけを持っていれば良い
結論
- アーキテクチャとは?
- 「堅牢で高品質なアプリを作るための設計」
- UIレイヤー・ドメインレイヤー・データレイヤーの概要
- UIレイヤー
- UIはUiStateをただ単に視覚的に表したもの
- UiStateの変更は、即UIに反映される
- ドメインレイヤー(※必須ではない)
- ビジネスロジックだけを含む
- UseCaseで構成される
- データレイヤー
- 1つ以上のDataSourceと相互作用できるRepositoryで構成される
- データレイヤーへのエントリポイントは常にRepository
- UIレイヤー
- その他、大切なこと
- Entities(何かの状態を表す概念)
- レイヤーごとにモデルを作成することが大切
主な参考資料
主にModern Android Development (MAD) Skills Architectureの動画やAndroidの公式ドキュメントを参考にしました。詳しくは以下からご覧ください。
おわりに
ここまで読んでいただき、ありがとうございました!
何かありましたら、コメントをお願いいたします。