まえがき
ドメイン駆動設計(DDD)を勉強中の大学生です。
これまでDDDはふんわり理解したつもりでいたのですが,ふとDomain Modelの意味範囲の広さには2通りあるのでは? と感じました。
すなわち,オニオンアーキテクチャの文脈におけるDomain Model
と,より一般的なDDDの文脈におけるDomain Model
では,それぞれの指す意味領域の広さが少し違うのでは?と感じたので,ドメイン駆動設計の理解を整理しながら,その疑問について考察していきます。
DDDとは何者なのか,特にDomain Model
とDomain Service
の違いについて整理しているので,「なんとなくDDDが理解しきれない…」という方にとっても参考になるかもしれません!
この記事はきちんとした調査に基づいたものではなく,雑に調べて個人の頭の中で整理したことが書かれています。そのため情報が不正確である可能性がありますので,あくまで参考程度にとどめておいてください。有識者の方は,ぜひアドバイス・指摘等お願いします!
また,Domain Model
のような英語表記と「ロジック」のようなカタカナ表記が混在していますが,前者のような英語表記は,DDDなどの文脈における細かなニュアンスを含んだ意味で,後者のようなカタカナ表記は,日常語における意味合いで使っています。
ドメイン駆動設計 (DDD) とは
まずDDDについて前提を確認します。
私は,DDDとはオブジェクト指向らしいアプリケーション設計をするための方法論と解釈しています。
すなわち,「登場人物」や「専門家のもつ知識」,「業務ロジック」などのDomain Model
をアプリケーションの中心部で表現し,実際の業務フロー=処理の流れは,Use Case
やApplication Service
等のレイヤーでDomain Model
を操作することで表現します。
Domain Model
とは
では,Domain Model
とは何でしょうか?
Domain Model
とは,DDDにおいてまさしく「登場人物」や「専門家のもつ知識」,「業務ロジック」などを表現し,カプセル化したモノです。多くの場合クラスで表現します。
しかし,どうやらこのDomain Model
という言葉の意味の範囲が,文脈によって少し変わってくるような気がしたのです。
Domain Model
の意味範囲の考察
一般的(と思われる)意味領域については以下の後者で説明しますが,まずは私が「ちょっと意味領域違うかも?」と引っかかった,オニオンアーキテクチャにおけるDomain Model
について説明します。
オニオンアーキテクチャにおけるDomain Model
の意味範囲
オニオンアーキテクチャでは,外側から順に
UI(Presentation), Infrastructure, Tests
> Application Service
> Domain Service
> Domain Model
というレイヤー分けが提案されています。
アプリケーションのコア領域をDomain
と呼んでいながら,そこにはDomain Model
とDomain Service
という異なるレイヤーが存在しており,混乱しそうです。。。
Domain Model
とDomain Service
の違い
そこでいろいろと調べた結果,なんとなく感じ取れたことがあります。それは,どうやらオニオンアーキテクチャの文脈では,ふつうよりDomain Model
の意味領域が狭いっぽい,ということです。
すなわち,オニオンアーキテクチャの文脈でDomain Model
が指すのは,Entity
やValue Object
,あとはそれらのAggregate
(集約)など,要するに登場人物の実体のことであるように感じられます。
このときDomain Model
は,登場人物と,その登場人物ひとりの中にカプセル化「できる」専門知識やロジックをメソッドとして表現したものであるといえそうです。
いま,カプセル化「できる」と強調したことに気づかれましたか?これらDomain Model
はアプリケーションの中核となる「知識」や「ロジック」を表現しますが,一方でそれら全てを表現し尽くすことは「できない」のです。
というのも,複数の登場人物の関係性の中で初めて表現できる知識やロジックもあるはずだからです。
ひと声で「これやって」と言われたら,登場人物たちをまとめて,いい感じに業務フローをまわすのもまた,専門知識やロジックであり,これらをカプセル化するのがDomain Service
です1。
たとえば「会社全体を運営する」業務フローを考える時,「経理部での仕事内容」は十分に中核にあり専門的です。
一方でこの「経理部での仕事内容」ももっと細かな粒度に分割できるはずで,「請求・支払いをする人」や「給与計算をする人」「書類作成をする人」などの個々の登場人物が関わり合うことではじめて「経理部での仕事内容」が実現されます。
でももちろん,「会社全体を運営する」経営層の立場から,直接個々の登場人物をつなげて「経理部の仕事内容」を実現するのは大変です。できれば会社の経営層が「経理部さん,この仕事やってください」と仕事を投げたら,いい感じに内部で連携してやってくれる,そんな業務フローの単位があればいいですよね。それがDomain Service
です(だとおもっています)。
一般的なDDDの文脈におけるDomain Model
の意味範囲
ここまでオニオンアーキテクチャの一癖ある語彙について触れてきましたが,基本的にはDomain Model
と言われたら,これまで書いてきたような「登場人物」や「専門家のもつ知識」,「業務ロジック」等をまとめて指す,と考えてよさそうです。
このときDomain Model
は,Domain
領域を具体的にモデリングした結果(要するに,指し示す領域はDomain
と同じ)である,といえるでしょう。
そしてDomain Model
≒Domain
を内部にあるモノを大まかに分類すると,以下のようになるでしょう。
-
Entity
,Value Object
: 登場人物の実体を表現し,ひとりで実現できる業務ロジックやルールをカプセル化する -
Aggregate
: 集約。「登場人物」の一単位であり,属性をValue Object
やEntity
で表現する -
Service
: 複数のEntity
やValue Object
が関わり合って実現できる業務ロジックをカプセル化する -
Repository
: データの永続化や取得をインターフェース等を用いて抽象化する。2
Domain Service
と呼ぶのは大げさな,ちょっとしたロジックの,私なりの取り扱いを紹介します。
Entity
やValue Object
とは少し性質が異なるようにみえるが,一方でそれらの関係性をとりもつService
的役割を果たすわけでもない,というような微妙な立ち位置のロジック,すなわち日常語の意味での「ロジック」に近いモノを,そのままlogic
と名付けます。ディレクトリ構成でいえば/domain/logic
みたいな感じで配置します。service
ほど大きな粒度で登場人物を扱うわけではないが,実体がイメージしづらい「ロジック」や「ルール」をここで実装します。
まとめ
DDDにおける様々な用語の雰囲気・気持ちを改めて整理することで,「オニオンアーキテクチャにおけるDomain Model
」と「DDDのDomain Model
」の違いを考察してみました。
オニオンアーキテクチャにおいては,Domain Model
は登場人物に絞った意味で,Domain Service
はそれら登場人物を利用して実現できる,専門的な業務ロジックを表現したものである。
一方,より一般的なDDDの文脈では,Domain Model
は登場人物と業務ロジック全般,さらにリポジトリ等を包含する総合的な呼び名である。より細かい意味合いで分けるならEntity
やAggregate
,Service
などがある。
こうした解釈を行えば,DDDのクリーンアーキテクチャやオニオンアーキテクチャにおけるパッケージ構成やディレクトリ構成も考えやすくなるかもしれません。3
ここまでお読みいただきありがとうございました!
-
Domain Model
内部には,「ひとりで完結する仕事」がカプセル化されます。一方で,Domain Service
の責務は,「Domain Model
の関係を取り持って業務フローを実現する」といえます。 ↩ -
Domain
層にRepository
のインターフェースを置いてもよいか,という点はしばしば議論になります。厳密なDDDの理論ではDomain
層は値の永続化(要するにDBへの読み書き)に関心をもたない,とされるからです。ですが,データストアへの問い合わせをしなければ実現できないドメインロジックも存在するので,この辺りは妥協しても怒られないでしょう,と私は考えています。 ↩ -
たとえばディレクトリ構成に"src/domain/models"と"src/domain/services"とあれば,前者が「登場人物」 ,後者が「登場人物が関わり合って実現できるロジック」を格納しているのであろう,と推測します。
一方で"src/domain/entities"や"src/domain/valueObjects","src/domain/services"のような構成であれば,厳密に「登場人物」を分類しながら,単一の登場人物に収まりきらないロジックを切り分けているのだろう,と推測できます。
また,"src/domain"というディレクトリの配下に,ある程度大きな粒度でディレクトリが作られていたとしたら(このパターンが一番多そう),「登場人物」と「ロジック(サービス)」が一点にまとめられているのであろう,と推測できます。このとき,当然「登場人物」同士ではお互いに関心を持ちませんが,「ロジック(サービス)」は別領域の「登場人物」や「ロジック」に関心をもつ=依存する可能性があります。 ↩