ストーリー
ミッション概要
| ミッション | テーマ | 目安時間 |
|---|---|---|
| Mission 1 | Bounded Context の特定 | 15分 |
| Mission 2 | コンテキストマップの作成 | 15分 |
| Mission 3 | API契約の設計 | 15分 |
| Mission 4 | データベース分割計画 | 15分 |
前提シナリオ
ShopMasterの主要ビジネスプロセスは以下の通りです:
- 商品管理: 出品者が商品を登録・編集・公開する
- 検索・閲覧: ユーザーが商品を検索し、詳細を閲覧する
- カート・注文: ユーザーがカートに追加し、注文を確定する
- 決済: クレジットカード/コンビニ支払い処理
- 在庫管理: 在庫確認・引当・補充管理
- 配送: 出荷指示、追跡番号管理、配送状況通知
- レビュー: 商品レビューの投稿・表示
- 顧客管理: 会員登録、プロフィール、購入履歴
- 通知: メール、プッシュ通知、SMS
- マーケティング: クーポン、キャンペーン、ポイント
Mission 1: Bounded Contextの特定(15分)
要件
上記のビジネスプロセスをBounded Contextにグルーピングし、各Contextの責務とサブドメイン分類(Core/Supporting/Generic)を定義してください。
解答例
| Bounded Context | 責務 | サブドメイン | 理由 |
|---|---|---|---|
| Catalog | 商品情報管理・検索 | Supporting | 商品の正本管理 |
| Order | カート・注文ライフサイクル | Core | 収益の中核プロセス |
| Payment | 決済処理・返金 | Generic | Stripe等で外部化可能 |
| Inventory | 在庫引当・補充 | Supporting | 注文を支える固有機能 |
| Shipping | 配送・追跡 | Supporting | 配送パートナー連携 |
| Customer | 会員・認証・プロフィール | Generic | 汎用的な認証基盤 |
| Review | レビュー・評価 | Supporting | 購買判断を支援 |
| Notification | 通知配信 | Generic | 汎用メッセージング |
| Marketing | クーポン・ポイント | Core | 競争優位の差別化 |
設計判断の根拠:
- OrderをCoreとした理由: ECの本質は「注文→決済→配送」のフローであり、このフローの最適化が競争優位になる
- MarketingをCoreとした理由: クーポン・ポイント施策はLTV向上の鍵であり、独自のロジックが必要
Mission 2: コンテキストマップの作成(15分)
要件
Mission 1で特定したBounded Context間の関係をContext Mappingパターンで定義してください。
解答例
graph TD
CAT["Catalog"] -->|OHS/PL| ORD["Order"]
INV["Inventory"] -->|Customer/Supplier| ORD
ORD -->|ACL| PAY["Payment<br/>(Stripe)"]
ORD -->|C/S| SHP["Shipping"]
ORD -->|Partnership| MKT["Marketing"]
REV["Review"] -->|Conformist| CAT
NOTIFY["Notification<br/>← 全Contextからイベント受信"] -.->|Published Language| ORD
NOTIFY -.-> CAT
NOTIFY -.-> PAY
NOTIFY -.-> SHP
CUST["Customer"] -->|OHS| ALL["全サービス"]
classDef core fill:#d4edda,stroke:#28a745,color:#333
classDef ext fill:#fff3cd,stroke:#f0ad4e,color:#333
classDef generic fill:#e8f4fd,stroke:#2196f3,color:#333
class ORD,MKT core
class PAY,CUST,NOTIFY generic
class CAT,INV,SHP,REV ext
関係性の選択理由:
| ペア | パターン | 理由 |
|---|---|---|
| Order → Payment | ACL | Stripe APIの変更から保護 |
| Order ↔ Marketing | Partnership | 注文時のクーポン適用は密連携が必要 |
| Order → Inventory | Customer/Supplier | 注文が在庫に要求を出す |
| Review → Catalog | Conformist | レビューはカタログのモデルに従う |
| Notification | Published Language | 標準イベントフォーマットで疎結合 |
Mission 3: API契約の設計(15分)
要件
Order Context と Inventory Context 間の API 契約を設計してください(在庫確認・引当のフロー)。
解答例
同期API(在庫確認):
# OpenAPI 仕様
paths:
/inventory/{productId}/availability:
get:
summary: 在庫確認
parameters:
- name: productId
in: path
required: true
schema:
type: string
responses:
200:
content:
application/json:
schema:
type: object
properties:
productId:
type: string
available:
type: boolean
quantity:
type: integer
reservableUntil:
type: string
format: date-time
非同期イベント(在庫引当):
// 注文確定 → 在庫引当リクエスト(イベント)
interface StockReservationRequested {
type: 'stock.reservation.requested';
orderId: string;
items: Array<{
productId: string;
quantity: number;
}>;
timestamp: string;
}
// 在庫引当結果(イベント)
interface StockReservationCompleted {
type: 'stock.reservation.completed';
orderId: string;
status: 'reserved' | 'insufficient';
items: Array<{
productId: string;
quantity: number;
reserved: boolean;
}>;
expiresAt: string; // 引当の有効期限
timestamp: string;
}
設計判断: 在庫確認は同期(即時応答が必要)、引当は非同期(Sagaの一部として結果整合性で処理)。
Mission 4: データベース分割計画(15分)
要件
Order/Inventory/Catalog の3サービスのDB分割計画を段階的に策定してください。
解答例
Phase 1: Schema分離(2週間)
-- 共有DBをSchema分離
CREATE SCHEMA order_schema;
CREATE SCHEMA inventory_schema;
CREATE SCHEMA catalog_schema;
-- テーブルを適切なSchemaに移動
ALTER TABLE orders SET SCHEMA order_schema;
ALTER TABLE order_items SET SCHEMA order_schema;
ALTER TABLE products SET SCHEMA catalog_schema;
ALTER TABLE stock_levels SET SCHEMA inventory_schema;
-- 互換性のためにViewを作成
CREATE VIEW public.orders AS SELECT * FROM order_schema.orders;
Phase 2: JOIN解消(4週間)
// Before: SQL JOIN
// SELECT o.*, p.name FROM orders o JOIN products p ...
// After: API Composition
class OrderDetailService {
async getOrderDetail(orderId: string) {
const order = await this.orderRepo.findById(orderId);
const productIds = order.items.map(i => i.productId);
const products = await this.catalogClient.getProducts(productIds);
return this.compose(order, products);
}
}
Phase 3: 物理DB分離(4週間)
| サービス | DB | 選定理由 |
|---|---|---|
| Order | PostgreSQL | トランザクション整合性が重要 |
| Inventory | PostgreSQL + Redis | 在庫数はRedisでキャッシュ |
| Catalog | PostgreSQL + Elasticsearch | 全文検索が必要 |
データ同期戦略:
graph LR
ODB["Order DB"] -->|CDC Debezium| K1["Kafka"] -->|注文実績| CDB["Catalog DB"]
CDB -->|CDC| K2["Kafka"] -->|商品名キャッシュ| ODB2["Order DB"]
IDB["Inventory DB"] -->|CDC| K3["Kafka"] -->|在庫状況表示| CDB2["Catalog DB"]
style ODB fill:#dbeafe,stroke:#2563eb,color:#1e40af
style ODB2 fill:#dbeafe,stroke:#2563eb,color:#1e40af
style CDB fill:#d1fae5,stroke:#059669,color:#065f46
style CDB2 fill:#d1fae5,stroke:#059669,color:#065f46
style IDB fill:#fef3c7,stroke:#d97706,color:#92400e
style K1 fill:#f3e8ff,stroke:#7c3aed,color:#5b21b6
style K2 fill:#f3e8ff,stroke:#7c3aed,color:#5b21b6
style K3 fill:#f3e8ff,stroke:#7c3aed,color:#5b21b6
まとめ
| ポイント | 内容 |
|---|---|
| Context特定 | ビジネスプロセスからBounded Contextを導出 |
| Context Map | 関係性パターンで協調方法を定義 |
| API契約 | 同期/非同期を使い分けて設計 |
| DB分割 | Schema分離→JOIN解消→物理分離の3段階 |
チェックリスト
- Bounded Context を特定しサブドメイン分類できた
- Context Map で関係性を定義できた
- 同期/非同期のAPI契約を設計できた
- 段階的なDB分割計画を策定できた
次のステップへ
次はチェックポイントクイズでサービス境界設計の理解度を確認します。
推定読了時間: 60分