アーキテクチャって何？（UIレイヤー・ドメインレイヤー・データレイヤーなど）

## はじめに

アーキテクチャについて学んだことを個人的にまとめました。「アーキテクチャ？何それ？？」状態の方にとって少しでも参考になれば幸いです。
また、間違っている部分があればご指摘いただければと思います。

### この記事で分かること

- アーキテクチャとは？
- UIレイヤー・ドメインレイヤー・データレイヤーの概要
- その他、大切なこと


※細かい話は省いていますので、詳しくは公式ドキュメントなどをご覧ください

## アーキテクチャってそもそも何？

- 「堅牢で高品質なアプリを作るための設計」みたいなイメージ
    - アーキテクチャがしっかりしてないと、修正やテストがしにくかったり、思わぬところに変更の影響が出てしまったり…など、余計な労力がかかる

## 推奨されるアプリアーキテクチャ

- 推奨されるアプリアーキテクチャは、下記の矢印のような依存関係を持つUIレイヤー・ドメインレイヤー（※必須ではない）・データレイヤーに関心の分離を行う

![mad-arch-overview.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1630025/c786e951-93af-a412-2bef-d05a486566b6.png)

### UIレイヤー

![mad-arch-ui-overview.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1630025/e3987a64-3eb4-0204-2b38-7127a16f3506.png)

- UIはUiStateをただ単に視覚的に表したもの
- UiStateの変更は、即UIに反映される
- ViewModelはState Holder

#### UiState
- `data class`や`sealed class`でカプセル化する

``` kotlin
data class NewsUiState(
	val newsItem: List<NewsItemUiState>,
	val userMessages: List<Message>
)
```

- 不変
    - これにより、状態を読み取りそれに応じてUI要素を更新する単一の役割に集中できる
- :warning: UI自体がUiStateを直接変更してはいけない

### ドメインレイヤー（※必須ではない）

- ビジネスロジックだけを含む
    - データの表示や保存・取得はどーでもいい
    - （ビジネスロジック：イベントやデータ変更の処理方法）
- UseCaseで構成される
- :warning: データをキャッシュする必要がある場合はドメインレイヤーではなく、データレイヤーに配置した方が良い

#### UseCase

- メリット
    - ビジネスロジックをカプセル化し、UIの複雑さを軽減
    - 複数のViewModelで使用されるロジックを、単一のUseCaseに抽出することで重複回避
        - （従来はUtilに置かれていたが、それはあまり好ましくない）
    - ViewModelのテストが楽
        - RepositoryじゃなくてUseCaseのみに依存するため
        - （ViewModelが複数のRepositoryに依存すると複雑なロジックが含まれる可能性があり、不必要に大きくなってしまう）
- `invoke`関数を使うことで、1つのことだけを行うように強制できる
    - ユースケースの呼び出しが簡潔になる

``` kotlin
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)
	}
}
```

- Repositoryなどの下位レイヤーや、他のUseCaseに依存できる
    <img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1630025/d41035a2-f687-e31b-1e1c-248170fb357c.png" width=400 />



### データレイヤー

![mad-arch-data-overview.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1630025/41d9f1b6-6545-67d1-3f5a-36d666fffc4f.png)

- 1つ以上のDataSourceと相互作用できるRepositoryで構成される
- データレイヤーへのエントリポイントは常にRepository
- 公開されるデータは不変

#### DataSource

- アプリが機能するために必要なデータを提供する責任を持つ
    - :warning: ただし、直接DataSourceにアクセスしてはいけない（必ずRepositoryを通る）
- ネットワークやローカルデータベースなど、1つのデータソースのみを操作する責任を持つ
    - DataSourceでAPIを叩いたりする

#### Repository

- 主な特徴
    - アプリ内にデータを公開
    - データを一元化
    - 複数のDataSource間の競合を解決
    - 他の部分からデータのソースを抽象化
    - ビジネスロジックを含む
- その他
    - 様々なDataSourceを組み合わせることが出来る
    - 他の複数のRepositoryに依存することもある
         <img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1630025/2e9ab6dd-fd38-2a87-2c19-97c2995e97c4.png" width=400 />

## その他、大切なこと：Entities

- レイヤーごとにモデルを作成しよう！！
    - レイヤー間の変更を他のレイヤーに伝播させないようにするため
    - これをしないと、修正範囲が広くなってしまう
- Entity
    - 何かの状態を表す概念のこと
    - そのレイヤーで必要なものだけを持っていれば良い

## 結論

- アーキテクチャとは？
    - 「堅牢で高品質なアプリを作るための設計」
- UIレイヤー・ドメインレイヤー・データレイヤーの概要
    - UIレイヤー
        - UIはUiStateをただ単に視覚的に表したもの
        - UiStateの変更は、即UIに反映される
    - ドメインレイヤー（※必須ではない）
        - ビジネスロジックだけを含む
        - UseCaseで構成される
    - データレイヤー
        - 1つ以上のDataSourceと相互作用できるRepositoryで構成される
        - データレイヤーへのエントリポイントは常にRepository
- その他、大切なこと
    - Entities（何かの状態を表す概念）
    - レイヤーごとにモデルを作成することが大切

### 主な参考資料

主にModern Android Development (MAD) Skills Architectureの動画やAndroidの公式ドキュメントを参考にしました。詳しくは以下からご覧ください。

https://www.youtube.com/watch?v=TPWmfJq16rA&list=PLWz5rJ2EKKc91i2QT8qfrfKgLNlJiG1z7&index=3

https://developer.android.com/topic/architecture

## おわりに

ここまで読んでいただき、ありがとうございました！
何かありましたら、コメントをお願いいたします。