[速習] ドメイン駆動設計(DDD) 第1回 ソフトウェアのプロフェッショナルへの道 (レイヤードアーキテクチャと依存性の逆転/境界づけられたコンテキスト)

![k02.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3521573/df8b4299-8c0f-f7af-b67c-82122bdfbf4d.png)

https://qiita.com/ShigemoriMasato/items/73d25705f7db1b692047

前回の記事では、GPT-4 32kを用いたドメイン駆動設計(DDD)の新しい設計手法について説明しました。GPT-4 32kの大規模なコンテキストサイズを活用することで、複雑なタスクも無理なく実行でき、設計プロセスの効率化を大いに進めることができました。また、設計と実装の間のギャップを最小限に抑えることができ、開発者はドメインの複雑さを容易に理解し、それを反映した設計を効率的に行うことができました。これにより、新たな開発体験が実現しました。

今回は、前回の記事とは別に、ドメイン駆動設計(DDD)の具体的な概念と実装について掘り下げていきます。

## ドメイン駆動設計

ソフトウェア開発はビジネス要件の理解と技術的な実装という二つの側面を持つ複雑なプロセスであり、それらを適切に結びつけることが重要です。その解決策としてエリック・エヴァンスはドメイン駆動設計(DDD)を提唱しました。DDDはビジネス要件（ドメイン）を中心に設計と実装を進める方法で、これによりビジネス要件の理解を深め、それを反映した高品質なソフトウェアの作成を可能にします。また、DDDはビジネス担当者[^1]と技術者[^2]の間のコミュニケーションギャップ[^3]を解消する手法も提供します。

https://www.seshop.com/product/detail/20690

DDDの主な目的は、ビジネス要件[^4]の理解を深め、それを反映した高品質なソフトウェアを作ることです。

```mermaid
graph LR
  A[ドメイン駆動設計] --> B1[ビジネス要件の理解]
  A --> B2[技術的な実装]
  B1 --> C1[ドメインエキスパート]
  B1 --> C2[ユビキタス言語]
  B2 --> C3[レイヤードアーキテクチャ]
  B2 --> C4[境界づけられたコンテキスト]
  C3 --> D1[依存性の逆転]
  C4 --> D2[モデルの境界の明確化]
```

## レイヤードアーキテクチャと依存性の逆転

レイヤードアーキテクチャ[^5]は、ソフトウェアの設計パターンであり、その構造を複数の層に分割します。これらの層は一般的にプレゼンテーション層、アプリケーション層、ドメイン層、インフラストラクチャ層の4つで構成され、それぞれが特定の役割を果たします。具体的には、プレゼンテーション層がユーザーインターフェースを、アプリケーション層がビジネスロジックのコーディネート[^6]を、ドメイン層がビジネスルール[^7]の定義を、インフラストラクチャ層がデータの永続性[^8]や外部システムとの通信[^9]を担当します。

**プレゼンテーション層** アプリケーションのユーザーインターフェース(UI)を管理し、ユーザーからの入力を受け取り、結果を表示します。この層はユーザーがアプリケーションと対話できるようにするインターフェースを提供し、ユーザーの要求を下位の層に伝達します。具体的には、フロントエンドとサーバーサイドの両方が含まれます。フロントエンドはUIを管理し、サーバーサイドはユーザーの要求を処理し、結果をフロントエンドに伝達する役割を担当します。

**アプリケーション層** アプリケーションのビジネスロジックのコーディネートとシステムのユースケースの実装を担当します。具体的には、ユーザーの要求を処理し、必要なビジネスルールと計算を適用し、システムが行うべき仕事（ユースケース）を実装する役割を果たします。この層は、ユーザーからの要求に応じてビジネスロジックを適用し、ユースケースを実行し、結果をプレゼンテーション層に伝達します。

**ドメイン層** アプリケーションのビジネスルールの定義を担当します。これはアプリケーションのビジネスロジックを表現するもので、ビジネスロジックの実装を提供します。この層は、ビジネスロジックを定義し、アプリケーション層がビジネスロジックを適用するためのメソッドやインターフェースを提供し、ドメインモデル(集約ルート)を管理します。

**インフラストラクチャ層** アプリケーションのデータの永続性、外部システムとの通信、そしてセッション管理を担当します。具体的には、データの保存と取得を担当し、データベースとの対話を管理します。さらに、ユーザーのセッション情報の管理もこの層の責任です。これにより、ユーザーがシステムにログインしてからログアウトするまでの間、ユーザーの状態やアクティビティを追跡し、必要に応じてこれらの情報を利用します。この層は、アプリケーションの永続性の詳細を処理し、データベースや外部システムとの通信、そしてセッションの維持と管理を担当します。

このように**各層の責任と関心事が明確に区分け**されることで、保守性と再利用性が向上します。

```mermaid
graph LR
    UI["プレゼンテーション層<br>ユーザーインターフェース(UI)"]
    AL["アプリケーション層<br>サービス"]
    DL["ドメイン層<br>ビジネスロジック"]
    IL["インフラストラクチャ層<br>データアクセス"]
    UI -->|リクエスト| AL
    AL -->|ビジネスロジックを実行| DL
    DL -->|データ操作| IL
    IL -->|データを返す| DL
    DL -->|結果を返す| AL
    AL -->|レスポンスを表示| UI
```

一方、依存性の逆転の原則は、ソフトウェアコンポーネント間の依存関係を管理するためのガイドラインです。この原則は、上位レベルのポリシーが下位レベルの詳細に依存しないようにすることを目指します。具体的には、**抽象に対してのみ依存することで、上位レベルのポリシーを具体的な実装から独立させることが可能**となります。これにより、システムの各部分を独立してテスト、保守、再利用することが可能となり、ソフトウェアの柔軟性と再利用性が向上します。

```mermaid
graph RL
    subgraph "プレゼンテーション層"
        Controller[Controller]
    end
    subgraph "アプリケーション層"
        Service[Service]
    end
    subgraph "ドメイン層"
        Model[Model]
    end
    subgraph "インフラストラクチャ層"
        Repository[Repository]
    end
    Database[Database]
    Request[Request] --> Controller
    Controller --> Service
    Service --> Model
    Model --> Repository
    Repository --> Database
    Database --> Repository
    Repository --> Model
    Model --> Service
    Service --> Controller
    Controller --> Response[Response]
```

レイヤードアーキテクチャと依存性の逆転の原則は、ソフトウェア設計において密接に関連しています。レイヤードアーキテクチャはソフトウェアの構造を整理し、各層の責任を明確にします。一方、依存性の逆転の原則は各層間の依存関係を適切に管理し、具体的な実装から上位レベルのポリシーを独立させることで、ソフトウェアの柔軟性と再利用性を向上します。これらの原則を組み合わせることで、**高品質で保守性の高いソフトウェアを設計・実装することが可能**となります。

他にも3層アーキテクチャ[^10]、ヘキサゴナルアーキテクチャ[^11]、オニオンアーキテクチャ[^12]、クリーンアーキテクチャ[^13]などのアーキテクチャも存在します。これらのアーキテクチャもDDDと相性が良く、それぞれが特定の問題を解決するために設計されています。

https://qiita.com/ShigemoriMasato/items/c0e015098730d93a188b

## 境界づけられたコンテキスト

境界づけられたコンテキストは、ドメイン駆動設計(DDD)の中心的な概念であり、特定のビジネスモデルが適用される範囲を明確に定義します。この概念は、大規模なシステムを小さな管理しやすい部分に分割し、各部分が独立して機能できるようにします。以下に、境界づけられたコンテキストの主要な特性を詳述します。

**モデルの適用範囲の明確化** 境界づけられたコンテキストは、モデルが適用すべき範囲と、適用すべきでない範囲を明確に区別します。これにより、モデルの適用範囲とその役割が明確になり、モデルの複雑さを管理しやすくなります。

**異なるコンテキスト間の関係管理** 境界づけられたコンテキストは、異なるコンテキスト間の関係性も管理するのに役立ちます。これは、コンテキストマップを使用して視覚的に表現され、各チームはどのコンテキストが他のコンテキストに影響を与えるかを理解し、適切に管理することができます。

**ユビキタス言語の使用** 境界づけられたコンテキスト内では、ユビキタス言語という共通の言語を用いてコミュニケーションを行います。これは、特定のコンテキスト内で共有される共通の言語であり、ビジネス要件の誤解を防ぎ、要件の正確な理解と実装を促進します。

**システムの分割と集中** 境界づけられたコンテキストを用いることで、大規模なシステムを小さな管理可能な部分に分割することができます。これにより、各チームは自身のコンテキストに集中し、他のコンテキストの詳細に気を取られることなく、高品質なソフトウェアを効率的に開発することが可能となります。

```mermaid
graph TB
    A[境界づけられたコンテキスト]
    subgraph "モデルの適用範囲の明確化"
        B[モデルの適用と非適用の区別]
        C[モデルの役割の明確化]
    end
    subgraph "異なるコンテキスト間の関係管理"
        D[コンテキストマップの作成]
        E[影響範囲の理解と管理]
    end
    subgraph "ユビキタス言語の使用"
        F[共通の言語の定義と使用]
        G[誤解の防止と要件の正確な理解と実装]
    end
    subgraph "システムの分割と集中"
        H[大規模なシステムの分割]
        I[各部分の独立した機能]
    end
    A --> B
    A --> D
    A --> F
    A --> H
    B --> C
    D --> E
    F --> G
    H --> I
    B -. "影響" .-> D
    C -. "影響" .-> E
    D -. "影響" .-> F
    E -. "影響" .-> G
    F -. "影響" .-> H
    G -. "影響" .-> I
```

境界づけられたコンテキストは、モデルの適用範囲を明確にし、異なるコンテキスト間の関係を管理し、ユビキタス言語を使用してコミュニケーションを行うことで、システムを分割し、各部分に集中することを可能にします。これらの特性により、境界づけられたコンテキストは、高品質で保守性の高いソフトウェアを設計・実装する上で不可欠な要素となります。

https://note.com/happyodangoo/n/n27e31289eb78?from=notice

## おわりに

DDDは、ビジネス要件の理解を深め、それを反映した高品質なソフトウェアを作ることを目指します。また、ビジネス担当者と技術者の間のコミュニケーションギャップを解消する手段を提供します。これらの考え方が、あなたのソフトウェア開発をよりスムーズに、そして高品質に進めるための一助となれば幸いです。

```mermaid
graph LR
    A[ドメイン駆動設計]
    B[ビジネス要件の理解]
    C[技術的な実装]
    D[ユビキタス言語]
    E[レイヤードアーキテクチャ]
    F[境界づけられたコンテキスト]
    G[プレゼンテーション層]
    H[アプリケーション層]
    I[ドメイン層]
    J[インフラストラクチャ層]
    K[依存性の逆転]
    L[モデルの境界の明確化]
    M[コンテキスト1]
    N[コンテキスト2]
    O[コンテキスト3]
    P[ユーザーインターフェースの管理]
    Q[ビジネスロジックのコーディネート]
    R[ビジネスルールの定義]
    S[データの永続性と外部システムとの通信]
    T[上位レベルのポリシー]
    U[下位レベルの詳細]
    V[ユーザーからの入力受け取り]
    W[データや結果の表示]
    X[ユーザーの要求の処理]
    Y[必要なビジネスルールと計算の適用]
    Z[ビジネスロジックの定義]
    AA[データの保存と取得]
    AB[データベースとの対話の管理]
    A --> B
    A --> C
    B --> D
    C --> E
    C --> F
    E --> G
    E --> H
    E --> I
    E --> J
    E --> K
    F --> L
    F --> M
    F --> N
    F --> O
    G --> P
    H --> Q
    I --> R
    J --> S
    K --> T
    K --> U
    P --> V
    P --> W
    Q --> X
    Q --> Y
    R --> Z
    S --> AA
    S --> AB
    M -->|関係| N
    N -->|関係| O
    O -->|関係| M
```

DDDは複雑なビジネス要件と技術的な実装を効果的に結びつける強力なツールであり、その理解と適用は現代のソフトウェア開発において非常に重要です。

[^1]: **ビジネス担当者** - 企業や組織における業務を担当する人。ビジネス要件の定義やプロジェクトの管理などを行う。
[^2]: **技術者** - 技術的な専門知識を持ち、ソフトウェアの設計や開発、テストなどを行う人。
[^3]: **コミュニケーションギャップ** - 情報の伝達における誤解や不足。ビジネス担当者と技術者の間では、専門知識や言葉の違いから生じることが多い。
[^4]: **ビジネス要件** - ソフトウェアが満たすべきビジネス上の要求。具体的な業務のルールや目標などを含む。
[^5]: **設計パターン** - ソフトウェア設計における典型的な問題とその解決策をまとめたもの。再利用可能な設計のテンプレートとして機能する。
[^6]: **ビジネスロジックのコーディネート** - ビジネスロジックの流れや処理の順序を管理すること。アプリケーション層で主に行われる。
[^7]: **ビジネスルール** - ビジネスの運用を決定するルールや方針。これをソフトウェアに反映させることで、ビジネスプロセスを自動化する。
[^8]: **データの永続性** - システムが停止してもデータが保持される性質。データベースなどの永続化技術を用いることで実現する。
[^9]: **外部システムとの通信** - ソフトウェアが他のシステムとデータをやり取りすること。APIやデータベース接続などの技術を用いる。
[^10]: **3層アーキテクチャ** - ソフトウェア設計の一般的なパターンで、アプリケーションを3つの水平層に分割します。各層は特定の種類のタスクを担当し、上位の層が下位の層に依存します。
[^11]: **ヘキサゴナルアーキテクチャ** - アプリケーションのビジネスロジックを中心に、入出力をポートとアダプターを通じて抽象化します。これにより、ビジネスロジックと外部の世界との依存性を分離し、テストや保守を容易にします。
[^12]: **オニオンアーキテクチャ** - 内部から外部へとレイヤーを配置します。最内部にはドメインモデルを配置し、それを中心にアプリケーションサービス、UI、インフラストラクチャなどのレイヤーが存在します。これにより、ドメインモデルとビジネスロジックの独立性を保ちつつ、外部の要素との結合度を低くします。
[^13]: **クリーンアーキテクチャ** - ソフトウェアの設計と組織を円状に表現します。中心から外側へと、エンティティ、ユースケース、インターフェースアダプター、フレームワークとドライバーのレイヤーが存在します。このアーキテクチャは、各レイヤーの依存関係を一方向に保つことで、高いテスト性と保守性を確保します。