クリーンアーキテクチャ
クリーンアーキテクチャ(The Clean Architecture)とは、Robert C. Martinが主張している、きれいなアーキテクチャとはこういうものだ、という目安である。
図の意味
黄色の層(Enterprise Business Rules)
ユースケースが扱うオブジェクトであり、エンティティという名前がついている。エンティティは値を持ったオブジェクトであり、さらにオブジェクトは自身を操作するメソッドを持っていたり、制約条件を持っている。
DDDでいうドメイン知識(ルール/制約)が含まれるだろう。DDDでいう値オブジェクトも多分含まれるだろう。
赤色の層(Application Business Rules)
ユースケースを実装する層(ビジネスロジック層)。フレームワークを意識しないという点で抽象的なコードになっている。
エンティティのリストからエンティティを検索するとか、エンティティ単体では実現できないコードが入っている。
エンティティの持つメソッドを呼び出してビジネスロジックを記述する。
緑色の層(Interface Adapters)
橋渡し役。抽象的なユースケースにとって便利な形式に変換したり、ユースケースの実行結果をフレームワークが扱う形式に変換したりする層だと思う。
青色の層(Frameworks & Drivers)
多分MySQLとか、Express.jsとか、Reactとかのフレームワークが当てはまる。
①②③ について
図中に書けてないがController(ユーザー入力を受け取る人) が直接UseCaseの実装を参照しておらず、インターフェースを経由しているのがポイントらしい。Presenter(表示する人)も同様。
矢印の向きに着目する。緑色の層は赤色の層に依存している。ControllerはUseCaseのインターフェースに依存している。PresenterはUseCaseのインターフェースを実装している。
同心円について
- 同心円の内側のものほど抽象的になる。つまりフレームワークやハードウェアに依存するコードはなくなる。
- 同心円の外側のものほど具体的になる。また開発対象から遠くなる。
- 同心円内の矢印は依存性。外から中に向かっている。依存関係逆転の原則、つまりインターフェースでやりとりさせることで解決できる。
- 同心円内の矢印は処理の流れを指すものではない。例えばGatewaysからDBアクセスは当然あり得る。
- 同心円は4つで分けられているが、4つが正解と述べているわけではない。
- 外側の層は内側の層に依存するのがクリーンアーキテクチャの肝だが、緑色の層(
Interface Adapters)については外界とユースケースの橋渡し役であり、現実には外界に依存する必要があるという点で矛盾しているという意見がネットにはある。
クリーンアーキテクチャが述べていることは以下3点だと解釈している。
- フレームワークに依存しない、テスト可能で、UIに依存せず、外界にも依存しないのが美しいアーキテクチャである。
- 上を守るために、ハードウェアや枠組みに依存するコードとそうでないコードを層として分けるべき。
- 上を守るために、どの層の部品もインターフェースを作っておいて、交換可能な部品にするべき。
依存方向=処理の流れではないことに注意する
出典不明の画像があるがわかりやすい。
サーバーサイド未経験の大学生が4日でGolang×CleanArchitectureのAPIを構築した話 #アーキテクチャ - Qiita
ユーザがUIを操作したとき、応答がUIに返ってくるまでの処理の流れを示したものだと思われる。
依存方向は常に内側だが、処理は外側を行き来してもアーキテクチャ的に問題ないようだ。
クリーンアーキテクチャというアーキテクチャは存在するのか
クリーンアーキテクチャなんてものはない(クリーンアーキテクチャーの読み方) - プログラマのはしくれダイアリー
美しいアーキテクチャというのはこんな感じだ、というのが上記の図であって、これがクリーンアーキテクチャというアーキテクチャだという提唱ではないという声。
クリーンアーキテクチャのUsecaseはなぜControllerへ値を返すのではなくOutput PortとしてPresenterを呼び出すのか
クリーンアーキテクチャのUsecaseはなぜControllerへ値を返すのではなくOutput PortとしてPresenterを呼び出すのか - Runner in the High
最近のWebフレームワーク(Express.jsとかNestJSとかFlaskとかFastAPIとか)では以下のように結果をControllerにreturnする事が多い。
1 2 3 4 5 6 7 8 9 10 11 12 | |
しかし、クリーンアーキテクチャにおける同心円の図と、図の右下の処理フローにしたがって実装すると以下のような感じになる。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 | |
要するにクリーンアーキテクチャにおいてはControllerへ入力したとき、UseCaseはControllerに結果を戻すのではなく、Presenterに結果を渡すという形で出力する。この点でクリーンアーキテクチャは伝統的な階層型アーキテクチャとは異なる。
Webフレームワークの思想にそぐわない場合、無理して導入することはないという意見がネットでは見られる。自分もそれでいいと思う。
Humble Objectパターン
テストしやすいコードとテストしにくいコードは分けておくこと。
| ❌️悪い例 | |
|---|---|
1 2 3 4 5 | |
| ✅️良い例 | |
|---|---|
1 2 3 4 5 6 7 8 | |
