ストーリー
Bounded Context とは
Bounded Context は、特定のドメインモデルが適用される明示的な境界です。
graph TD
subgraph EC["EC ドメイン"]
CAT["カタログ Context<br/>・商品<br/>・カテゴリ<br/>・レビュー"]
ORD["注文 Context<br/>・注文<br/>・注文明細<br/>・決済"]
SHP["配送 Context<br/>・出荷<br/>・配送先<br/>・追跡"]
CUS["顧客管理 Context"]
INV["在庫 Context"]
MKT["マーケ Context"]
end
classDef ctx fill:#e8f4fd,stroke:#2196f3,color:#333
class CAT,ORD,SHP,CUS,INV,MKT ctx
境界の見つけ方
| シグナル | 説明 | 例 |
|---|---|---|
| 言語の違い | 同じ用語が異なる意味を持つ | 「商品」の定義がチームで異なる |
| ビジネスプロセスの境界 | 業務フローの切れ目 | 注文確定と配送手配の間 |
| データの所有権 | 誰がそのデータの正本を持つか | 在庫数は在庫チームが所有 |
| 変更の速度 | 異なるペースで変更される | カタログは毎日、決済は月1回 |
| チーム構造 | 既存のチーム境界 | 逆コンウェイ戦略に活用 |
Context Mapping パターン
7つの主要パターン
graph LR
subgraph 協調的
P["Partnership"]
CS["Customer/<br/>Supplier"]
end
subgraph 中間
SK["Shared Kernel"]
CF["Conformist"]
OHS["Open Host<br/>Service"]
PL["Published<br/>Language"]
end
subgraph 防御的
ACL["ACL"]
SW["Separate Ways"]
end
P --- SK --- ACL
CS --- CF --- SW
SK --- OHS
OHS --- PL
classDef coop fill:#d4edda,stroke:#28a745,color:#333
classDef mid fill:#fff3cd,stroke:#f0ad4e,color:#333
classDef def fill:#f8d7da,stroke:#dc3545,color:#333
class P,CS coop
class SK,CF,OHS,PL mid
class ACL,SW def
| パターン | 関係性 | 使用場面 |
|---|---|---|
| Partnership | 対等・協調 | 2チームが密に連携して開発 |
| Shared Kernel | 共有モデル | 小さなモデルを複数コンテキストで共有 |
| Customer/Supplier | 上流/下流 | 下流が上流に要求を出せる |
| Conformist | 従属 | 下流が上流のモデルに合わせる |
| Anti-Corruption Layer | 防御的翻訳 | 外部モデルから自ドメインを保護 |
| Open Host Service | 公開API | 汎用的なプロトコルを提供 |
| Published Language | 共通言語 | 標準化されたデータフォーマット |
ACL(Anti-Corruption Layer)の実装例
// 外部の決済サービスのモデル
interface StripePaymentIntent {
id: string;
amount: number; // セント単位
currency: string;
status: 'succeeded' | 'pending' | 'failed';
metadata: Record<string, string>;
}
// 自ドメインのモデル
class Payment {
constructor(
readonly id: PaymentId,
readonly amount: Money,
readonly status: PaymentStatus,
readonly orderId: OrderId
) {}
}
// ACL: 外部モデル → 自ドメインモデルへの変換
class StripePaymentAdapter {
toDomain(intent: StripePaymentIntent): Payment {
return new Payment(
new PaymentId(intent.id),
new Money(intent.amount / 100, intent.currency as Currency),
this.mapStatus(intent.status),
new OrderId(intent.metadata.orderId)
);
}
private mapStatus(status: string): PaymentStatus {
const mapping: Record<string, PaymentStatus> = {
succeeded: PaymentStatus.COMPLETED,
pending: PaymentStatus.PROCESSING,
failed: PaymentStatus.FAILED,
};
return mapping[status] ?? PaymentStatus.UNKNOWN;
}
}
ECプラットフォームのコンテキストマップ
graph TD
CAT["カタログ Context"] <-->|Partnership| INV["在庫 Context"]
CAT -->|OHS/PL| ORD["注文 Context"]
INV -->|Customer/Supplier| ORD
ORD <-->|Partnership| SHP["配送 Context"]
ORD -->|ACL| PAY["決済 Context<br/>← 外部サービス(Stripe)との<br/>間にACLを配置"]
classDef ctx fill:#e8f4fd,stroke:#2196f3,color:#333
classDef ext fill:#fff3cd,stroke:#f0ad4e,color:#333
class CAT,INV,ORD,SHP ctx
class PAY ext
Event Storming によるコンテキスト発見
Event Storming は、ドメインエキスパートと開発者が共同でドメインイベントを洗い出し、Bounded Context を発見する手法です。
進め方
- ドメインイベント(オレンジ付箋)を時系列に並べる
- コマンド(青付箋)を特定する
- 集約(黄色付箋)をグルーピングする
- 境界線を引いて Context を分ける
graph LR
subgraph Catalog["カタログ"]
E1["商品登録された"]
end
subgraph Stock["在庫"]
E2["在庫設定された"]
end
E1 --> E2 --> E3["商品公開された"]
subgraph Cart["カート"]
E4["カートに追加された"]
end
subgraph Order["注文"]
E5["注文確定された"]
end
subgraph Payment["決済"]
E6["決済処理された"]
end
subgraph Shipping["配送"]
E7["出荷指示された"]
end
E4 --> E5 --> E6 --> E7
style Catalog fill:#dbeafe,stroke:#2563eb,color:#1e40af
style Stock fill:#d1fae5,stroke:#059669,color:#065f46
style Cart fill:#f3e8ff,stroke:#7c3aed,color:#5b21b6
style Order fill:#fef3c7,stroke:#d97706,color:#92400e
style Payment fill:#fee2e2,stroke:#dc2626,color:#991b1b
style Shipping fill:#d1fae5,stroke:#059669,color:#065f46
style E1 fill:#dbeafe,stroke:#2563eb,color:#1e40af
style E2 fill:#d1fae5,stroke:#059669,color:#065f46
style E3 fill:#f3f4f6,stroke:#9ca3af,color:#374151
style E4 fill:#f3e8ff,stroke:#7c3aed,color:#5b21b6
style E5 fill:#fef3c7,stroke:#d97706,color:#92400e
style E6 fill:#fee2e2,stroke:#dc2626,color:#991b1b
style E7 fill:#d1fae5,stroke:#059669,color:#065f46
まとめ
| ポイント | 内容 |
|---|---|
| Bounded Context | ドメインモデルの適用境界 |
| Context Mapping | Context 間の関係性を定義 |
| ACL | 外部モデルから自ドメインを保護 |
| Event Storming | Context 発見のワークショップ手法 |
チェックリスト
- Bounded Context の境界を特定する方法を理解した
- 7つの Context Mapping パターンを説明できる
- ACL の役割と実装方法を理解した
- Event Storming の進め方を説明できる
次のステップへ
次はサービス分割戦略と段階的移行アプローチを学びます。
推定読了時間: 40分