ドメイン駆動設計（DDD）についての整理

## 序論
ドメイン駆動開発（以下、DDDと記述します。）について、誤解していたことや新たに学んだことについて書いてみます。

##ドメインとは何か？
まず始めに、「ドメインとは何か？」という質問に答えられなければなりません。一体「ドメイン」とは何でしょうか？何故それを基にして開発を行う必要があるのでしょうか。

この質問に対する答えとして、エリック・エヴァンスは著書『ドメイン駆動設計』の第1部で次のように述べています。

>「すべてのソフトウェアプログラムは、そのソフトウェアを使用するユーザーの活動や関心事に関連しています。ユーザーがプログラムを使用する対象領域が、そのソフ> トウェアのドメインです。」

これだけではまだピンとこないかもしれません。そこで今度は、「一体ソフトウェアって何なのか？」という疑問が生まれるかもしれません。

著者は続けて本の中で次のように述べています。

> 「ソフトウェアの本質は、そのソフトウェアのユーザーのためにドメインに関連する問題を解決する能力にあります。」

## ドメインモデルを作る過程
そうです。ソフトウェアのユーザー（以下、ユーザーと呼びます）は日常生活で不便さを感じています。

例を挙げてみましょう。ある観光客がタクシーに乗る必要がある状況になったとします。しかし、その道はタクシーがあまり通らない場所であったり、雨の日にはタクシーをつかまえるのが難しいこともあります。不便ですね！

このようにして、私たちはユーザーのニーズ（不便さ）を捉える必要があります。そして、その不便さを解決するためにソフトウェアを開発するのです。

よし！さっきの例で私たちは問題を捉えました。

さて、ユーザーの問題を解決するためにソフトウェアを作ってみましょう。しかし、いざコーディングを始めようとすると、どうしていいのかわからず頭が痛くなります。どうやって開発すればいいのか？どこから始めればいいのか？まずはフレームワークを決めるべきでしょうか？でも、ユーザー数が増えることを考えると、Redisでキャッシュをしなければならないし、可用性を確保するためにKubernetesも構築しなければならないし……。
ドメイン駆動開発のやり方に関する本でも買って読もうかな？

うわぁ！

間違っていました。ドメイン駆動開発というのは、そういったものではありません。

不明確な目標、リソースの不足、官僚主義などのさまざまな問題で、私たちのプロジェクトは軌道から逸脱しています。

もう一度考えてみましょう……Redis、Kubernetes、フレームワーク……。今、技術的なことばかり追いかけているのではないでしょうか？

多くの開発者は自分の技術を磨き、次々と進化する技術を追いかけています。しかし、最も重要なことはその技術的複雑さではありません。

問題は、高可用性を確保し、どれだけの人が集まり、費用がどれだけかかるかという技術的な側面が本当の問題ではないということです。

最も重要な問題は、まさに「ユーザーが不便に感じている問題」そのものです！

どんなに優れた開発者がいても、どんなに良いプログラムがあっても、ユーザーが使わなければそれはソフトウェアとは言えません。

元に戻ってもう一度問題を定義しましょう。

ユーザーの問題は何だったでしょうか？それは、「雨の日にタクシーを捕まえるのが難しい」ということでした。

では、私たちが定義すべき問題は何でしょうか？それは、「タクシーを簡単に捕まえられるようにする」ということです。

よし、これで私たちはドメインモデルを作成しました。ソフトウェア開発の第一歩を踏み出しました。

> ほとんどのソフトウェアプロジェクトでは、まず最初にドメインとドメインロジックに集中する必要があります。
> 複雑なドメイン設計は、モデルを基盤にするべきです。
~~ eric evansの「domain driven design」序文より抜粋 ~~

## 知識の探求を通じて意義あるドメインを作る

開発を始めました。

どのように開発を進めるのか。通常、会社やチームにはドメインの専門家がいます。
(ここで言う専門家とは、CEOや社長、チームリーダーなどの決定権者を指します。)

私たちは彼らの提供する資料をもとに設計を始めます。

「8月30日までに完成させてみますね。」

しかし、そうはうまくいきません。少なくとも私はそうです。

あれ…なんでうまくいかないんだろう？果たして私は期限を守れるだろうか？

> ソフトウェアを書き始めるとき、私たちは十分に理解していない状態で始めます。

私はタクシー業界がどのように成り立っているかをよく知らず、知識は断片的であり、チーム内の知識もあちこちに散らばっています。

私たちは未知の要件に直面することもあるでしょうし、ドメインの専門家からは絶えず変化する要件が伝えられるでしょう。

「知識が漏れている。」

## 一体なぜそのようなことが起きるのでしょうか？

昔のソフトウェア開発者たちは、ほとんどがウォーターフォール(Waterfall)という手法を採用していました。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3815412/b27b9c51-3b24-6a8e-77f6-7d4a7f57b464.png)

> 要件分析 → 設計 → 実装 → 検証（テスト）→ 保守

問題が見えませんか？

スケジュールを立てる段階では見えなかった多くの問題が、確かに私たちの行く手を阻むでしょう。そして、私たちはまた最初からこのプロセスを繰り返すことになり、結果的にスケジュールを守ることができなくなるでしょう。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3815412/7560c313-448b-4ce1-0ca7-e89a8d9ca0e3.png)

## ユビキタス言語とドメイン駆動開発の核心、アジャイル手法

### Manifesto for Agile Software Development

> We are uncovering better ways of developing software by doing it and helping others do it.
Through this work we have come to value:
Individuals and interactions over processes and tools
Working software over comprehensive documentation
Customer collaboration over contract negotiation
Responding to change over following a plan
That is, while there is value in the items on the right, we value the items on the left more.
© 2001, the Agile Manifesto authors
This declaration may be freely copied in any form, but only in its entirety through this notice.

> 私たちは、ソフトウェアを開発することと、他の人々がそれを行うのを支援することで、より良い方法を発見しています。
この作業を通じて、私たちは以下のことを重視するようになりました：
プロセスやツールよりも個人と対話を重視します
包括的なドキュメントよりも動作するソフトウェアを重視します
契約交渉よりも顧客との協力を重視します
計画に従うことよりも変化への対応を重視します
つまり、右側の項目に価値がないわけではありませんが、私たちは左側の項目をより重視します。
© 2001 アジャイル宣言の著者
この宣言は、この通知を通じてその全体としての形で自由にコピーされることができます。

https://www.agilealliance.org/agile101/the-agile-manifesto/

そうです。曖昧な要件を解決するために、アジャイル手法は次のように述べています。

- プロセスやツールよりも個人との対話（つまり、チームメンバーとの議論やユビキタス言語）
- 包括的な文書よりも動作するソフトウェア（前述のソフトウェアの本質）
- 契約交渉よりも顧客との協力（ドメインモデル、ソフトウェアの本質）
- 計画に従うよりも変化に対応すること（TDD、リファクタリング、OOP、XPなど）
ドメイン駆動設計の序文には次のように書かれています。

「この本は特定の手法に縛られませんが、『アジャイル開発プロセス』という新しい流れを目指しています。特に、以下の2つの実践がプロジェクトの進行中に行われることを想定しています。この2つの実践は、本書のアプローチ（ドメイン駆動開発）を実行するための前提条件です。」

> 1. 開発は反復的なサイクルに基づいて進められるべきです
> 2. 開発者とドメインの専門家は密接な関係を築く必要があります

## モデル駆動設計とユビキタス言語

アジャイルの核心は、ドメイン駆動開発をうまく行うための鍵です。

以前に述べたように、私はチームと共にドメインについて十分に知識がありません。一方で、プロジェクトの責任者はコードに詳しくありません。

どうすればいいのでしょうか？

それは、定期的に短い目標を持ってディスカッションを行うことです。これはまるでパズルのピースを埋める行為のようです。

最初は私たちがドメインをよく知らず、責任者も私たちのコードを知らないので、非常に小さな単位を設定し、定期的に繰り返し議論と意見交換を行います。こうして徐々に私たちのドメインモデルが何であるかを意見を合わせていくのです。

そうしているうちに、プロジェクトの方向性が見えてくるでしょう。できるだけ小さなドメインモデルで、できるだけ小さな問題を定義する必要があります。以前のタクシーの例を用いると、以下のように考えます。

- ユーザーが通りに出る -> タクシーを探す -> タクシーが来たら手を挙げる -> タクシーに乗る -> 目的地を告げる -> 料金を計算する -> 降車

それでは、まず大きなドメインモデルを定義する必要がありますね。私たちのチームはディスカッションを通じて、以下の流れをソフトウェアとして実現することをドメインモデルとして定義しました。

- タクシーを探す -> タクシーが来たら手を挙げる -> 目的地を告げる -> 料金を計算する

どうですか？ 少し明確になりましたか？

これからはドメインの専門家と絶えずディスカッションをする必要があります。チーム全員が、自分たちのプロジェクトをユーザーに届けるために、それぞれの責任を果たさなければなりません。

さあ、ディスカッションを始めました。開発者がドメインの専門家に開発用語を説明しても理解できないでしょうし、ドメインの専門家が開発者にドメイン用語を説明しても理解できないでしょう。

それでは、どうすればいいのでしょうか？

文書に残すべきでしょうか？それともコーディングを教えるべきでしょうか？

これまでの文章をすべて読んでいただければ、次のような答えを導き出すことができるでしょう。

「ユーザーに合わせること」、つまりドメインに関する言語をコードへ自然に組み込むことです。

そうすれば、開発者は要件（ドメインの変更）に合わせてリファクタリングを行い、迅速に対応できるようになります。なぜなら、ドメインがすなわちコードだからです。たとえば、Userというテーブルがあれば、ドメイン管理者にとってはそれが会員（すなわちユーザー）であり、コードでもUser、すなわちユーザーです。

ドメインをそのままコードに移すためには、オブジェクト指向プログラミング（OOP）を使用することが効率的だと思います。（これはいつか新しい記事で詳しく書くつもりです）

しかし、ここで疑問があります。それでは、開発者はドメインの専門家に従わなければならないのでしょうか？

答えは「いいえ」です。開発者はチームの一員として、私たちのコードを保護し、正しい方向に進む責任があります。もし技術的に制限がある場合や、このドメインをコードで表現するのが難しい場合は、その問題を説明し、より良い方向へ進むためにディスカッションを行う必要があります。

文書は必要でしょうか？私たちはコードでドメインを表現しましたが。

以前述べたように、契約交渉よりも顧客との協力、包括的な文書よりも動作するソフトウェアを重視します。

アジャイルやドメイン駆動開発、ソフトウェアの本質について少し理解が深まりましたか？

> そして、私たちのチームが定めたドメイン用語が、ユビキタス言語です。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3815412/cd0a3f0c-9611-8101-9da5-7b2c4d9d3280.png)

ふふ、図を描くのは簡単ではないですね。

## 説明を続けます

文書はあくまでも補足説明です。
コードを見れば、私たちのドメインが理解できるようにすべきです（新卒者が会社に入ってきたとしても）。
文書はコードを補完する説明であり、コードがすでにうまくやっていることを文書で行おうとしてはいけません。
文書は常に最新の状態で保たれなければならず、プロジェクトの活動と関連していなければなりません。
...

## ドメイン駆動設計の第1章を振り返って

ドメイン駆動開発を行う理由はとても簡単です。それは「私たちのコードを上手に書くため」です。

ある意味では、OOPやさまざまなデザインパターンを使う理由と同じです。ドメイン駆動開発には、技術的な要件は含まれていません。目的は次の通りです。

変更に柔軟に対応できるコードを書くため
ユーザーが使用するコードを書くため
このために、ドメインの専門家と協力し、素早く問題に対応し、人と交流します。

ユーザーの問題を理解し、ドメイン（問題）を定義し、それを解決するためにドメインをコードに移す努力をしているのであれば、それがドメイン駆動開発です。

あなたが関数型プログラミングをしようが、オブジェクト指向プログラミングをしようが、どのようなデザインパターンを採用しようが、あなたはドメイン駆動開発を行うためにさまざまなツールを活用しているのです。

開発者がドメインを理解し、徹底してユーザー中心にユーザーの不便を減らしましょう。これがドメイン駆動開発の第1章の内容のすべてです。

第2章の要約に入る前に、次の記事では「ドメイン駆動開発とレイヤードアーキテクチャ」についてお話しします。Springのサービスやリポジトリという概念を見ながら、ドメイン駆動開発がレイヤードアーキテクチャのどのような面を採用しているのかについてお話しします。

え？ドメイン駆動開発がレイヤードアーキテクチャじゃないんですか？いいえ。私たちはドメイン駆動開発を行うために便利なデザインを採用しているだけです。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3815412/92fc25b0-4ef1-1596-c43c-f6e25e9f4738.png)


## 終わりに

私は韓国人として、日本語を勉強するためにChatGPTやPapago、Google翻訳を活用してこの文章を書きました。

文脈が不自然だったり、おかしな部分が多いかもしれません。
ご指摘いただければ学んでいきます。

技術的なフィードバックもいつでも歓迎します。

ありがとうございます。よい一日をお過ごしください。

日本語、正直まったくわかりませんね…まだ一歩踏み出したばかりですが、頑張らなければなりません。
私が翻訳機を使って作成した文章をすべて理解できるようになれば、日本語で会話できるようになるでしょうか？

## レファレンス

Eric Evans『Domain-Driven Design』
チョ・ヨンホの「ドメイン駆動開発 事実と誤解」講義を受講