はじめに
業務担当者は「注文を確定する」と説明していても、画面ではボタン操作、データベースでは状態値、プログラムでは複数の条件分岐として別々に表現されていることがあります。言葉と実装の意味がそろっていなければ、業務ルールの変更時に確認範囲が広がり、判断の意図も失われていきます。
ドメイン駆動設計(DDD)は、エンティティや値オブジェクトなどの用語を導入することが目的ではありません。業務を理解するための言葉とルールをモデルとして整理し、そのモデルを実装へ反映し続けるための設計アプローチです。この記事では、DDDの目的、注文業務を使った考え方、既存の設計知識との違い、取り入れ方を解説します。
この記事で分かること
- ドメイン駆動設計(DDD)の目的
- DDDが必要になる問題
- 業務の言葉、モデル、実装の関係
- 戦略的設計と戦術的設計の違い
- DDDが向いている場合と小さく始める方法
ドメイン駆動設計(DDD)とは
ドメイン駆動設計(Domain-Driven Design:DDD)とは、業務知識を設計の中心に置き、業務で使われる言葉とルールをモデルとして整理し、そのモデルを実装へ継続的に反映する設計アプローチです。
ドメインとは、システムが対象とする業務領域です。注文管理であれば、注文の受付、価格の決定、在庫の確保、支払い、配送などの業務が含まれます。ドメインモデルは、その業務で重要な概念、関係、判断、制約を表したものです。
DDDでは、業務担当者と開発者が対話し、同じ意味で使える言葉を整えます。この共通の言葉はユビキタス言語と呼ばれますが、用語集を作ることだけが目的ではありません。会話、要件、モデル、コードで同じ意味を使い、業務理解が変わればモデルと実装も見直します。
DDDが必要になる問題
業務ルールが単純なうちは、画面やデータベースを中心に設計しても大きな問題にならない場合があります。しかし、判断条件や例外が増えると、業務の意味が画面、API、バッチ、SQLなどへ分散しやすくなります。
例えば「注文確定」という言葉を、ある担当者は注文内容の確定、別の担当者は支払い完了として使っているとします。意味を決めないまま実装へ進めば、要件、画面、データ、テストで異なる状態を「確定」と呼ぶことになります。
言葉の意味を合わせても、業務ルールを処理ごとに個別実装すれば、会話上の理解とコードの構造は再び離れます。同じ言葉でも認識がずれる仕組みは、要件定義はなぜズレるのか?同じ言葉でも意味が違う理由を解説で説明しています。
業務の言葉とモデルを一致させる
業務と開発で共通の言葉を使う
共通の言葉を使うには、「注文を確定するとは、どの条件を満たし、確定後に何を変更できる状態なのか」まで具体化します。会話では「注文確定」と呼んでいるのに、コードでは意味の曖昧なupdateStatus()として表現すると、処理の目的や条件を読み取れません。
業務の言葉をコードへ反映するには、名前から責務と意味が分かることも重要です。詳しくは、命名が設計品質を左右する理由|良いクラス名・メソッド名の考え方で解説しています。
業務ルールをモデルの責任として表す
ドメインモデルは、データを保存するための項目を並べたものではありません。「商品が一件もない注文は確定できない」「発送済みの注文はキャンセルできない」といった業務上の判断を、意味のある単位へまとめます。
注文に関する判断を画面、API、バッチが個別に持つと、同じルールが重複し、変更時の修正漏れが発生します。モデルが判断を担当すれば、利用側は状態値や計算式を直接解釈せず、業務上の操作として処理を依頼できます。
モデルと実装を見直し続ける
モデルは、開発の最初に作って固定する設計書ではありません。運用で新しい例外が分かったり、対話によって言葉の意味が変わったりすれば、モデルとコードにも反映します。
文書だけを更新し、実装へ古い名前や判断が残れば、業務理解とシステムは再びずれます。DDDでは、対話、モデル、実装を一度だけ対応させるのではなく、変化に合わせて一致させ続けます。
注文業務をモデルで考える例
注文業務に、次のルールがあるとします。
- 注文は「作成中」「確定済み」「発送済み」の状態を持つ
- 商品が一件もない注文は確定できない
- 発送済みの注文はキャンセルできない
- 合計金額は明細と割引条件から決まる
業務モデルを意識しない場合、画面やサービスごとに状態値を比較し、明細数を確認し、金額を計算します。ルールが複数の処理へ分散すると、変更時にどこを修正すべきか分かりにくくなります。
| 観点 | 処理側へ分散した状態 | モデルへ表現した状態 |
|---|---|---|
| 注文の確定 | 画面やAPIが明細数と状態値を確認する | 注文モデルが確定できるか判断する |
| キャンセル | 各処理が発送状態を個別に比較する | 注文モデルが現在の状態から判断する |
| 合計金額 | 複数の処理が計算式と割引条件を持つ | 注文モデルが明細と条件から計算する |
| 変更時の確認 | 関連する画面、API、バッチを横断して探す | 注文モデルを中心に影響を確認する |
重要なのは、すべての処理を一つのクラスへ集めることではありません。注文に関する状態とルールの関係を整理し、業務上の判断を担当するモデルを明確にすることです。
戦略的設計と戦術的設計の全体像
DDDには、大きく分けて戦略的設計と戦術的設計があります。両者は別の手法ではなく、業務の境界を整理し、その範囲のモデルを実装するための異なる視点です。
| 区分 | 中心となる問い | 代表的な考え方 |
|---|---|---|
| 戦略的設計 | どの業務を、どの範囲の言葉とモデルで扱うか | 境界づけられたコンテキストなど |
| 戦術的設計 | 業務の概念やルールをコードでどう表現するか | エンティティ、値オブジェクト、集約、リポジトリなど |
戦略的設計では、同じ言葉を同じ意味で使える範囲を整理します。例えば「顧客」という言葉でも、販売では購入者、請求では請求先として異なる情報と責任を持つ場合があります。
境界づけられたコンテキストは、マイクロサービスの境界を考える手掛かりにもなります。ただし、業務上の境界と配備単位は、必ず1対1で対応するわけではありません。詳しくは、「マイクロサービス設計とは?サービス境界と独立性の考え方」で解説しています。
戦術的設計では、その範囲で整理したモデルをコードへ表現します。ただし、個別の要素を実装すること自体がDDDの目的ではありません。各要素の詳しい設計方法は別の知識として扱い、本記事では全体における役割だけを示します。
DDDと既存の設計知識との違い
DDDは、SOLID原則やクリーンアーキテクチャと置き換えるものではありません。それぞれが中心とする問題は次のように異なります。
| 設計知識 | 中心となる問い |
|---|---|
| DDD | 業務の言葉とルールを、どのようなモデルとして表現するか |
| クリーンアーキテクチャ | 業務ルールを外部技術からどう守るか |
| SOLID原則 | クラスや依存関係を変更しやすくするにはどう設計するか |
| 設計品質 | 要求と制約に対して設計が適切か |
| 変更できる設計 | 将来の変更による影響をどう限定するか |
DDDで業務ルールの意味と境界をモデルとして整理し、クリーンアーキテクチャによって、そのモデルをUIやデータベースなどの外部技術から分離するという組み合わせもできます。詳しくは、クリーンアーキテクチャとは?業務ルールを外部技術から分離する設計の考え方で解説しています。
DDDが向いている場合・向いていない場合
DDDが向いているのは、次のような場合です。
- 判断条件や例外が多い
- 業務変更が継続的に発生する
- 複数部門の認識合わせが重要である
- 同じ言葉の意味が業務範囲によって変わる
- 長期間の保守を想定している
一方、次のような場合は過剰になりやすくなります。
- 単純な登録・参照が中心である
- 業務ルールがほとんどない
- 短期間だけ使用する
- 外部サービスへの単純な受け渡しが中心である
- モデル化の維持コストが効果を上回る
DDDを採用しただけで設計品質が高くなるわけではありません。モデルや境界を維持するコストが、業務の複雑さや変更頻度に見合うかを判断します。設計手法を要求と制約から評価する考え方は、設計品質とは?要求と制約から良い設計を判断する考え方で解説しています。
DDDを小さく始める流れ
DDDを始めるときに、システム全体の言葉やモデルを一度に作る必要はありません。業務ルールが複雑で、変更の影響を追いにくい範囲を一つ選びます。
- 業務ルールが複雑な範囲を選ぶ
- 業務担当者と重要な言葉、状態、判断条件を確認する
- 状態、制約、振る舞いをモデルとして整理する
- モデルの言葉と責任をコードへ反映する
- 運用で得た知識をモデルと実装へ戻す
例えば注文業務全体を作り直すのではなく、キャンセル可否の判断が分散している範囲から整理します。小さな範囲で効果と維持コストを確認しながら対象を広げます。業務変更の影響を必要な範囲へ限定する理由は、良い設計より「変更できる設計」が重要な理由で解説しています。
DDDを導入するときの注意点
用語を採用することを目的にしない
クラス名にEntityやRepositoryを付けても、業務の言葉とルールがモデルへ反映されていなければ、DDDの目的は達成できません。実装要素から始めず、解決したい業務上の問題から考えます。
データベース構造をそのままモデルにしない
テーブルの列をクラスの属性へ移しただけでは、業務上の判断や制約を表現できません。保存形式と業務モデルには関係がありますが、同じものではありません。
開発者だけでモデルを決めない
業務知識を持つ人との対話がなければ、技術的には整っていても実際の業務とずれたモデルになる可能性があります。モデルは、実装の構造であると同時に、業務への共通理解を作るためのものです。
すべての機能へ同じ深さで適用しない
複雑な業務ルールがある範囲と、単純な入出力が中心の範囲では、必要な設計の深さが異なります。全体へ一律に適用せず、業務の複雑さと変更の必要性から対象を選びます。
まとめ
ドメイン駆動設計(DDD)は、業務知識を設計の中心に置き、業務で使われる言葉とルールをモデルとして整理し、そのモデルを実装へ反映し続ける設計アプローチです。
エンティティ、値オブジェクト、集約、リポジトリなどは、業務モデルを表現するための選択肢です。個別の用語や構造を採用すること自体を目的にせず、言葉と実装のずれや業務ルールの分散が問題になっている範囲から、小さく取り入れることが重要です。


コメント