第22章:境界づけられたコンテキスト🗺️🏰

〜1つのアプリの中に「小さな独立国」を作る話〜✨
今日のゴール🎯
この章が終わると…
- 「同じ言葉なのに意味が違う…😵」を設計で防ぐ考え方がわかる
- 1つのアプリの中に、役割が違う“国”を分けて考える感覚が身につく
- AIに頼るときも、どの国の話かブレないようにできる🤖💡
まずは超たとえ話🍙🏫
あなたの大学にこんな2つの場所があるとするね👇
- 学食: “注文”=「ごはんを頼む」
- 図書館: “注文”=「本を取り寄せる」
同じ「注文」でも意味が全然違うよね?📚🍛 もし大学のルールブックが1冊で、両方ごちゃ混ぜだったら…混乱するはず😇
DDDの「境界づけられたコンテキスト(Bounded Context)」は、まさにこれを防ぐ仕組みだよ🚧✨
「コンテキスト」ってなに?🤔
ざっくり言うと…
ある言葉やルールが“同じ意味”で通じる範囲📦
たとえば「ユーザー」って言葉も、場所によって意味が変わることがあるよね👇
- ログインの「ユーザー」=アカウント情報が大事🔐
- 販売の「ユーザー」=購入履歴や住所が大事📦
- 運営の「ユーザー」=問い合わせや通報が大事🛠️
全部を1つの「User」クラスに背負わせると…だいたい地獄が始まるよ😇🔥
境界づけられたコンテキスト(Bounded Context)とは?🏰
ひとことで言うと…
アプリ内にある“意味が統一される範囲”を、境界で区切って別世界にすること🚧
境界の内側は「この国の法律(ルール)」が通る 境界の外側に行くと「別の国の法律」が通る だから、国境を越えるときはパスポート(変換・翻訳)が必要✈️🛂
どうして分けるの?(1人開発でも超重要)🧠✨
1人だと「全部わかってるし、分けなくてもいいじゃん😎」って思いがちなんだけど…
- 数週間後の自分は記憶が抜けた別人👤💭
- AIは部分最適しがちで、言葉の意味が混ざると盛大にズレる🤖💥
- 「Userが何者か」がブレると、修正が芋づる式になる🍠😵
だから最初に「この国ではこの意味ね!」を決めると強い💪✨
境界を見つける“4つのサイン”🔍🚦
次のどれかが出たら、コンテキスト分割の候補だよ👇
- 同じ言葉が、場面で意味が変わる(例:ユーザー、注文、ステータス)🌀
- ルールが違う(割引の条件、承認フロー、計算式など)📏
- 変更の理由が違う(片方は法務、片方はUI都合…みたいな)🛠️
- 関係者が違う(管理者、顧客、倉庫担当…)👥
具体例:サークル管理アプリで分けてみよう🎺📅💰
「サークル管理アプリ」を想像してみてね😊 よくある機能を並べると…
- 入部・退部、プロフィール管理(名簿)👤
- イベント作成、出欠管理📅
- 部費管理、会計💰
- 連絡、通知📩
これ、ぜんぶ「サークルアプリ」だけど、意味の世界は4つに分けられるかも👇
- Membership(名簿の国):会員・役職・在籍
- Events(イベントの国):日程・出欠・定員
- Accounting(会計の国):部費・支払い・未納
- Messaging(連絡の国):通知・送信履歴
ざっくり図にするとこんな感じ🗺️
ポイントはこれ👇 「会員(Member)」の意味は名簿の国が一番えらい👑 イベントの国は「会員の詳細」を全部知らなくてもよくて、必要な情報だけ持てばOK✨
「同じクラス名」があってもいいの?→ いいよ🙆♀️✨
境界づけられたコンテキストでは、むしろ…
- それぞれの国に、それぞれの“正しいモデル”があってOK✅
たとえば「User」って名前が被るなら、国ごとに分けよう👇
namespace Membership.Users
{
public class User
{
public required string UserId { get; init; }
public required string DisplayName { get; init; }
public bool IsActive { get; init; }
}
}
namespace Accounting.Users
{
public class User
{
public required string UserId { get; init; }
public required string BillingName { get; init; }
public bool IsDelinquent { get; init; } // 未納フラグ
}
}
同じ「User」でも、国が違えば正義が違うのだ🏰✨ (ここで無理に共通化すると、カオスになりやすいよ😇)
国境を越えるときは「翻訳」する🛂✨
コンテキスト間でデータを渡すときは、そのまま相手のモデルを使わないのが基本だよ🙅♀️
たとえば名簿の国 → イベントの国へ「参加者情報」を渡すなら、イベント側が欲しい形にする👇
public record ParticipantInfo(string MemberId, string DisplayName);
- 名簿の国:Memberの詳細を持つ(学部、学年、連絡先…)
- イベントの国:出欠に必要な最低限だけ(IDと表示名)
こうすると、名簿の仕様が変わってもイベントが巻き込まれにくい👍✨
AIに強くなる「境界づけ」プロンプト例🤖🧠
AIに頼むときは、「どの国の話か」を最初に固定するとブレにくいよ✨ コピペで使える感じにしておくね👇
あなたはDDDの設計者です。
対象アプリ:サークル管理アプリ
今は「Events(イベントの国)」の話だけをします。
- Eventsの責務(この国が持つルール)を箇条書きで
- Membershipに依存しないために、Eventsが持つべきデータだけを定義して
- Events内で使う用語集(ユビキタス言語)を10個出して
さらに「国境越え」も頼める👇
Membership(名簿)→ Events(イベント)へ渡すデータの契約を作りたい。
Events側が必要な情報だけを持つDTO/recordを提案して。
将来、Membershipの項目が増減してもEventsに影響が出ない形にして。
ミニ演習✍️✨(ここが一番大事!)
あなたが作りたいアプリで、次をやってみてね😊💕
演習1:言葉の衝突探し💥
「同じ言葉だけど意味が違いそう」な単語を5個書こう👇 例:ユーザー、注文、ステータス、承認、公開…
演習2:国を3つに分ける🏰🏰🏰
機能を眺めて、「変更理由が違うもの」を分けてみよう✨ (最初は雑でOK!🌱)
演習3:国の“憲法”を書く📜
各国についてこれを1行ずつ👇
- この国が守るルールは?
- この国の中心データは?
- 他国から勝手に入られたくないものは?🚧
まとめ🌟
- コンテキスト=言葉とルールの意味が統一される範囲📦
- 境界づけられたコンテキスト=アプリ内の小さな独立国🏰
- 国境を越えるときは、翻訳(DTO/record)で渡す🛂
- AI活用でも「今どの国の話か」を固定すると強い🤖✨
次の第23章では、この「国境」を実際の開発でどう置くか(フォルダ?プロジェクト?)を、めちゃ現実的に決めていくよ〜🚧📁✨