DDD
CleanArchitecture

ドメインオブジェクトを中心とした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は間接依存のために必要。コールバックとして抽象化する方法もあるし、単にプレゼンターのインターフェイスだけを定義する方法もある。
  • 集約は本来ライフサイクルのためのパターンの一つなので、インターフェイス層ではないか説がある。集約にも契約と実装に分離し、実装はインターフェイス層に配置した方がいいかもしれない。