Edited at

ドメインオブジェクトを中心としたClean Architecture のためのレイヤー構成

ドメインオブジェクトを中心としたClean Architectureは、どういうレイヤー構成にするとよいか、簡単にまとめてみた。


イメージ

たぶん、こんな感じになるはず。通常は円状に表現するが、わかりにくいので層状に書いてみた。


レイヤー構成

赤い部分の層は、直接依存の方向が上から下です。グレー部分の層は、契約だけが定義された独立した層で、ユースケース層やインターフェイス層から依存できるものとします。


  • インターフェイス(アダプタ)層


    • 内外とのデータ形式の変換が主な役割

    • コントローラ、プレゼンター(内部から外部へデータ形式を変換する責務),ゲートウェイ(外部と通信する責務。DBやRPC)



  • ユースケース層


    • アプリーケーション層ともいう

    • アプリケーション固有のビジネスルールをカプセル化する



  • ドメイン層



    • Clean Architecture本では、中心にはエンティティとだけ書かれているが、DDDでは中心はドメイン層になる

    • ドメインモデルを表現した実装



  • 契約層(契約だけを表現した型を配置)


    • ⚠️こういう層を定義するというのはClean Architectureにはない、アイデアです。

    • Input Port, Output Port, DTO

    • リポジトリ

    • DAO, Record




DIによるオブジェクトグラフの構築


  • コントローラに対してDIするオブジェクト


    • ユースケース

    • プレゼンター



  • ユースケースに対してDIするオブジェクト


    • リポジトリ

    • DAO(CQRSのリード責務なら)




インフラストラクチャ層はどこに行った?

インフラストラクチャ層は、要件が変化しても依存し続ける層。すべての層が依存できる汎用的な技術基盤(言語を拡張するような実装が提供されることが多い)。Clean Architectureでも導入できる。インターフェイス層とごっちゃにしないこと。


所感


  • 永続化に関する層が上位に配置される以外は、伝統的なレイヤー化アーキテクチャと基本的に差がないと考えてよい。あとは、Input Port, Output Portが仰々しく見えるだけ。


  • Clean Architecture本によると、Input PortとOutput Portはバウンダリの抽象っぽい。バウンダリだけに限らず、永続化に関するInput Port, Output Portの概念があってもよい気がするが、用語の使い方はClean Architecture本に合わせておいた。

  • インターフェイス層からユースケースの実装を直接呼べてしまうので、Input Portの抽象がどこまで必要かわからない。そもそも抽象がなくてもいいのではないか。Output Portは間接依存のために必要。コールバックとして抽象化する方法もあるし、単にプレゼンターのインターフェイスだけを定義する方法もある。

  • 集約は本来ライフサイクルのためのパターンの一つなので、インターフェイス層ではないか説がある。集約にも契約と実装に分離し、実装はインターフェイス層に配置した方がいいかもしれない。