ひとことで言うと#
システムを「同じ言葉が同じ意味を持つ範囲(境界づけられたコンテキスト)」に分割し、コンテキスト間の関係性をマップとして可視化する手法。マイクロサービスの分割やチーム編成の判断基準になる。
押さえておきたい用語#
- Bounded Context(バウンデッド コンテキスト)
- 特定のドメインモデルが通用する明確な境界のこと。「顧客」という同じ言葉でも、営業と配送では意味が違う。その違いが生じる境界がこれにあたる。
- Ubiquitous Language(ユビキタス言語)
- 1つのBounded Context内で開発者とドメインエキスパートが共通で使う用語体系。コンテキストが変われば言語も変わる。
- Context Map(コンテキストマップ)
- Bounded Context同士の関係性を図示した全体地図を指す。上流・下流の力関係や連携方式を可視化する。
- Upstream / Downstream(アップストリーム / ダウンストリーム)
- データや影響を与える側がUpstream、受ける側がDownstream。Upstreamの変更にDownstreamが影響を受ける。
- Anti-Corruption Layer(腐敗防止層)
- 外部コンテキストのモデルが自分のコンテキストに侵入するのを防ぐ変換層である。
境界づけられたコンテキストマッピングの全体像#
こんな悩みに効く#
- モノリスをマイクロサービスに分割したいが、どこで切るべきかわからない
- チーム間で同じ用語が違う意味で使われていて混乱が起きている
- サービス間の依存関係が複雑で、変更の影響範囲が読めない
基本の使い方#
「同じ言葉が違う意味で使われている」箇所を探す。これがコンテキストの境界。
- 「顧客」: 営業では「見込み客+既存客」、配送では「届け先住所」、請求では「請求先」
- 「商品」: カタログでは「画像+説明文」、在庫では「SKU+数量」、配送では「重量+サイズ」
DDDでは以下の関係パターンが定義されている。実態に最も近いものを選ぶ。
- Shared Kernel: 2つのコンテキストが共通モデルを共有(変更には両者の合意が必要)
- Customer-Supplier: Upstream(供給者)がDownstream(消費者)の要求に応じる
- Conformist: Downstreamが無条件にUpstreamのモデルに従う
- Anti-Corruption Layer: Downstreamが変換層を通じて自分のモデルを守る
- Published Language: 共通のスキーマ(JSONスキーマ等)で連携
具体例#
従業員120名のEC企業。10年間で成長したモノリスが30万行に膨れ上がり、1つの機能変更に平均3チームの調整が必要になっていた。
コンテキストマッピングを実施し、「顧客」という言葉の使われ方を調査。
| 部門 | 「顧客」の意味 | 持つ属性 |
|---|---|---|
| マーケティング | 見込み客+既存客 | 流入経路、行動履歴 |
| 受注 | 注文者 | 氏名、配送先、決済情報 |
| カスタマーサポート | 問い合わせ者 | チケット履歴、対応状況 |
| 請求 | 請求先 | 与信枠、支払い方法 |
4つのBounded Contextを識別し、それぞれ独立したサービスに分割。チームも1コンテキスト1チームに再編成した結果、機能変更のリードタイムが平均 3週間 → 4日 に短縮された。
電子カルテSaaS。病院の会計システム、保険請求システム、検査機器メーカーのAPIなど7つの外部システムと連携しており、外部仕様変更のたびに自社のドメインモデルまで汚染されていた。
コンテキストマップを描いたところ、外部システムとの境界に腐敗防止層(ACL)がないことが判明。外部のデータモデルがそのまま自社DBに入り込んでいた。
各外部連携にACLを設置し、外部モデルと自社モデルの変換を明確に分離。外部仕様変更時の影響範囲がACL内に限定され、変更対応の工数が平均 2週間 → 2日 に短縮。内部のドメインモデルの一貫性も回復した。
人口30万人の自治体。住民情報・税務・福祉・都市計画の4部門がそれぞれ独自の「住民」データを持ち、部門間のデータ連携は紙とCSVで行われていた。DX推進で統合データベースを作ろうとしたが、「住民」の定義が部門ごとに違いすぎて頓挫しかけた。
コンテキストマッピングを適用し、あえて統合せずにBounded Contextとして分離。
- 住民基本台帳コンテキスト: 法定情報(住所、世帯、マイナンバー連携)
- 税務コンテキスト: 課税対象者(所得、控除、納税履歴)
- 福祉コンテキスト: 受給者(世帯構成、支援計画)
- 都市計画コンテキスト: 地番単位の居住者
Published Languageとして住民IDと基本属性だけを共通スキーマ化し、各コンテキストはAPIで必要な情報だけを取得する設計にした。無理な統合を諦めたことで、プロジェクトが再始動し 12ヶ月で第一フェーズが稼働 した。
やりがちな失敗パターン#
- 技術的な観点だけで境界を引く — 「DBテーブルの関連」ではなく「同じ言葉が同じ意味を持つ範囲」で境界を決める。技術的な分割だとドメインの境界と合わず、かえって複雑になる
- コンテキストマップを一度描いて放置する — 組織やビジネスが変われば境界も変わる。四半期ごとに見直す習慣をつける
- すべてのコンテキスト間にACLを入れる — ACLはオーバーヘッドがある。信頼できる内部コンテキスト間ではPublished LanguageやShared Kernelで十分な場合も多い
- Bounded Contextを小さくしすぎる — 1テーブル1サービスのような過剰分割は、分散システムの複雑さだけが増える。意味のあるドメインの塊で分ける
まとめ#
Bounded Context Mappingは 「同じ言葉が違う意味を持つ境界」 を明示し、コンテキスト間の関係性をマップとして可視化する手法。マイクロサービスの分割判断やチーム編成の根拠になり、特にモノリスからの段階的移行で威力を発揮する。マップは定期的に見直し、組織とシステムの成長に合わせて進化させることが大切になる。