ドメイン駆動設計 - ntuf/Tips GitHub Wiki

今までのレイヤードアーキテクチャは
プレゼンテーション・ビジネスロジック・データアクセスの分離
していてビジネスロジックにあったり、
ビジネスルールは分散していた。

DDDは
エンティティ・バリューオブジェクト・集約・ドメインサービスなどを活用
関連するエンティティとバリューオブジェクトを「一つの単位(集約)」として扱う
集約の中のデータは外部から直接変更できず、「集約ルート」が管理する

■DDDを使うべき場面と向かない場面
◯向いている場面
ビジネスルールが複雑(例:銀行の取引、在庫管理、ECサイトの決済)
長期的に拡張するシステム(例:SaaS、ERP)

×向いていない場面
単純なCRUDアプリ(例:ブログ、簡単な管理ツール)
開発コストを抑えたい場合(DDDの設計には時間とコストがかかる)

レイヤードアーキテクチャだって、
dddだってビジネスロジックは分散するのでは?
分散する塊が違うだけで
→そのとおり
どこに分散させるか?どの粒度でまとめるか? が異なる

分散の仕方の違い
🔷 レイヤードアーキテクチャ(LA)
ビジネスロジックは 「機能別のレイヤー」に分散 する。

プレゼンテーション層(例:コントローラー、ビュー)

アプリケーション層(例:ユースケース、サービス)

ドメイン層(例:エンティティ、ビジネスルール)

インフラ層(例:データアクセス、外部API連携)

各レイヤーが役割を分担するが、ドメイン層(エンティティ)自体は薄くなりがち。
アプリケーション層に「ユースケース単位」の処理が集まり、ビジネスルールがアプリケーションサービスに寄ってしまうことが多い。

🔶 DDD
ビジネスロジックは 「ドメインモデル」に集約し、その単位で分散 する。

エンティティ → 自分自身の振る舞いを持つ

バリューオブジェクト → 変更不可の小さい値オブジェクト

集約(Aggregate) → 関連するエンティティをひとまとめに管理

ドメインサービス → 集約をまたぐビジネスルールを担当

リポジトリ → 集約単位で永続化を管理

DDDでは、「ユースケース(アプリケーション層)」にロジックを集中させず、できるだけドメイン層に閉じ込める」 という思想がある。

ーーー
どんな業務ルールの変更や複雑なドメインの変化にも強いですか

「どんな業務ルールの変更や複雑なドメインの変化にも強い」わけではありません。
DDDは 特定の種類の変更に強い ですが、万能ではなく、次のようなケースでは弱点があります。

DDDが強い変更・複雑なドメインの変化
✅ 局所的な業務ルールの追加・変更
✅ 業務プロセスの拡張(既存モデルの延長)
✅ 複雑なビジネスルールの整理と変更

✅ 局所的な業務ルールの変更
DDDでは ビジネスルールを集約(Aggregate)に閉じ込める ため、変更の影響を最小限に抑えられる。

例:「ECサイトのキャンセルポリシー変更」

「キャンセルは注文後 24時間以内 のみ可能 → 48時間以内 に変更」

Order のロジック内で時間判定を変更するだけで済む。

✅ 業務プロセスの拡張(既存モデルの延長)
既存のモデルを拡張しやすい。

例:「BtoB向け注文フローを追加」

企業顧客向けの注文では 「承認プロセス」 が必要になる。

既存の Order モデルに ApprovalStep を追加すれば済む。

✅ 複雑なビジネスルールの整理と変更
業務ルールを 意図が明確な単位(集約、ドメインサービス) に分けることで、変更しやすくなる。

例:「保険料の計算ロジック変更」

Policy(契約)、Customer(顧客)、PremiumCalculator(保険料計算)を分離。

計算ロジックを PremiumCalculator 内にまとめれば、新ルール(年齢別割引など)を追加しやすい。

DDDが弱い(苦手な)業務ルールの変更
❌ 業務ルールの「全体的な構造が変わる」**ケース
❌ ビジネスプロセスが激変するケース
❌ データ主導の変更(BI, レポート分析向け)

❌ 業務ルールの全体構造が変わる
DDDは モデルの関係性を前提として設計 しているため、関係そのものが変わると影響が大きい。

例:「ECサイトで在庫管理を外部システムに完全移行」

以前は Product 集約の中に Stock(在庫情報)があった。

しかし、新システムでは 在庫情報が外部API経由で管理される。

Product と Stock の関係を再設計する必要があり、大掛かりな変更になる。

❌ ビジネスプロセスが激変するケース
DDDのモデル構造に影響するような業務変更 には弱い。

例:「人事評価制度が、成果報酬型 → AI評価型に変わる」

旧モデルでは Evaluation は 上司の評価データ を持っていた。

新モデルでは AIの分析結果 を持つようになり、評価基準が完全に異なる。

Evaluation の構造が根本的に変わるため、既存モデルをそのまま流用できない。

❌ データ主導の変更(BI, レポート分析向け)
DDDは「状態と振る舞い」を重視するが、分析向けの変更には向かない。

例:「顧客の購買データを分析し、ダッシュボードを作る」

DDDのモデルは 業務ロジック に特化しており、分析用のデータ最適化には向かない。

BIツール向けには、データウェアハウスやイベントストリーミングが適している。

結論
DDDは 「業務ロジックが局所的に変わる or 段階的に拡張される」 場合に強いが、
「業務プロセス全体が激変する」「データ主導の変更」 には適していない。

✅ DDDが有効
追加・拡張しやすい変更(新ルールの適用、プロセスの一部変更)

影響範囲を最小限に抑えたい変更(局所的な修正)

❌ DDDが不向き
ビジネスモデルやデータ構造が大幅に変わる変更

データ分析、レポート作成など「振る舞いを持たないデータ」の扱い

つまり 「どんな業務変更にも強い」わけではなく、向き不向きがある というのが結論です。

ーーー
DDDとレイヤードアーキテクチャの「わかりやすさ」の違い
🔹 レイヤードアーキテクチャ
✅ コードの構造がシンプルでわかりやすい
✅ 一般的なMVCや3層構造と似ているため学習コストが低い
❌ ビジネスロジックが分散しやすく、変更が難しくなる

🔹 DDD
✅ ビジネスルールを中心に整理されるため、業務の意図がわかりやすい
✅ 変更に強く、コードのまとまりが良い
❌ 概念が多く、学習コストが高い(集約、ユビキタス言語、境界づけられたコンテキストなど)
❌ 単純なシステムでは過剰設計になりやすい

ーーー
ソースコードではどう表現されますか。mvcみたいなアーキテクチャが存在するんですか

DDDでは、MVCのような決まったアーキテクチャの形は存在しません。
しかし、実際のプロジェクトでよく使われる構造はいくつかあります。

🔹 DDDの典型的なアーキテクチャ構造
① レイヤードアーキテクチャ + DDD
レイヤードアーキテクチャと似ていますが、DDDの概念(エンティティ・値オブジェクト・ドメインサービスなど)を取り入れています。

plaintext
コピーする
編集する
📂 src/
├── 📂 application/ ← ユースケース(アプリケーションサービス)
├── 📂 domain/ ← ドメイン層(ビジネスロジック)
│ ├── entity/ ← エンティティ
│ ├── valueobject/ ← 値オブジェクト
│ ├── service/ ← ドメインサービス
│ ├── repository/ ← リポジトリ(インターフェース)
├── 📂 infrastructure/ ← DBアクセス・外部API(リポジトリ実装)
├── 📂 presentation/ ← コントローラーやAPI
このように、DDDの概念を反映しつつ、レイヤードアーキテクチャに落とし込んだ形がよく使われます。

ーーー
内製でプログラムを作るときにドメイン駆動設計を用いたりすることはあるのかなと思っていますが、外注する際にドメイン駆動設計で作るとかありますか?

💡 内製 vs 外注でのDDD採用について
✅ 内製開発でDDDを採用することはよくある
✅ 外注ではDDDを採用しにくいが、可能な場合もある

🔹 内製開発でDDDが採用される理由
内製の場合、以下のような理由でDDDが向いています。

1️⃣ 業務知識が社内にある
DDDでは「ドメインエキスパート」の知識を最大限活用する。

内製なら、エンジニアが業務部門と直接連携できる。

「ビジネスルールが頻繁に変わる」「業務ロジックが複雑」なら特にDDDが効果を発揮。

2️⃣ 長期的な開発・保守が前提
DDDは初期コストが高い(設計に時間がかかる)。

しかし、長期的に見れば保守性や拡張性が向上し、変更に強くなる。

内製なら、長期的な視点で投資できる。

3️⃣ 継続的な開発がしやすい
リファクタリングをしやすい(内部構造を変えやすい)。

ビジネスの変化に対応しやすく、開発の柔軟性が高まる。

🔹 例: 内製でDDDが向いているケース

自社のコア業務を支える基幹システム(金融、物流、製造、ECなど)

長期間運用し、頻繁に機能追加が必要なシステム(社内の業務アプリ)

複雑なビジネスルールを持つアプリケーション

🔹 外注開発でDDDを採用する場合
外注する場合、DDDが採用されることは少ないが、条件次第では可能。

1️⃣ 短期間・単発の外注ではDDDは向かない
DDDの設計には時間がかかるため、短期間のプロジェクトには向かない。

受託開発では「納品したら終わり」になりやすく、DDDのメリット(長期運用のしやすさ)が活かせない。

2️⃣ 開発パートナーとして長期契約するなら可能
内製チームと外注チームが密接に連携する場合は、DDDが可能。

長期開発を前提に、外部のエンジニアが「ドメイン知識を学ぶ時間」を取れるなら採用できる。

3️⃣ 外注先のスキルによる
DDDを理解した開発会社でないと、形だけのDDD(いわゆる"DDD風")になりがち。

「とりあえずレイヤー分けしてみました」だけになり、本来のDDDのメリットを得られない。

🔹 例: 外注でDDDが向いているケース

長期間の開発契約(1年以上)

外注先が「ビジネスドメインの理解」に時間をかけられる

内製チームと外注チームが密に連携できる

🔹 外注でDDDを導入する際の課題と対策
✅ 課題: 外注先にドメイン知識がない
👉 対策: ドメイン知識を共有するためのドキュメントやワークショップを実施する。

✅ 課題: DDDの設計に時間がかかりすぎる
👉 対策: 最初に「スモールスタート」する(重要な部分だけDDDを採用)。

✅ 課題: 納品後の開発が続かない
👉 対策: 外注を長期契約にするか、内製チームで引き継げる設計にする。

📌 まとめ
項目 内製 外注
DDD採用のしやすさ ◎ しやすい △ 難しい(条件次第)
ドメイン知識の蓄積 社内に蓄積しやすい 外注先に蓄積しにくい
長期保守・拡張性 しやすい 難しい(短期案件は特に)
スキルの問題 社内で育成可能 外注先のスキル次第
向いているケース コア業務システム / 長期開発 長期契約 / 外注先と密な連携
🔹 内製ならDDDは効果を発揮しやすい。
🔹 外注でも、長期契約+高スキルな外注先ならDDDを採用可能。

⚠️ **GitHub.com Fallback** ⚠️