「ドメインモデル」はどこまで広い概念か？「ドメインサービス」との違いは？

# まえがき
ドメイン駆動設計（DDD）を勉強中の大学生です。

これまでDDDはふんわり理解したつもりでいたのですが，ふと**Domain Modelの意味範囲の広さには２通りあるのでは？** と感じました。
すなわち，**オニオンアーキテクチャの文脈における`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`は「知識」や「ロジック」などを表現し，カプセル化するものなので，それ以上の責務を持たせてはいけません。
ですからこれを作っただけでは意味がなく，必ず`Use Case`や`Application Service`層から操作する処理を書く必要があります。
逆に，`Domain Model`単体でアプリケーション全体の目標を達成できてしまうとすると，それはモデリング=関心事の凝集が不十分と捉えるべきです。DDDでは，中核となる部分（ドメインロジック，ビジネスルールとか？）と，それらを手続き的に操作する外側の部分に分けて考えます。(という認識です。) -->

# `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`は，**登場人物と，その登場人物ひとりの中にカプセル化「できる」専門知識やロジックをメソッドとして表現したもの**であるといえそうです。
いま，カプセル化<b>「できる」</b>と強調したことに気づかれましたか？これら`Domain Model`はアプリケーションの中核となる「知識」や「ロジック」を表現しますが，一方でそれら全てを表現し尽くすことは<b>「できない」</b>のです。

というのも，**複数の登場人物の関係性の中で初めて表現できる知識やロジック**もあるはずだからです。
ひと声で「これやって」と言われたら，登場人物たちをまとめて，いい感じに業務フローをまわすのもまた，**専門知識やロジック**であり，これらをカプセル化するのが`Domain Service`です[^DIFFERENCE]。
[^DIFFERENCE]: `Domain Model`内部には，「ひとりで完結する仕事」がカプセル化されます。一方で，`Domain Service`の責務は，「`Domain Model`の関係を取り持って業務フローを実現する」といえます。
> たとえば「**会社全体を運営する**」業務フローを考える時，「**経理部での仕事内容**」は十分に**中核**にあり**専門的**です。
  一方でこの「**経理部での仕事内容**」ももっと細かな粒度に分割できるはずで，「請求・支払いをする人」や「給与計算をする人」「書類作成をする人」などの**個々の登場人物**が関わり合うことではじめて「**経理部での仕事内容**」が実現されます。
  でももちろん，「**会社全体を運営する**」経営層の立場から，直接**個々の登場人物**をつなげて「**経理部の仕事内容**」を実現するのは大変です。できれば会社の経営層が「経理部さん，この仕事やってください」と仕事を投げたら，いい感じに内部で連携してやってくれる，そんな業務フローの単位があればいいですよね。それが`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`: データの永続化や取得をインターフェース等を用いて抽象化する。[^REPOSITORY]
[^REPOSITORY]: `Domain`層に`Repository`のインターフェースを置いてもよいか，という点はしばしば議論になります。厳密なDDDの理論では`Domain`層は値の永続化（要するにDBへの読み書き）に関心をもたない，とされるからです。ですが，データストアへの問い合わせをしなければ実現できないドメインロジックも存在するので，この辺りは妥協しても怒られないでしょう，と私は考えています。

> `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のクリーンアーキテクチャやオニオンアーキテクチャにおけるパッケージ構成やディレクトリ構成も考えやすくなるかもしれません。[^PACKAGE_COMPOSITION]
[^PACKAGE_COMPOSITION]: たとえばディレクトリ構成に"src/domain/models"と"src/domain/services"とあれば，前者が「登場人物」 ，後者が「登場人物が関わり合って実現できるロジック」を格納しているのであろう，と推測します。
一方で"src/domain/entities"や"src/domain/valueObjects"，"src/domain/services"のような構成であれば，**厳密に「登場人物」を分類しながら**，単一の登場人物に収まりきらないロジックを切り分けているのだろう，と推測できます。
また，"src/domain"というディレクトリの配下に，ある程度大きな粒度でディレクトリが作られていたとしたら(このパターンが一番多そう)，「登場人物」と「ロジック（サービス）」が一点にまとめられているのであろう，と推測できます。このとき，当然「登場人物」同士ではお互いに関心を持ちませんが，「ロジック（サービス）」は別領域の「登場人物」や「ロジック」に関心をもつ＝依存する可能性があります。

ここまでお読みいただきありがとうございました！