第32章:依存の向きを決める(依存関係ルール)➡️📏
この章でできるようになること🎯✨
- 「どっちがどっちに依存していいか」を 言葉で説明 できる😊🗣️
- Bounded Context(BC)同士の 依存の向き(矢印) を決められる🧭➡️
- ルールを コードで破れない仕組み(ESLint)にできる👮♀️🚨
- PRレビューで「境界が崩れてる!」を すぐ見抜ける観点が持てる👀✅
32.1 そもそも「依存の向き」ってなに?🧠➡️

BCを箱📦だとすると、依存は矢印➡️です。
-
A➡️B:AがBを使う(AはBがないと困る)
-
依存の向きがぐちゃぐちゃになると…
- 変更が連鎖して止まらない😵💫💥
- 同じ言葉が混ざってモデルが汚れる🧼➡️🧟
- 境界が「ただのフォルダ分け」になって崩壊😇📁
BCの境界を守るには、「矢印のルール」を先に決めるのが超大事です🧱✨
32.2 依存関係ルールの基本セット(まずはこれだけ)📜✨
ここでは、初心者でも運用しやすい“最小ルール”でいきます😊🧸
ルールA:他BCの「中身(internal)」を直接見ない🙈🚫
- OK:相手BCの 公開口(Public API) だけを使う🚪✨
- NG:相手BCの domain / application / internal フォルダを直接 import する📦🔓➡️😱
ルールB:依存の矢印は「片道」を基本にする➡️➡️
- なるべく循環(A➡️B➡️A)を作らない🔁🚫
- どうしても循環っぽくなるなら、受け渡しの形(DTO) や ACL に逃がす🛡️📦
ルールC:「共有」は最小にして、増えそうなら止める✂️🧬
- 共有が増える=調整が増える=速度が死ぬ😵💫⛔
- 共有するなら「本当にブレないもの」だけ(例:IDの型など)🧊✨
32.3 例題(学内フリマ🛍️)で矢印を決めてみよう🗺️➡️
たとえばBCがこんな感じだとします👇
- Listing(出品)📦
- Trading(取引)🤝
- Shipping(配送)🚚
よくある“自然な”依存はこう👇
-
Trading ➡️ Listing
- 取引は「どの商品が出品されてる?」を知りたい
- 出品は「取引がどうなってる?」を知らなくていい
-
Shipping ➡️ Trading
- 配送は「取引が成立した?」を知りたい
- 取引は「配送会社の都合」を知らなくていい
つまり、
- Listing ⬅️ Trading ⬅️ Shipping
みたいな 片方向チェーン になりやすいです😊➡️➡️
ポイント💡 「どっちが“元データの持ち主(真実の源)”か?」で決めるとブレにくいよ🧠✨
32.4 依存の向きを決める4つの質問🤔🧭
矢印に迷ったら、この4問でだいたい決まります✅✨
-
どっちが真実の源(Source of Truth)? 🏛️
- “持ってる側”に依存しがち
-
どっちの変更が多い? 🔥
- 変更が多い側が、少ない側に依存すると事故りやすい😇💥
-
問い合わせるのはどっち?(呼び出し方向) 📞
- 「知りたいから呼ぶ」側が依存する➡️
-
循環(A➡️B➡️A)になってない? 🔁
- なってたら黄色信号⚠️
- DTO/ACL/イベントなど、境界越えの形を見直す🧼🛡️
32.5 依存ルールを「1枚」にするテンプレ📝✨
決めたら、短くていいので文章化します(ここ超大事)📌😊 例👇(そのまま貼って使えるよ🧸✨)
- 依存の基本:BC間の依存は片方向を基本とする➡️
- 禁止:他BCの内部フォルダを直接 import しない🙈🚫
- 許可:他BCは公開口(各BCの入口)だけ import してよい🚪✨
- 例外:どうしても必要な場合はDTO/ACLで受け渡しし、例外理由を短く残す🛡️📦
- 守り方:ESLintで機械的に検出してPRで止める👮♀️🚨
4. ルールをコードで守る(ESLint)👮♀️🚨

依存ルールを「気合い」で守るのは不可能です😇 だから、フォルダで“破りにくく”します💪📁
例(イメージ)👇
src/
contexts/
listing/
index.ts // ✅ 公開口(Public API)
domain/
application/
infrastructure/
internal/ // ✅ ここは外から触らせない想定
trading/
index.ts
domain/
application/
infrastructure/
internal/
ここでの狙い🎯
- 他BCからは「contexts/◯◯/index.ts」だけ触れればOKにする🚪✨
- 「internal/」配下を触ろうとしたら、機械的に怒られるようにする👮♀️💢
32.7 ESLintで「破ったら即エラー」にする👮♀️🚨
今どきESLintは Flat Config(設定ファイル形式)が標準です📄✨(設定ファイル名も決まってるよ)(ESLint) さらにESLint v9ではFlat Configがデフォルトになった流れが整理されています。(ESLint) そして、ESLint v10は2026年1月にRC(リリース候補)が出ています。(ESLint)
① まず導入(必要パッケージ)📦✨
typescript-eslint のクイックスタートでは、Flat Config前提で「ESLint + TypeScript + typescript-eslint」を入れて設定する流れが案内されています。(TypeScript ESLint)
(例)
npm install --save-dev eslint @eslint/js typescript typescript-eslint
② eslint.config.mjs を作る📄✨
typescript-eslintの推奨構成は、defineConfigと recommended を組み合わせる形です。(TypeScript ESLint)
// eslint.config.mjs
// @ts-check
import eslint from "@eslint/js";
import { defineConfig } from "eslint/config";
import tseslint from "typescript-eslint";
export default defineConfig(
eslint.configs.recommended,
tseslint.configs.recommended,
// ここから「境界を守るルール」を追加していくよ👮♀️✨
);
③ “境界違反import” を禁止する(最小構成)🚫➡️
ここで使うのが「特定のimportを禁止できる」ルールです。(ESLint) TypeScriptでは type import などもあるので、typescript-eslint版(拡張ルール)を使うのが安全です🧷✨(ベースルールをoffにする注意も書かれています)(TypeScript ESLint)
例:他BCの internal を触ったらアウト🙅♀️
// eslint.config.mjs(さっきの続き)
import eslint from "@eslint/js";
import { defineConfig } from "eslint/config";
import tseslint from "typescript-eslint";
export default defineConfig(
eslint.configs.recommended,
tseslint.configs.recommended,
{
files: ["src/**/*.ts"],
rules: {
// TypeScriptでは拡張ルールを使うのが安心🧸
"no-restricted-imports": "off",
"@typescript-eslint/no-restricted-imports": [
"error",
{
// patterns で “禁止するパスの型” を指定できるよ🧩
// (patterns/group などのオプションがある):contentReference[oaicite:7]{index=7}
patterns: [
{
group: ["src/contexts/*/internal/**"],
message:
"他BCの internal は触らないでね🛡️ 公開口(各BCの index.ts)経由で使おう✨",
},
{
group: ["src/contexts/*/domain/**", "src/contexts/*/application/**", "src/contexts/*/infrastructure/**"],
message:
"他BCの中身は直接import禁止🙈 公開口(index.ts)だけにしよう🚪✨",
},
],
},
],
},
}
);
これで、誰かがうっかり 「contexts/listing/domain/…」を import した瞬間に、VS Code上で赤く怒られます💢🔴(最高)✨
32.8 もっと強く守りたい人向け:境界専用プラグイン🧱🔍(任意)
「禁止パターン」だけでも十分強いけど、 “大きい構成”になると 境界ルール専用プラグイン が便利です😊✨
たとえば ESLint Plugin Boundaries は「アーキテクチャ境界を強制する」系のプラグインとして紹介されています。(GitHub)
ここは発展枠🎓✨ まずは 32.7 の禁止パターンで“事故を止める”だけでも合格です💮😊
32.9 ミニ演習🎮✨(破って学ぶのが最速!)
演習1:わざと境界違反してみよう😈➡️👮♀️
- trading 側のどこかで、listing の domain を直接 import してみる
- ESLintに怒られるのを確認する🔴💢
- 「listing/index.ts」に必要な公開関数を出して、そっち経由に直す🚪✨
✅ ゴール:“直し方が毎回同じ” になったら勝ち🎉
演習2:依存の矢印を図にする🗺️✏️
- Listing / Trading / Shipping の箱を書いて
- 依存する方向に矢印を書くだけ➡️➡️
- 循環があったら、DTO/ACLで逃がす案を1つ書く🛡️📦
32.10 AI相棒🤖✨:そのまま使える質問テンプレ
テンプレA:依存の向きをレビューしてもらう🧠➡️
- 「Listing / Trading / Shipping がある。今の依存はこう。循環が出ない矢印に直して。理由も一言で。」
テンプレB:ESLintルールの“抜け”を探してもらう👮♀️🔍
- 「この eslint.config.mjs で境界を守ってる。抜け道(すり抜けimport)がありそうなら指摘して、塞ぐ案を出して。」
テンプレC:公開口の設計を手伝ってもらう🚪✨
- 「このBCの外に出すべき関数/型を“最小”で提案して。外に出しちゃダメなものも列挙して。」
32.11 よくある失敗あるある集😵💫⚠️
- 「とりあえず使えたから…」で他BCの domain を直importし始める🙈
- index.ts が薄すぎて、みんな中身を覗きに行く👀💥
- 共有フォルダに便利関数が増殖して、実質“第2のBC”になる🧟📦
全部、ルールとESLintで止めればOKです👮♀️✨
32.12 おまけ:最近の開発安全メモ🔐📦
npm周りでは、人気パッケージが乗っ取られて悪性バージョンが出た事例が報じられています(例:eslint-config-prettier など)。(TechRadar) なので、最低限これだけはやっておくと安心度が上がるよ🧸🛡️
- lockfile(package-lock など)はコミット📌
- 依存更新はまとめてやらず、小さく刻む✂️
- 怪しい時はリリースノートや差分を見る👀
まとめ🎁✨
- 依存の向きは「真実の源」「呼び出し方向」「循環チェック」で決める🧭
- ルールは文章化して1枚にする📝
- 気合いで守らず、ESLintで“破ったら即エラー”にする👮♀️🚨
- まずは「他BCの中身をimport禁止」だけでも境界が一気に強くなる🧱✨