ドメイン駆動設計についての理解まとめ：用語より、基本思想を掴もう

最近、[ドメイン駆動設計入門](https://www.shoeisha.co.jp/book/detail/9784798150727)という本を読んだ。この本では、値オブジェクトやドメインサービスなど、多くの概念が紹介されているが、それらの概念を全力で理解しようとした結果、ドメイン駆動設計の基本的な考え方がかえって理解しにくくなってしまった。

そこで英語で情報を検索し、いくつかの資料を読んだ後、特にエリック・エバンス本人の講演動画（[What is DDD - Eric Evans - DDD Europe 2019](https://www.youtube.com/watch?v=pMuiVlnGqjk)）を視聴した。これにより、DDDの基本的な考え方についてなんとなくイメージが付いたと思うので、メモとして残しておく。

## ドメイン駆動設計とは

ドメイン駆動設計（DDD）は、ソフトウェアを設計するためのアプローチであり、**ビジネスドメインの知識に焦点を当て、その知識をソフトウェアモデルに抽象化する**。

「ドメイン」とは、ビジネス領域の特定の知識のこと。 例えば、銀行業界のドメインには、口座、取引、顧客、支店などの概念が含まれる。

### ドメインを重視する理由

なぜドメインから始めるのかというと、ソフトウェアは最終的にユーザーに使用されるものであり、ビジネスシナリオは非常に複雑である可能性があるからだ。 

特定のビジネスに関する十分な知識がなければ、エンジニアが自分の理解に基づいてソフトウェアを設計しても、それがユーザーの実際のニーズを満たすことができないかもしれないし、ビジネスの変化に対応できない可能性が高くなり、最終的にはソフトウェアプロジェクトが失敗する原因になる。

## ドメインの知識をモデルに抽象化する方法

DDDの提案する解答は、ビジネスドメインの専門家と密接に協力して、ビジネスドメインの複雑さと詳細を理解すること。

エリック・エバンスは講演で、彼らが使う言葉に注意深く耳を傾けることが重要だと述べている。

**ビジネスの専門家がビジネスを説明するときに使う語彙や例に注意深く耳を傾けることで、モデル化される概念が明らかになる。**

また、キーワードを探すことも重要であり、エバンスは完璧な解決策を見つけようとすることに注意を促した。万能のように見える完璧なモデルで問題を説明するのは大きな間違いだと。

ビジネスの専門家が**これらの用語をどのように表現しているか**に特に注意を払う。 これらの言葉を記録し、擬似コードを書くのに使うことができる。

講演動画の中で、エバンスはある物流システムを例に挙げている。 このシステムでは、カーゴという一つのモデルと輸送ルートを処理するルーティング・サービスを使っている。

しかし、ビジネスの専門家の説明をよく聞いてみると、カーゴ(貨物)、旅程、ストップ、区間といった複数の用語を使っていることがわかる。

貨物は、出発地と目的地を含む旅程を持ち、旅程には複数の区間があり、それぞれが異なるストップを通過し、異なるストップを通過する際に荷下ろしと荷積みを行う場合がある。 

ビジネスシナリオがこれらの用語で記述されると、モデルはより自然に構築できるだろう。

### ユビキタス言語(共通言語)

DDDでは、ビジネスの専門家と開発者の間に共通言語が必要であり、この言語はユビキタス言語（共通言語）と呼ばれる。

この共通言語は通常、ビジネスドメインの概念を記述するために使用されるドメイン専門用語であり、この言語はビジネスの専門家と開発者の間のコミュニケーションと理解の架け橋となる。

より一般的には、ある概念について、ビジネスの専門家とエンジニアは同じ語彙を使って記述する必要がある。

例えば、私の仕事上は、単発なアンケート調査をアドホックと呼ぶ。 

個人的には単発的調査と表現したいが、クライアントとのコミュニケーションでは、アドホックと表現した方が圧倒的に共通理解が得やすい。

DDDでは、**すべてのクラス、すべてのメソッド、すべての変数が、ビジネスと一貫性のある方法で注意深く命名されるべき**と強調。

それによって語られるストーリーが、あなたが書いているビジネスのストーリーになると考えている。 将来、顧客やユーザーと新機能やエラー報告について議論するとき、お互いを理解することが容易になると。

**つまり、コード自体がビジネスの現実を反映すること。**


### 境界づけられたコンテキスト(Bounded Contexts)

DDDにおけるもう一つの重要な概念は、「境界づけられたコンテキスト」である。

言語をモデルに抽象化するとき、異なるモデル間の境界にも注意を払う必要がある。

例えば、私が最近担当した案件では、ある製品のコンセプト調査がすでにクライアントのシステムに存在しており、アクティビティ、ジョブ、コンセプトなどの概念が使用されていた。

しかし、クライアントが製品の広告調査を追加する必要があるとき、アクティビティ、ジョブ、コンセプトなどの概念も使用されているにもかかわらず、これらの概念の内容は少し異なっている。 これは、コンセプト調査と広告調査のビジネスシーンや目的が異なるからだ。

また、クライアント企業内では、将来的にこの2つの調査種類は異なる部署が管理する可能性もあるので、モデルを設計する際には、混乱を避けるために、この2つのモデルの境界を考慮する必要がある。

このように理解すると、実は単一責任原則と共通するかもしれない。後者は、モデルが1つの責任しか持てないだけでなく、**1人または一つの関連する代表的なグループのみ**に対して責任を負うべきであることを強調している。

## モデリングに使用できるテクニック

上記の基本概念を理解した後、DDDはこれらのモデルをコードで実装する方法について、Entity、Value Object、Repository、Factory、Aggregate、Service、Domain Eventなど、多くの概念を紹介する。

これらの概念を最初に理解しようとすると、迷子になりやすいし、中には本当に混乱しやすい概念もあると思う。

このブログ([DDD 101 - The 5-Minute Tour](https://medium.com/the-coding-matrix/ddd-101-the-5-minute-tour-7a3037cf53b8))が非常にわかりやすく要約しているので、ここに原文から直接引用することにする。

> You model your business using Entities (the ID matters) and Value Objects (the values matter). You use Repositories to retrieve and store them. You create them with the help of Factories. If an object is too complex for a single class, you’ll create Aggregates that will bind Entities & Value Objects under the same root. If a business logic doesn’t belong to a given object, you’ll define Services that will manipulate the involved elements. Eventually, when the state of the business changes (a change that matters to business experts), you’ll publish Domain Events to communicate the change.

- **エンティティ**（IDが重要）と**値オブジェクト**（値が重要）でビジネスをモデル化する
- それらを取得および保存するために**リポジトリ**を使用
- モデルの作成が複雑だったら、**ファクトリ**を使う
- オブジェクトが単一のクラスに複雑すぎる場合、エンティティと値オブジェクトを同じルートの下にバインドする**アグリゲート**を作成する
- ビジネスロジックが特定のオブジェクトに属さない場合、関連する要素を操作する**サービス**を定義する
- 最終的に、ビジネスの状態が変化すると（ビジネス専門家にとって重要な変化）、**ドメインイベント**を発行して変更を通知する


以上はドメイン駆動設計について、現段階の基本理解だけど、今後理解を深くするため、原書を読む予定。

参照
- [DDD 101 — The 5-Minute Tour](https://medium.com/the-coding-matrix/ddd-101-the-5-minute-tour-7a3037cf53b8)
- [Anemic Domain Model](https://www.martinfowler.com/bliki/AnemicDomainModel.html)
- [Domain-Driven Design (DDD)](https://www.geeksforgeeks.org/domain-driven-design-ddd/)
- [The Single Responsibility Principle](https://blog.cleancoder.com/uncle-bob/2014/05/08/SingleReponsibilityPrinciple.html)