DDD（ドメイン駆動設計）の復習part1

# ドメイン駆動設計とは
ドメイン駆動設計はソフトウェア開発手法の一つで、ドメインの知識に焦点をあてた設計手法です。
ドメイン駆動設計における「ドメイン」はソフトウェアが解決しようとしている特定の問題領域を指します。
ソフトウェア開発者は業務知識を深め、その知識をもとにしたドメインモデルを構築することで、ビジネス要件を直接的にソフトウェアに反映させることができます。これにより、ソフトウェアがビジネスの真のニーズを満たし本当に価値があるものとなるのです。

:::note info
「domain」という言葉の意味
![スクリーンショット 2024-12-15 13.31.46.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/326452/8438423b-5d22-913b-9458-854ab0c6f9a2.png)
DDDのドメインは5の「知識領域」のこと。
インターネットのドメインは2の「領土」のこと。
https://www.ei-navi.jp/dictionary/content/domain/
:::
## DDDのメリット、デメリット
AIに聞いてみた
<details><summary>Q. DDDのメリット、デメリットを教えて下さい</summary>

A. ドメイン駆動設計（DDD: Domain-Driven Design）のメリットとデメリットについて、できるだけ多く挙げてみます。
### DDDのメリット
1\. ドメイン理解の深さ
開発者とビジネス担当者が密に連携することで、システムが実際のビジネスドメインに密接に対応するようになります。これにより、ビジネス要求に即したシステムを作成できるため、ビジネス価値の高いソフトウェアが作成できます。

2\. 複雑なビジネスロジックの管理
ドメインを中心に設計を進めるため、複雑なビジネスロジックをシステマティックに整理し、管理しやすくなります。

3\. 境界づけられたコンテキスト（Bounded Context）
異なるドメインやサブドメインを明確に分けることで、それぞれのコンテキストにおける整合性を保つことができます。これにより、コンポーネント間の依存関係や複雑性が軽減されます。

4\. チーム間の共通理解
言語（ユビキタス言語）を統一し、開発チームやビジネス担当者の間で共通の理解を持つことで、コミュニケーションがスムーズになり、誤解が減少します。

5\. 保守性の向上
ドメインに基づいた設計がされているため、システムの変更や拡張が容易になります。ビジネスロジックがしっかりと抽象化されているため、新しい要件にも柔軟に対応できます。

6\. テスト容易性の向上
ドメイン駆動設計は、ドメインロジックのユニットテストをしやすくします。モジュール化されたアーキテクチャにより、テストが独立して実行でき、テストの精度も高くなります。

7\. スケーラビリティと分散開発
ドメインごとに独立したチームが作業することができ、マイクロサービスなどの分散システムにも適用しやすいです。これにより、大規模なシステムであっても効率的に開発が進められます。

8\. アーキテクチャの明確化
DDDは、システム全体のアーキテクチャを明確にするため、システム設計が一貫性を持ち、コードの品質が向上します。

9\. 進化するソフトウェア
ドメインの変化に対応しやすい設計となっているため、ビジネス要求が変化しても柔軟に対応可能です。長期的な視点でシステムの進化を支援します。

10\. ドメインオブジェクトの再利用
明確に定義されたビジネスロジックは特定のロジックからだけではなく、複数のロジックで使用することができます。

### DDDのデメリット
1\. 初期投資の大きさ
DDDを採用するには、初期段階でかなりの時間とリソースがかかります。ドメインの理解、ユビキタス言語の整備、アーキテクチャ設計など、多くの作業が必要です。

2\. 学習コスト
DDDの概念や技術を習得するためには、開発者やチームが一定の学習をしなければならないため、特に経験の少ないチームには負担となることがあります。

3\. オーバーエンジニアリング
小規模なシステムや単純なビジネスロジックを持つアプリケーションには、DDDを導入することが過剰になることがあります。過度に設計が複雑になり、オーバーエンジニアリングとなる可能性があります。

4\. 複雑なドメインの扱い
非常に複雑で不明確なビジネスドメインを持つシステムでは、DDDを適用することが難しく、ドメインを正しく理解すること自体が困難になる場合があります。

5\. コミュニケーションの必要性
DDDでは、開発者とビジネス担当者の密接な連携が求められます。これには継続的なコミュニケーションが必要ですが、コミュニケーションの質が悪い場合、DDDのメリットが十分に活かせません。

6\. パフォーマンスの問題
DDDの設計は、特にオブジェクト指向の設計に基づくため、パフォーマンスを最適化することが難しくなることがあります。特に大量のデータ処理を行う場合、パフォーマンスの低下が懸念されることがあります。

7\. 高度な技術的要求
DDDでは、エンタープライズアーキテクチャに関する高度な技術的知識が求められ、一般的な開発者にとっては敷居が高い場合があります。

8\. チームの協力と調整が難しい
チームが大きい場合、ドメインごとに分割されたコンテキストを調整することが難しくなる場合があります。境界づけられたコンテキスト間の調整を適切に行うことが重要ですが、これには労力がかかります。

9\. ドメイン知識の依存
DDDはドメイン知識に大きく依存しているため、そのドメインの専門家がいないと、設計や実装に困難を感じることがあります。外部のドメインエキスパートと協力する必要があります。

10\. ツールやフレームワークのサポートが不十分
DDDの考え方は非常に柔軟である一方で、既存のツールやフレームワークの多くは、このアーキテクチャスタイルに特化していないことがあります。これにより、設計に合わせたカスタムツールやフレームワークを開発する必要が生じることがあります。

11\. ソフトウェアの開発スピードが遅くなる可能性
DDDを採用することで、開発初期段階での設計に時間がかかるため、全体の開発スピードが遅くなる可能性があります。特に短期間でリリースを求められるプロジェクトでは、この点が問題になることがあります。
</details>

### メリット
#### 保守性の向上、ドメインの再利用性
```
ドメインに基づいた設計がされているため、システムの変更や拡張が容易になります。
ビジネスロジックがしっかりと抽象化されているため、新しい要件にも柔軟に対応できます。
```
```
明確に定義されたビジネスロジックは特定のロジックからだけではなく、複数のロジックで使用することができます。
```
DDDでは基本的にビジネスロジックは定められたクラスに定義されます。
さらに同じ関心事の処理に関しては同じクラスに定義するようにして凝集度を高め、役割ごとにレイヤーを分け依存の方向を固定することで結合度を下げ、複数のユースケースで使用できるようになり再利用性があがります。

#### 進化するソフトウェア
```
ドメインの変化に対応しやすい設計となっているため、ビジネス要求が変化しても柔軟に対応可能です。
長期的な視点でシステムの進化を支援します。
```

- トランザクションスクリプトパターン
ビジネスロジックを「スクリプト」または「手続き的なコード」として表現するアーキテクチャパターン。
基本的には、ビジネスロジックを個々の操作（例えば、注文の作成、支払い処理など）に対応する単一の手続きとして書く。

- テーブルモジュールパターン
ビジネスロジックを「テーブル」として管理し、各テーブルに関連する操作（例えば、ユーザーの作成や更新）を1つのモジュール（クラス）内で実装する。
各テーブルモジュールは、データベースの特定のテーブルに対応し、そのテーブルに関連する処理（CRUD操作など）を統一的に管理する。

ソフトウェアの進化に伴い複雑性が高くっても、機能追加や変更にかかるコストは比較的低くなりやすい

![20201110231849.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/326452/ff5f34bc-cdfd-33d2-f83e-a1f8478db905.png)


### デメリット
#### 初期投資の大きさ、オーバーエンジニアリング
```
DDDを採用するには、初期段階でかなりの時間とリソースがかかります。
ドメインの理解、ユビキタス言語の整備、アーキテクチャ設計など、多くの作業が必要です。
```
```
小規模なシステムや単純なビジネスロジックを持つアプリケーションには、DDDを導入することが過剰になることがあります。
過度に設計が複雑になり、オーバーエンジニアリングとなる可能性があります。
```

「進化するソフトウェア」で記載したメリットの一方で、DDDではドメインのモデリングを行う必要があったり、責務ごとにクラスを分ける性質上作成するファイルが多かったりと初期コストがかかりやすいです。
また、システムのビジネスロジックに複雑性がない場合オーバーエンジニアリングとなってしまい、DDDの本領を発揮できません。

#### パフォーマンスの問題
```
DDDの設計は、特にオブジェクト指向の設計に基づくため、パフォーマンスを最適化することが難しくなることがあります。
特に大量のデータ処理を行う場合、パフォーマンスの低下が懸念されることがあります。
```
DDDではビジネスロジックを「エンティティ」や「値オブジェクト」といったオブジェクトにカプセル化します。
そのためエンティティや値オブジェクトが多くなると、オブジェクトの生成やメモリ使用量が増加するため、パフォーマンスに悪影響を与えることがあります。

## ドメインモデルとは
モデルとは現実の事象あるいは概念を抽象化した概念です。
ドメイン駆動設計では特定の知識領域を抽象化したものをドメインモデルと呼びます。

### 良いモデルを作るには
重要な 2 つのアプローチがあります。
・ドメインエキスパートと会話する
・運用して得られた発見をモデルに還元する

#### ドメインエキスパートと会話する
ソフトウェアを有用なものにするには、まずドメインに詳しい人に話を聞くことが必要です。
ソフトウェア開発においてよくあるのは、十分にモデリングやヒアリングを行わず、開発者の部分的な理解のみで実装を進めてしまうパターンです。
そのような場合、求められているものとのすれ違いに気付くには時間がかかります。そして、気付いた時点ではすでにコードやデータが目指したい形とは大きく異なっており、大きな修正コストが必要になってしまいます。

#### 運用して得られた発見をモデルに還元する
リリースして運用してみたら意外な改善点があった、ということは必ず発生します。この発見をモデルに反映することが、モデルを改善するためのもう一つの重要な点です。
「最初からモデルは完成せず、徐々に改善して行くもの」という考えは DDD において非常に重要です。
モデルを頻繁に更新したら、コードも頻繁に変更する必要があります。コードは、そのような変更に耐えられる実装でなければなりません。これは、ソフトウェアにとっては、実はとても高い要求です。そして、それを達成するためのベストプラクティスが、エンティティやリポジトリといった戦術的設計パターンなのです。


![23edf9b5ca4f-20231004.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/326452/0a896a97-a5a4-2523-79c7-f02f2bb05d3b.png)



:::note info
なぜいまドメイン駆動設計なのか
近年ではDXの取り組みに伴い、クラウド環境でアプリケーション開発のアジリティを向上させるマイクロサービスアーキテクチャへの関心が高まっています。
DDDそのマイクロサービスと相性の良い設計手法として注目されています。

https://www.meti.go.jp/shingikai/mono_info_service/digital_transformation/pdf/20180907_01.pdf
:::