1. はじめに
この記事ではドメイン駆動設計(DDD)の基本概念と実践の初歩について、学習したことのアウトプットとして説明してみようと思います。私がドメイン駆動設計(DDD)に興味を持ったきっかけは以下です。
- 担当するプロダクトでDDDを採用していたから
- ドメイン知識の欠如により苦労したから
2. DDDの基本概念
DDDは、ソフトウェア開発においてドメイン知識を中心に設計を進める手法です。以下に主要な概念を示します。
2.1 ドメイン
ドメインとは、システムが扱う領域を指します。例えばECサイトで言うと、商品、購入履歴、注文などが含まれます。
2.2 境界づけられたコンテキスト
境界づけられたコンテキスト(Bounded Contexts)は、ドメインの一部を分割して一つのまとまりにする概念です。例えばECサイトの「在庫管理」と「販売管理」を別々のコンテキストとして分けることが考えられます。コンテキストを分けることで、異なる部分の設計を独立させることができ、コードの見通しが良くなります。
2.3 DDDにおける主要なパターン
- Entityは、ドメイン内で一位に識別できるオブジェクトです。例えば、ECサイトの「顧客」はエンティティであり、IDで一意に識別されます。
- ValueObjectは、エンティティとは異なり、一意に識別されません。不変性があり、住所や価格などがこれに該当します。
-
Serviceは、ドメインのビジネスロジックを担当するオブジェクトで、複数のエンティティや集約を操作します。サービスは2種類に分けられます。
- ドメインサービスは、複数のエンティティや集約にまたがるビジネスロジックを提供し、ドメイン内でのビジネスルルーの一貫性を維持します。例えば「注文サービス」は、注文に関するビジネスロジックを担当します。
- アプリケーションサービスは、ユーザーのユースケースに基づいたシステム全体のビジネスプロセスを実現するために、ドメインサービスやリポジトリと連携して全体的なビジネスロジックを担当します。 例えば「注文処理アプリケーションサービス」は、注文に関する一連のプロセス(注文の作成・確認、在庫の確保、支払いの処理、配送の手配等)をまとめて調整します。
- Repositoryは、エンティティや集約のデータの保存と再構築を担当するオブジェクトです。例えば「顧客リポジトリ」は顧客エンティティを保存し、必要な時に取り出せるようにします。
- Factoryは、オブジェクトの生成を専門に扱います。特に複雑なオブジェクトや条件によって生成過程が異なるオブジェクトの生成に役立ちます。ファクトリを使用することで、生成の詳細を隠蔽し、コードの再利用性とテストの容易性を高めることが出来ます。
- Aggregateは、エンティティやバリューオブジェクトをグループ化(集約)したもので、一連の操作やルールを持つ単位です。例えば「注文集約」では、顧客エンティティと商品バリューオブジェクトが含まれ、注文に関する操作を提供します。
これらのパターンは以下のように分類出来ます。
- 知識を表現する
- エンティティ
- バリューオブジェクト
- ドメインサービス
- 集約
- アプリケーションを実現する
- リポジトリ
- アプリケーションサービス
- ファクトリ
3. DDDの実践例
ドメインモデリングは、ビジネスロジックを整理し、ビジネスルールを実装するための設計プロセスです。まず、ドメイン全体を境界づけられたコンテキストに分け、それぞれの領域でエンティティ、バリューオブジェクト、エンティティ間の関係を定義します。これにより、システム全体の整合性と再利用性を高め、特定のビジネスルールを効率的に適用できます。ドメインモデリングの例を以下に示します。
3.1 顧客コンテキストのモデリング
「顧客」コンテキストでは、「顧客」エンティティと「氏名」バリューオブジェクトを定義します。顧客エンティティには氏名、メールアドレス、住所などの属性が含まれ、氏名バリューオブジェクトには姓と名の属性が含まれます。
3.2 価格変動への対応
ECサイトでは、セールなどにより商品価格が変動します。商品エンティティに「通常価格」と「割引価格」「割引率」の属性を持たせることで、セール期間中の割引価格などを正確に管理できます。価格変更サービスは特定条件(セール期間、特定顧客のプロモーションなど)に基づいて価格の切り替えを実施します。
3.3 注文の返品
注文の返品に対応するためには、ドメインサービスやリポジトリを活用して返品処理を実装します。注文サービスに「返品」機能を追加し、返品が発生した場合にどのように商品を返すのか、そのビジネスロジックを定義します。以下は返品プロセスの例です。
- 返品理由と商品情報の保存
返品リクエストには返品理由を含め、返品対象となる商品の情報(商品名、価格、数量など)をリポジトリに保存します。これにより、どの商品がどの理由で返品されたかを追跡し、後で分析や改善に役立てます。 - 在庫の更新
返品された商品は在庫に戻されるため、返品処理の一部として在庫を更新します。これにより最新の在庫情報を保ち、他の注文や在庫管理システムで正確な在庫数が把握できます。 - 顧客への通知
返品処理の完了後、顧客へ通知します。返品承認の連絡、返品商品の受領確認、返金手続きの進行状況など、顧客が自分の返品がどの段階にあるかを理解できるようにします。
4. まとめ
DDDを学ぶことで、複雑なビジネスロジックを整理し再利用性の高い設計ができると感じました。特に境界づけられたコンテキストの考え方は、システム全体を明確に分割し、ドメインに集中した設計を行う上で非常に重要だと思いました。実践にはまだ多くのことを学ぶ必要がありますが、今回の学習を通じてシステム設計におけるドメイン知識の重要性を再認識しました。今後のプロジェクトでDDDの概念を活用し、より価値あるソフトウェアを作るために引き続き学んでいきたいと思います。