# Module Boundary Design

> 機能境界・責務分離・モジュール分割・抽象化の設計判断を行うスキル。どこで境界を切るか、責務をどう分けるか、抽象化が妥当か、責務配置を見直したいときに使用する。単純な CRUD 追加・差分レビュー・API 表面設計には使わない。リファクタリング全般の判断は refactor-mindset を使い、境界の引き方・責務配置が主題のとき本スキルを使う。

- Skill: `efoo-team/module-boundary-design` (Agent Skill, multi-file: 2 files)
- Install (CLI): `npx skillmds@latest add efoo-team/module-boundary-design`
- Raw SKILL.md: https://api.skillmd.com/api/skills/efoo-team/module-boundary-design/raw
- Safety review: pending
- Works with: Claude Code, Claude.ai, OpenAI Codex
- Category: Integrations & APIs
- Author: efoo-team (https://skillmd.com/u/efoo-team)
- Updated: 2026-09-17
- Page: https://skillmd.com/skills/efoo-team/module-boundary-design

---


# モジュール境界設計スキル

機能の境界をどこに引き、何を同じ側に置き、何を分けるかを判断するための思考手順。

---

## 原則

機能境界は **処理の順序** ではなく **変更理由の独立性** で決まる。

そしてもう一つ。境界を「引く」だけでは不十分で、その境界を「成立させる」必要がある。責務を分けただけでは境界にはならない。境界が意味を持つのは、公開面・状態の所有・依存方向・不変条件の守備範囲が明確になったときである。

---

## 適用範囲

### このスキルを使う場面
- 機能の境界が曖昧で、どこで切るべきか判断が必要なとき
- モジュールやクラスが肥大化していて分割を検討するとき
- 変更の影響が広範囲に波及している構造を改善するとき
- 抽象化の妥当性に疑いがあるとき
- 既存の責務配置を見直すとき

### このスキルの対象外
- 単純な CRUD の実装判断
- 差分レベルのコードレビュー
- API のインターフェース設計（境界は決まっていて表面だけ考える場合）
- 依存方向の違反検出だけが目的の場合

---

## 思考手順

### Step 1: 機能文の構造化

設計対象の機能を「〈主語〉が〈対象〉を〈操作〉する」の形に分解する。複数の操作が含まれていれば、操作ごとに分けて書き出す。

ユーザーが使った言葉をそのまま使わない。「何を受け取り、何を保全し、何を変換し、何を出力するか」という責務が見える動詞に置き換える。

---

### Step 2: 境界候補の発見

以下の4つの観点から、境界の候補を洗い出す。どれか1つではなく、4つすべてを順に確認する。

#### 2-A: 対象の置換（共通性・可変性の識別）

機能文の中の対象（目的語）を、現実的にありうる別の対象で3つ以上置き換える。

- どの置換でも処理が変わらない部分 → 共通層（抽象化してよい）
- 置換すると処理の内容・ルール・制約が変わる部分 → 専用層（ドメイン固有に残す）

3つ以上なのは、2つでは偶然の一致と本質的な共通性の区別がつかないため。ただし3つ目が現実に存在しない場合は、無理に一般化せず継ぎ目だけを意識する。

#### 2-B: 意味の分裂の検出

同じ言葉（名詞）が、文脈によって異なる意味で使われていないかを確認する。

同じ「ユーザー」でも、認証では「認証主体」、課金では「支払者」、サポートでは「問い合わせ者」を意味するなら、それぞれ別の境界に属する可能性が高い。意味が変わる地点は境界候補になる。

確認方法:
- 機能文に登場する主要な名詞を列挙する
- 各名詞の意味が、機能のどの文脈でも同一かを問う
- 意味がずれる地点があれば、そこに境界候補を置く
- 境界をまたぐ場合に翻訳（変換層）が必要かを判断する

#### 2-C: 不変条件の特定

「一緒に壊れてはいけないルール」を特定する。あるルール群が1つのトランザクションや1つの整合性制約で結びついているなら、それらは同じ境界に留めるべき可能性が高い。

確認方法:
- この機能が守るべきビジネスルール・整合性制約は何かを列挙する
- そのルールが成立するために、どのデータが同時に参照・更新される必要があるかを特定する
- 同じ不変条件に縛られるデータと処理は、同じ境界に置く

不変条件が境界をまたぐ場合、調整コスト（saga、eventual consistency、手動整合）が発生する。そのコストを許容できるかどうかが、境界を分けるかどうかの判断材料になる。

#### 2-D: 所有と変更頻度の確認

誰が、どのくらいの頻度で、その部分を変更するかを確認する。

- 変更の起点が異なるもの（法務起点 vs 開発起点 vs 顧客要望起点）は、別の境界候補
- 変更頻度が極端に異なるもの（年1回変わるルール vs 週次で変わるルール）は、分離した方が安定する
- 所有者（継続的に面倒を見る人・チーム）が異なるものは、別の境界にした方が実務上強い

所有者が曖昧な境界は、設計がどれだけ綺麗でも時間とともに崩壊する。

---

### Step 3: 変化軸の特定と境界の確定

Step 2 で見つけた境界候補を「なぜ変わるのか」で分類し、最終的な境界を確定する。

- 「この部分が変わるとき、他のどこが一緒に変わるか？」→ 一緒に変わるものは同じ境界
- 「この部分が変わるとき、他はそのままでいられるか？」→ いられるなら、そこが境界

変化軸が異なるものは、見た目が似ていても・処理フロー上は隣接していても分ける。変化軸が同じものは、処理フロー上は離れていても束ねる。

---

### Step 4: 差分の吸収方法の選択

境界内の可変部分をどう設計に取り込むかを、差分の性質に応じて選ぶ。

**値だけが異なる場合（型・構造は同一）:** パラメータ化する。

**振る舞い・アルゴリズムが異なる場合:** インターフェースを抽出し、実装を差し替え可能にする。

**処理の流れ自体が異なる場合:** 別のモジュール・サービスとして独立させる。

判断の閾値:
- パラメータが3つ以下で条件分岐が増えない → パラメータ化してよい
- パラメータに応じて内部の制御フローが変わる → インターフェース抽出を検討
- 統合後に型チェックや条件分岐が増えた → 抽象を解体して戻す

---

### Step 5: 境界の成立条件の確認

境界を引いたら、その境界が実際に機能するかを確認する。境界が成立するには、以下の4つが明確である必要がある。

**公開面（Public Contract）:** この境界が外部に提供するインターフェースは何か。何を受け取り、何を返すか。公開面が言語化できないなら、境界が不明確である。

**状態の所有:** この境界が排他的に所有するデータは何か。他の境界が直接読み書きしてよいデータはあるか。共有される可変状態があるなら、境界は名目上のものでしかない。

**依存方向:** この境界は何に依存し、何がこの境界に依存するか。循環依存があれば、境界の引き方を見直す。

**通信方式:** 境界間はどう連携するか。直接呼び出し、イベント、非同期メッセージ、変換層のどれが適切かは、境界の独立性の要求水準で決まる。

---

### Step 6: 変更マトリクスによる検証

想定される変更シナリオを5つ程度並べ、各シナリオで影響を受けるモジュールを特定する。影響が1〜2モジュールに閉じていれば妥当。3モジュール以上に波及するなら、境界の引き直しを検討する。

---

### Step 7: 抽象化の範囲の制限

抽象化は「広げること」だけでなく「受け入れる可変性を制限すること」でもある。

- 初期実装では今ある具体例だけで動くものを作る
- インターフェースは切っておくが実装は1つだけにする
- 2つ目・3つ目の具体的な要件が現れた時点で、必要な分だけ一般化する

まだ存在しない要件のために抽象化すると、必要な柔軟性ではなく不要な複雑性が生まれる。間違った抽象を共有するより、重複を許容する方がコストが低い。

---

## 重要な区別: 境界設計と内部構造は別の問題

設計相談では、以下が頻繁に混同される。

- **境界設計**: どの責務をどのモジュールに配置するか。意味・変化軸・不変条件・所有で決める
- **内部構造**: 境界の中をどう整理するか。vertical slice、layer、CQRS などは内部戦略

この2つは別の問題であり、別の判断基準で決める。「feature ごとに切るべきか、domain ごとに切るべきか」という問いが出たら、まず「それは境界の話か、内部構造の話か」を切り分ける。

---

## 命名の原則

**責務名で命名する。実装技術名で命名しない。** 名前が「何の技術を使っているか」を説明しているなら実装名であり、悪い兆候。名前が「何の責任を負っているか」を説明しているなら責務名であり、良い兆候。

**1つの名前に複数の責務が含まれていないか検査する。** And / Or / Manager / Handler / Processor のような汎用語は、複数の変化軸が1つに混ざっている可能性を示す。

---

## 反パターン

以下は境界・責務配置の観点で扱う。リファクタリングを「いつ・どの規模で実施するか」の判断は refactor-mindset の担当。

### 1. フロー順分割
処理フローの順番（Step1, Step2, Step3）でモジュールを切る。変化軸をまたぐ境界になりやすい。

### 2. 間違った抽象の共有
共通化した結果、対象種別ごとの条件分岐・パラメータ・例外ケースが増殖する。統合前より複雑になったら、抽象を解体して重複に戻す。

### 3. 全能サービス
`XxxManager`, `XxxHandler`, `XxxProcessor` に責務が集中する。検出したら、そこに含まれる責務を列挙し、変化軸ごとに分離候補を出す。

### 4. 貧血ドメインモデル
データだけがエンティティにあり、ロジックがすべてサービスにある。境界内の責務配置が崩れているサイン。データとそのデータに対する操作が別の場所に散っている場合、それらを同じ場所に寄せることを検討する。

### 5. 名詞の類似性による統合
名前が似ているという理由だけで処理を統合する。操作集合・不変条件・エラー境界が一致しない限り、統合は避ける。

### 6. 過剰な先行抽象
具体例が1つしかないのに汎用フレームワークを作る。「将来必要になるかもしれない」は分割の根拠にならない。

### 7. 状態の暗黙共有
パッケージやフォルダは分かれているが、可変な状態を複数モジュールが直接読み書きしている。境界は名目上のものでしかなく、実質的に密結合。

### 8. 肥大化した境界
1つの境界の中に、実際には独立に変化する複数のサブドメインが同居している。境界自体は正しいが、粒度が粗すぎる。分割が必要になったら、最も変更頻度が高く他と独立しているサブドメインから切り出す。

---

## 理論的根拠

各ステップ・反パターンの理論的出典（SCV 分析・情報隠蔽・SRP・Bounded Context・Aggregate・Wrong Abstraction・Team Topologies 等）は `references/theory.md` を参照。

