# DDD設計アンチパターン・カタログ

## 目的と適用範囲
- DDD (Domain-Driven Design) を採用するプロダクトで再発しがちな設計・運用上の失敗例を俯瞰し、早期発見と是正判断に役立てる。
- 集約・境界コンテキスト・アプリケーションサービス・組織運用の4視点で整理し、兆候と回避策を即時確認できるようにする。
- 新規モデリング、既存システムの監査、チームオンボーディング時の共通言語として利用する。

## クイックインデックス
| 分類 | アンチパターン | 典型的な影響 |
|------|----------------|--------------|
| モデリング | アナミックドメインモデル / 巨大集約 / エンティティ万能主義 / リポジトリ肥大化 / ドメインイベント乱発 | 不変条件崩壊、ロック競合、冗長コード |
| 境界と依存関係 | 境界ズレ / 共有カーネルの希釈化 / インフラスパゲッティ / UI主導モデリング / マイクロサービス誤爆 | 境界破綻、結合度上昇、コスト拡大 |
| アプリケーション層 | トランザクションスクリプト回帰 / ドメインサービス濫用 / 認可ロジック漂流 / 状態変更と副作用の混濁 / 非同期至上主義 | ドメイン劣化、整合性欠落、障害増加 |
| 組織とプロセス | ユビキタス言語の形骸化 / プロジェクト型開発 / 境界横断チーム / ナレッジ共有不足 / テックデット据え置き | 共通理解の喪失、改善停滞 |

## モデリングに関するアンチパターン
| アンチパターン | 概要 | 陥りがちな背景 | 兆候 | 回避策 |
|------------------|------|------------------|------|----------|
| アナミックドメインモデル | 振る舞いがアプリ層へ流出し、ドメインが単なるデータ構造になる | ORM主導設計やCRUD至上主義 | エンティティがgetter/setterのみ | 集約ルートに不変条件と操作を集約し、値オブジェクトを活用する |
| 巨大集約 (God Aggregate) | 集約が複数コンテキストの責務を抱え、更新ロックが常時発生する | 境界設定が曖昧で「全部一つで安心」と考える | 集約が多数のリレーションとトランザクション更新を抱える | ユースケース単位で不変条件を棚卸しし、境界を再分割する |
| エンティティ万能主義 | 全てを識別子付きエンティティで表現する | 「IDが無いと安心できない」文化、過度な永続化志向 | 不変な概念にもID付与、比較が煩雑 | 値オブジェクトへ抽出し、意味的等価性で比較する |
| リポジトリ肥大化 | クエリやアプリ層ロジックまで抱え込む | 技術的関心ごととビジネスルールを混同 | リポジトリに条件分岐やDTO組み立てが散在 | 集約境界毎に専用リポジトリを置き、仕様ベースでクエリを表現する |
| ドメインイベント乱発 | 事後処理をイベントに丸投げし依存が不透明化 | イベント駆動を誤解し「とりあえず発火」する | 実体の無いイベントや過剰購読 | 状態変化という事実だけに絞り、契約と責務を明文化する |

## 境界・依存関係に関するアンチパターン
| アンチパターン | 概要 | 陥りがちな背景 | 兆候 | 回避策 |
|------------------|------|------------------|------|----------|
| 境界ズレ (Context Bleeding) | 別コンテキストの型やサービスへ直接依存する | 境界定義が曖昧で共有クラスを安易に利用 | DTOがドメイン層に侵入、循環依存 | 翻訳レイヤを設け、境界ごとに防護層を挟む |
| 共有カーネルの希釈化 | 便利クラスを共通化し過ぎて結合が進む | 共通ライブラリ重視文化、レビュー不足 | sharedモジュールが巨大化し意味不明 | 真の共通語彙に限定し、所有者と契約を明示する |
| インフラスパゲッティ | ドメインがORMやHTTPクライアントへ直接依存 | 技術ドライバが主導、ポート/アダプタ欠如 | ドメイン層で外部ライブラリ import | ポート・アダプタを定義し、DIでインフラを注入する |
| UI主導モデリング | 画面レイアウトからモデルがそのまま決まる | UI設計が先行し業務分析が追随 | ドメイン語彙がUI部品名と一致 | 業務価値・ルール起点でユビキタス言語を再構成する |
| マイクロサービス誤爆 | 用語だけ拝借し安易にサービス分割する | DDD=マイクロサービスという思い込み | チーム構造と境界の不整合、通信過多 | 組織責務とビジネス能力を先に分析し分割要否を判断する |

## アプリケーション層・サービス設計のアンチパターン
| アンチパターン | 概要 | 陥りがちな背景 | 兆候 | 回避策 |
|------------------|------|------------------|------|----------|
| トランザクションスクリプト回帰 | アプリケーションサービスが逐次的な状態遷移を直書き | 短期開発でドメインを作り切れない | サービスが長大でテスト困難 | 集約メソッドへ振る舞いを戻し、サービスはユースケース調停に徹する |
| ドメインサービス濫用 | あらゆる処理をサービスへ押し込み責務が不明 | 「エンティティは軽くあるべき」という誤解 | ドメインサービスが巨大化 | エンティティへ移せる振る舞いを棚卸し、横断関心のみに限定する |
| 認可ロジック漂流 | セキュリティ判断がUI/ドメインで重複 | 役割定義が曖昧、責任分界が不在 | 認可失敗時の振る舞いが不一致 | ポリシーオブジェクト等で統合し、ユースケース入口で評価する |
| 状態変更と副作用の混濁 | メール送信等をドメイン層が直接呼び出す | 副作用を扱うアダプタが未整備 | ドメインサービスで外部I/O | ドメインイベント→アプリケーションサービス→アダプタへ委譲する |
| 非同期至上主義 | 一貫性要件を無視し全てをイベント化 | レジリエンス志向の暴走 | 常に最終整合、補償処理が錯綜 | 強整合が必要な操作は同期コマンドを維持し、補償フローを別途設計する |

## 組織・プロセス面のアンチパターン
| アンチパターン | 概要 | 陥りがちな背景 | 兆候 | 回避策 |
|------------------|------|------------------|------|----------|
| ユビキタス言語の形骸化 | 用語がドキュメントのみでコードへ反映されない | 言語ガバナンスが不在 | コードレビューで用語がバラバラ | 用語集を管理し、レビューで対訳表との整合を確認する |
| プロジェクト型開発 | モデル進化が短期案件に従属し継続的改善が止まる | プロダクト運用チームが不在 | リリース後にモデル更新が途絶 | プロダクトチームを常設し、モデル進化の責任を明示する |
| 境界横断チーム | 1チームが複数コンテキストを担当し優先度競合 | 組織制約で兼務が常態化 | 論点調整コストが高騰 | チームと境界を極力1対1に合わせ、共有契約は協調ガバナンスで管理する |
| ナレッジ共有不足 | 戦略的設計の決定が暗黙知化する | ドキュメント文化不在 | モデリング方針が属人化 | モデルキャンバスや決定記録を軽量に残し、イベントストーミングを定期開催する |
| テックデット据え置き | アンチパターンを認識しても改善が先送り | 「今は開発が優先」という空気 | 技術負債チケットが積み残る | 技術負債バックログ枠を常設し、実行責任とKPIを可視化する |

## 再発防止のための実践観点
- 診断レーダ: 境界適合度・集約サイズ・イベント品質などの指標を定期レビューし、スコア変動を可視化する。
- 言語ガバナンス: ユビキタス言語の語彙表と対訳をリポジトリでバージョン管理し、変更にはレビューを必須化する。
- 設計カタログ: 成功パターンとアンチパターンの事例をペアで記録し、オンボーディングやワークショップで参照する。
- テスト粒度整備: 集約単位の振る舞いテストとコンテキスト契約テストを整備し、アナミック化や境界侵食を検知する。
- 継続的ワークショップ: イベントストーミングやモデリングセッションを定期的に開催し、モデルの鮮度と共通認識を維持する。
