図解クリーンアーキテクチャ

[こちら](https://www.12-technology.com/2021/06/blog-post.html)に詳細に記載しています。宜しければご参照ください。

# 概要
一見複雑に見えるクリーンアーキテクチャをSOLID原則を用いて、成り立ちをひも解いていきます。

# 背景
クリーンアーキテクチャを調べていくと下記のような概念図や構成図を見かけます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/372804/c1e62bec-1218-5359-9c7b-8e2f4ba69a1d.png)
![image (1).png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/372804/ae94c04b-e9e5-eb7d-d9d4-c7095fe4d2ca.png)

言いたいことは何となく分かるのですが、初見でメリットが理解できませんでした。
本記事ではレイヤードアーキテクチャの欠点を
SOLID原則に沿って補完していくことで、クリーンアーキテクチャをひも解いていきたいと思います。

# SOLID原則とは
ソフトウェアの拡張性、保守性等を担保し、メンテナンスしにくいプログラムになることを防ぐための原則です。

S：SRP、単一責任の原則
O：OCP、開放閉鎖の原則
L：LSP、リスコフの置換原則
I：ISP、インタフェース分離の原則
D：DIP、依存性逆転の原則
SOLID原則の詳細はこちらの記事が参考になります。
[イラストで理解するSOLID原則](https://qiita.com/baby-degu/items/d058a62f145235a0f007)

# クリーンアーキテクチャが必要な理由
![layer.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/372804/bb37672e-0277-fc4c-756c-bc48fc895cb1.png)

こちらの最も基本的なレイヤードアーキテクチャの欠点からクリーンアーキテクチャの必要性を見ていきます。

## 依存性逆転の原則 (DIP: Dependency Inversion Principle)　その①
上図のレイヤードアーキテクチャの欠点の一つに<font color="Red">**Domain層が、Infrastructure層に依存している**</font>ことが挙げられます。

安定依存の原則(SDP:The Stable Dependencies Principle)によれば
**安定しているDomain層が、変更が多く不安定なInfrastructure層に依存**していることは安定依存の原則に反しています。
![infra.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/372804/483b4aed-cc58-a15b-b93b-5adebd324ac4.png)

この依存関係を解決する考え方として**依存性逆転の原則**があります。
依存性逆転の原則に従うとDomainとInfrastructureの関係は下記のようになります。

![infra逆転.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/372804/2455f1c2-1268-ee75-31d8-9aecae954116.png)

DomainとInfrastructureの間に**Interface**を設けます。
この構成によりDomainからInfrastructureを**抽象化**します

## 依存性逆転の原則 (DIP: Dependency Inversion Principle)　その②
依存性逆転の原則により、DomainとInfrastructureの関係を逆転させました。
しかし、まだ完全には依存関係を切り離せていません。

下記の実装を見て見ます

```java:domain.java
DataAccessInterface interface = new Infrastructure();
interface.getData();
```

実装を考えるとDomainが、Data Access Interfaceを呼び出すときに**Infrastructureをインスタンス化する**必要があります。

そこでDomainからInfrastructureのインスタンスを隠蔽するため、
**Infrastructureをインスタンス化するData Accessを配置**することでこの問題を解決します。

![bbb.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/372804/076c5b28-d9c7-ce70-707b-60a297ab77bb.png)

```java:domain.java
DataAccessInterface interface = new DataAccess();
interface.getData();
```

```java:DataAccess.java
@Override
public void int getData(){
    Infrastructure infra = new Infrastructure();
    infra.getDataFromInfra();
}
```

この構成によって**DamainからInfrastructureを抽象化します**

DataAccessのようなデータアクセス手段、データの永続化を抽象化するオブジェクトを<font color="Red">Repository</font>と呼びます。デザインパターンの<font color="Red">リポジトリパターン</font>として知られています。

## 開放閉鎖の原則 (OCP:Open/Closed Principle)
次に視点を変えてUI(Presentation)とApplicationの依存関係に目を向けてみます。
![bbb.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/372804/076c5b28-d9c7-ce70-707b-60a297ab77bb.png)

一般的に、UIはユーザーの目に最も触れるため比較的変更が多く発生します。
<font color="Red">**このため、UIの変更をApplicationに波及させたくなく、
また、Applicationの変更にUIも振り回されたくありません。**</font>

こうした事態を解決する考え方として**開放閉鎖の原則**の考え方があります。

拡張に対して開いていなければならず、 修正に対して閉じていなければならない。という
開放閉鎖の原則に基づき**Application Interface**を設けます。
合わせて"依存性逆転の原則 (DIP: Dependency Inversion Principle)　その②"と同様にインスタンス化の**Controller**を設けます。
![aaa.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/372804/f8155f20-7a64-1b44-ad70-974435c56630.png)

この構成により、変更の多いUI(Presentation)は拡張に対して開いており、修正に対して閉じている状態に変更されます。

## 単一責任の原則 (SRP:Single Responsibility Principle)　その①
今度は**依存関係**ではなく、各モジュールの**責務**に目を向けてみます。

![aaa.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/372804/da3ea02e-7d7c-2812-249b-7b65483cdd8b.png)
上図Domainの責務は2つ存在しています。
<dl>
  <dt>1．ユースケースの実行</dt>
  <dd>Applicationの要求に基づき、Data Access Interfaceからデータ取得</dd>
  <dt>2．ビジネスロジックの実行</dt>
  <dd>Data Access Interfaceからのデータを加工する等ビジネスロジック実行</dd>
</dl>

このためDomainは、2つの変更理由によって修正が加えられます。
この問題として、<font color="Red">**一方の修正によってもう一方のコードに予期せぬ影響を及ぼすかもしれません。**</font>

こうした問題への考え方として**単一責任の原則**があります。
この考え方によると**一つのモジュールは二つ以上の変更理由で変更されてはなりません。**

この考えに基づいて、Domainを分割します。
**ビジネスルールを提供するモジュールをEntities**と、
**Data Access Interfaceを介してデータを取得するモジュールをUseCase Interactor**とします。
![aaa (1).png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/372804/61d92519-539b-9a88-a128-bad73a7b805f.png)

## 単一責任の原則 (SRP:Single Responsibility Principle)　その②
次にUI(Presentation)について考えます。

UI(Presentation)も責務が2つ存在します。
<dl>
  <dt>1．Viewからのイベント通知</dt>
  <dd>UI(Presentation)からのUIイベントをControllerに通知</dd>
  <dt>2．Viewへのデータ解釈</dt>
  <dd>ControllerからのデータをUI(Presentation)に渡す</dd>
</dl>

"単一責任の原則 (SRP:Single Responsibility Principle)　その①"と同じ考え方に基づき分割します。
**Viewへのデータ解釈を担うモジュールをPresenter**として分割します
![presenter_split.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/372804/cfda5947-ed7b-fd0f-89d1-97d3fc61cb63.png)

## インターフェース分離の原則(ISP:Interface Segregation Principle)
先ほど分割したControllerとPresenterについて考えます。

Controllerの責務はViewの状態を受け取ってApplication Interfaceを介して、
Applicationが要求するデータ形式でデータを引き渡すことです。

一方でPresenterの責務は、Controllerを介してApplicationのデータを受け取ることです。

このとき一つの問題が生じます。
<font color="Red">**Controllerに本来責務でない実装が入ってしまいます。**</font>
Application InterfaceのリターンをPresentationに渡す実装が必要となります。

こうした問題を解決する考え方にインターフェース分離の原則があります。
![presenter_interface.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/372804/70cf498d-3b1d-84f3-5431-20fca54d5102.png)

Controllerは
責務に沿ったInterfaceのみを呼び出せるように**Input Boundary**を配置されました。

Presenterも
責務に沿ったInterfaceのみを実装できるように、**Output Boundary**を配置されます。

この構成にシステム境界線を引いてみます。
![system_config.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/372804/adb4ded1-c329-7d9a-d153-4c26d3126fb7.png)

この図をクリーンアーキテクチャの構成図と見比べてみます。
![cleanarch_config.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/372804/2dadb82b-e737-a8d1-7c93-ec7d3c566f78.png)

ほとんどの構成が同じではないでしょうか？
こうして見て見るとクリーンアーキテクチャの構成がなぜこのような構成が理由をもって理解できるのではないでしょうか？

# さいごに
クリーンアーキテクチャをSOLID原則の観点で見ていきました。

いきなりクリーンアーキテクチャだけを見てしまうと難解に思えてしまいますが、
順を追ってみていくと既存の考え方の組み合わせのように見えます。