要件が何度も変わる業務システムでは、「どこにルールが書かれているのか分からない」「直すたびにどこまで影響するか読みにくい」といった悩みが出やすくなります。ドメイン駆動設計(DDD)は、業務の知識を設計の中心に置き、複雑なルールを散らばらせずに扱うための考え方です。特に、判断のよりどころが多く、変更も起きやすい領域で力を発揮しやすくなります。この記事では、全体像、取り入れると何が変わるか、進め方、つまずきやすい点を順に見ていきます。
ドメイン駆動設計(DDD:Domain-Driven Design)とは、ソフトウェア開発でドメインモデル(業務の概念・用語・ルールを表したモデル)を中心に設計と実装を進める考え方です。ここでいう「ドメイン」は、業務や問題の領域そのものを指し、例えば「受注」「在庫」「請求」「審査」「配送」などが該当します。DDDは、特定のフレームワークや万能のパターン集ではなく、複雑な業務をどう整理してコードへ表すかを考えるための進め方です。
DDDのポイントは、単に“業務を理解する”だけではなく、業務の言葉とルールをコードとして表し続けることにあります。ドメインモデルを起点にすることで、「仕様書にしかないルール」や「担当者の頭の中にしかない判断のよりどころ」を、設計・実装・テストの中で扱いやすい形へ近づけます。
ドメイン駆動設計は、エリック・エヴァンスの著書を通じて広く知られるようになった考え方で、複雑なビジネスロジックを持つソフトウェアで特に力を発揮しやすいとされています。ドメインモデルを中心に置くことで、ソフトウェアを業務の要求に合わせやすくし、変更にも対応しやすい設計を目指します。
ただし、DDDは「特定のフレームワーク」でも「何にでも効くパターン集」でもありません。業務の複雑さを扱うための考え方と、現場で進めるためのやり方の組み合わせと捉えると、導入時のズレが減ります。
ドメインモデルは、DDDの中心になります。役割は主に次の通りです。
ドメインモデルが弱いままだと、ビジネスルールが画面の分岐や DB 操作の寄せ集めに散らばりやすくなります。すると、変更のたびにどこまで直す必要があるかが読みにくくなり、修正のコストとリスクが上がります。反対に、ドメインモデルをうまく組めると、業務の要求に合わせやすく、保守もしやすい形へ近づきます。
DDDでは、ドメインエキスパート(対象の業務に詳しい人)との協業を重視します。ここで大切なのは、ドメインエキスパートに設計を決めてもらうことではなく、業務の判断のよりどころを開発チームが再現できる形へ落とし込むことです。
例えば「返品できる条件」「審査で否決になる理由」「例外時の扱い」などは、業務側には当然でも、実装側には曖昧なまま残りやすい部分です。DDDでは、こうした暗黙知を引き出し、言葉をそろえ、モデルとして固定していきます。そのために、ユビキタス言語を確立し、会話・設計・コード・テストで同じ言葉を使うことが求められます。
DDDは、よく「戦術の設計」と「戦略の設計」という2つの見方で整理されます。ざっくり言えば、戦術は“モデルをコードにするための部品”、戦略は“モデルの境界をどう切るか”です。
| 見方 | 説明 |
|---|---|
| 戦術の設計 | 個々のドメインオブジェクトをどう作るかに関わる領域です。エンティティ、値オブジェクト、集約、ドメインサービス、リポジトリなどを扱います。 |
| 戦略の設計 | システム全体をどう分けるかに関わる領域です。境界づけられたコンテキスト、コンテキストマップ、連携のやり方などを扱います。 |
戦術だけを先に入れると、「DDDらしいクラスはあるが、境界が曖昧で結局からみ合う」状態になりやすくなります。逆に、戦略だけで止まると、「図はきれいだが実装が変わらない」状態になりがちです。どこで境界を切り、どこへルールを置くかを両方でそろえることが大切です。
DDDを取り入れると、要求が変わったときに手を入れる場所を追いやすくなります。ドメインモデルを中心に設計することで、ビジネスルールが散らばりにくくなるためです。
例えば「割引の条件が変わる」「審査の判定が追加される」「在庫を引き当てるルールが変わる」といった変更は、画面やDB操作に直書きされていると、思わぬ場所まで影響が広がります。DDDでは、ルールの置き場をモデル側へ寄せることで、どこまで直す必要があるかを読みやすくし、対応の速さと品質を両立しやすくします。
DDDでは、業務の言葉に沿って設計するため、コードが「何をしているか」を追いやすくなります。名前と責務が業務に対応しやすくなり、結果として読みやすさや保守のしやすさが上がります。
また、機能を広げる場面でも、ドメインモデルを基準に変更点を整理できます。例えば新しい機能の追加が「今ある集約にルールを足せばよいのか」「別のコンテキストとして分けるべきか」といった話を、設計の言葉で議論しやすくなります。
DDDを取り入れると、ビジネスルールをコード上で追いやすくなります。ドメインエキスパートとの対話を通じて、業務の判断のよりどころを言葉にし、モデルへ落とし込むためです。
さらに、ルールがモデル側に集まりやすくなると、テストもしやすくなります。画面や外部I/Oに依存しない形でロジックを確かめやすくなるため、回帰テストのコストも抑えやすくなります。
DDDでは、ユビキタス言語を確立し、チーム全体で共有します。これにより、「同じ言葉を使っているつもりで別の概念を話していた」といったズレが減ります。
例えば「契約」「申込」「注文」が業務上は別物でも、開発側がひとまとめにしてしまうと、後から仕様が崩れやすくなります。DDDは、用語のズレを早い段階で見つけやすくし、設計の崩れを未然に防ぎやすくします。
主な良い点をまとめると、次のようになります。
| 良い点 | 内容 |
|---|---|
| 要求の変化に対応しやすい | ルールの置き場が読みやすくなり、どこまで直すかを追いやすくなる。 |
| 保守しやすく、広げやすい | 業務の言葉に沿った設計になるため、責務を整理しやすい。 |
| ルールをコードで追いやすい | モデル側へルールを寄せることで、テストもしやすくなる。 |
| チームで会話しやすい | ユビキタス言語をそろえることで、認識のズレを減らしやすい。 |
ただし、DDDは入れれば自動で改善する手法ではありません。共通の言葉を作ること、境界を決めること、モデルへルールを置くことを、運用として続ける必要があります。
DDDは、いきなり全部へ広げるより、重要な領域から少しずつ進める方が成功しやすくなります。ここでは、実務で押さえたい点を順に見ていきます。
ドメインモデリングは、DDDの起点です。ドメインエキスパートとの対話を通じて、業務の用語・概念・ルールをはっきりさせ、モデルへ落とし込みます。特に、次の点は「やったつもり」になりやすいため、意識して扱う必要があります。
モデリングは図を描くこと自体が目的ではありません。最終的には、コードとテストが業務の言葉で説明できる状態へ近づいているかが大切です。
ドメインモデルを実装へ落とすときは、集約(Aggregate)とエンティティ(Entity)の設計が重要になります。集約は、関連するエンティティや値オブジェクトをまとめ、整合性を守る単位として扱うための考え方です。エンティティは固有の識別子を持ち、状態が変わっても同じものとして追い続ける対象を表します。
全部を1つの集約へ押し込むと、一見すると分かりやすく見えますが、更新が多い場面では競合や性能の問題につながることがあります。逆に細かく分けすぎると、守りたいルールがアプリケーション側へ漏れやすくなります。業務上、どこまでを一緒に確かめる必要があるかを根拠に境界を決めることが大切です。
値オブジェクト(Value Object)は、値そのものに意味がある概念を表すためのパターンです。値オブジェクトは不変で扱うのが基本で、同じ属性値を持つものは同じとみなします。
値オブジェクトを増やしすぎると実装が重くなりますが、文字列や数値へ寄せすぎるとルールが散らばります。その値に業務上の意味や制約があるかを基準にすると、過不足を減らしやすくなります。
リポジトリ(Repository)とファクトリ(Factory)は、ドメイン層とインフラ層を分けやすくするための代表的なパターンです。リポジトリは保存と取得の詳細を隠し、ファクトリは生成の条件が複雑なオブジェクトを作る手順をまとめます。
また、DDDではアプリケーションサービスを置く構成がよく使われます。これは DDD の必須要素というより、ドメイン層に処理の手順を混ぜすぎないための整理方法の一つです。ドメイン層へ手順が混ざると責務が膨らみやすいため、層の役割を意識して分けると運用しやすくなります。
大きなシステムでは、境界づけられたコンテキスト(Bounded Context)とコンテキストマップ(Context Map)が重要になります。境界づけられたコンテキストは、同じ言葉が同じ意味で通る範囲を定義し、その範囲の中で一貫したモデルを作る考え方です。
例えば「顧客」という言葉が、販売では「購入者」、サポートでは「問い合わせ主」、与信では「審査対象者」を指すなら、同じモデルで無理に統一すると崩れやすくなります。コンテキストを分け、それぞれで必要な概念を持ち、連携時に翻訳や変換を行う方が安全な場合があります。
境界づけが曖昧だと、結局は全体で1つの巨大モデルになり、DDDの利点が出にくくなります。逆に、切りすぎると連携のコストが増えます。まずは、用語でもめやすい場所や、ルールが多い領域から境界を考えると、筋のよい分け方につながりやすくなります。
DDDは強力ですが、入れ方を誤ると形だけが残りやすい手法でもあります。ここでは、どこに使うか、どんな体制がいるか、どう始めるかの観点で注意点を整理します。
ドメイン駆動設計は、すべてのシステムに同じように向くわけではありません。特に、複雑なビジネスロジックがあり、要件が変わりやすい領域で力を発揮します。
一方、単純な CRUD が中心で、業務ルールが薄い領域では、DDDの設計コストやモデリングの負担が効果に見合わないこともあります。例えば、管理画面のマスタ編集や、ほぼデータの入出力だけの機能は、もっと単純な設計で十分な場合があります。どこに複雑さがあるのかを見極め、重要な領域から適用するのが現実的です。
DDDは個人の技量だけで成立しにくく、チーム運用が成果を左右します。特に次の点は、形だけになるのを防ぐうえで重要です。
また、経験の差がある場合に、最初から複雑な分割や多くのパターン適用を求めると疲れやすくなります。まずは共通の言葉とモデリングを整え、その後に重要な領域から設計を深める順の方が定着しやすくなります。
DDDの導入は一度で完成しません。小さく試し、見直しながら進める運用が必要です。例えば、次のような流れが現実的です。
導入の途中では、「モデルが実装に反映されているか」「言葉がそろっているか」「境界が守られているか」を定期的に確かめる必要があります。DDDはモデルを一度作って終わりではなく、育てていく活動でもあります。
ドメイン駆動設計は、複雑なビジネスロジックを持つシステムで、変更に強い設計を目指すための考え方です。ドメインモデルを中心に置き、ドメインエキスパートとの対話を通じて、業務のルールや判断のよりどころを設計・実装・テストへ反映しやすくします。
一方で、入れれば自動的に良くなるわけではありません。どこに複雑さがあるのか、どこで境界を切るのか、ルールをどこへ置くのかを、ユビキタス言語を軸にチームで見直し続ける必要があります。重要な領域から小さく始め、会話と実装の両方をそろえていく進め方が現実的です。
業務の概念とルールを表したドメインモデルを中心に、設計と実装を進める考え方です。
業務や問題の領域そのものを指し、受注・在庫・請求などが該当します。
業務の用語、概念、ルールを整理し、設計とコードで扱いやすい形にしたものです。
複雑なビジネスロジックがあり、要件が変わりやすいシステムに向いています。
必要性が低い場合も多く、設計コストが見合わないことがあります。
ドメインエキスパートと開発者が共通で使う言葉で、会話、設計、コードでそろえて使います。
戦術はモデルをコードへ落とす設計で、戦略はモデルの境界と連携を決める設計です。
同じ言葉が同じ意味で通る範囲を定め、その中で一貫したモデルを保つ考え方です。
境界が曖昧なままパターンだけを入れ、結局モデルがからみ合うことです。
重要な領域から小さく始め、共通の言葉とモデルを見直しながら育てていくやり方が現実的です。