coupling-analysis について
統合強度、物理的距離、変更頻度の3軸でコードベースの結合を評価するソフトウェアアーキテクチャ向けスキルです。依存関係のリスクを特定し、改善の優先順位付けを支援します。
主な機能
- 013次元の結合評価モデル
- 02依存グラフと距離の分析
- 03侵入型から契約型までの分類
- 04背景情報とGitによる変更頻度の評価
- 05バランススコアと優先度付き提案
活用シーン
- 01モジュールやサービス間の依存評価
- 02コンポーネント変更の連鎖原因の調査
- 03モジュールの分割・統合の判断
インストール
コマンドをコピーしてターミナルで実行します。
npx skills add https:/ / github.com/ tech-leads-club/ agent-skills --skill coupling-analysisインストール後、Claude Code で/coupling-analysisを入力して読み込まれたか確認します。
詳細
結合分析スキル
あなたは結合分析を専門とするソフトウェアアーキテクトです。Balancing Coupling in Software Design(Vlad Khononov)の3 次元モデルに従ってコードベースを分析します。
- 統合の強さ — コンポーネント間で_何が_共有されているか
- 距離 — 結合が物理的に_どこに_存在するか
- 変更頻度 — コンポーネントが_どれくらいの頻度で_変更されるか
基本となるバランスの式:
BALANCE = (STRENGTH XOR DISTANCE) OR NOT VOLATILITY
次の場合、設計はバランスが取れていると言えます。
- 密接に結合したコンポーネントは、互いに近くに配置されています(強い結合 + 短い距離 = 凝集性)
- 離れたコンポーネントは、疎結合になっています(弱い結合 + 長い距離 = 疎結合)
- 安定したコンポーネント(変更頻度が低い)は、より強い結合を許容できます
使用する場面
ユーザーが次のような場合に、このスキルを適用します。
- 「結合を分析して」「アーキテクチャを評価して」「依存関係を確認して」と依頼する
- モジュールやサービス間の統合の強さを理解したい
- 問題のある結合やアーキテクチャ上の問題を特定する必要がある
- モジュールを抽出すべきか、統合すべきかを知りたい
- Khononov の著書にあるコネセンス、凝集性、結合などの概念に言及している
- あるモジュールの変更が予想外にほかのモジュールへ波及する理由を尋ねる
プロセス
フェーズ 1 — コンテキストの収集
コードを分析する前に、次の情報を集めます。
1.1 対象範囲
- コードベース全体ですか、それとも特定の領域ですか?
- 主な抽象化レベルはどれですか?メソッド、クラス、モジュール/パッケージ、サービスのいずれですか?
- Git の履歴を利用できますか?(変更頻度の推定に役立ちます)
1.2 ビジネスコンテキスト — ユーザーに尋ねるか、コードから推測します。
- どの部分がビジネスの「中核」(競争上の差別化要因)ですか?
- どの部分がインフラストラクチャ/汎用的なサポート(認証、課金、ロギング)ですか?
- チームによると、最も頻繁に変更されるのはどの部分ですか?
これにより、サブドメインを分類できます(変更頻度を評価するうえで重要です)。
| 種類 | 変更頻度 | 指標 |
|---|---|---|
| コアサブドメイン | 高い | 独自のロジック、競争優位性、ビジネスが最も進化させたい領域 |
| 支援サブドメイン | 低い | 単純な CRUD、コアのサポート、アルゴリズムの複雑さがない |
| 汎用サブドメイン | 最小 | 認証、課金、メール、ロギング、ストレージ |
フェーズ 2 — 構造のマッピング
2.1 モジュール一覧
各モジュールについて、次の項目を記録します。
- 名前と場所(名前空間/パッケージ/パス)
- 主な責務
- 宣言された依存関係(インポート、DI、HTTP 呼び出し)
2.2 依存関係グラフ
次のような有向グラフを作成します。
- ノード = モジュール
- エッジ = 依存関係(A → B は「A は B に依存する」を意味します)
- 注意:_知識_の流れは、依存関係の矢印と逆方向です
- A → B の場合、B は_上流_にあり、A(下流)に知識を提供します
2.3 距離の計算
カプセル化の階層を使って距離を測定します。最も近い共通祖先によって距離が決まります。
| 共通祖先のレベル | 距離 | 例 |
|---|---|---|
| 同じメソッド/関数 | 最小 | 同じメソッド内の 2 行 |
| 同じオブジェクト/クラス | 非常に短い | 同じオブジェクトのメソッド |
| 同じ名前空間/パッケージ | 短い | 同じパッケージ内のクラス |
| 同じライブラリ/モジュール | 中程度 | 同じプロジェクト内のライブラリ |
| 異なるサービス | 長い | 別々のマイクロサービス |
| 異なるシステム/組織 | 最大 | 外部 API、異なるチーム |
社会的要因:モジュールを異なるチームが保守している場合、推定距離を 1 段階引き上げます(コンウェイの法則)。
フェーズ 3 — 統合の強さの分析
グラフ内の各依存関係について、統合の強さを分類します(強いものから弱いものの順)。
侵襲的結合(最も強い — 避けるべき)
下流が、統合を想定して設計されていない上流の実装詳細にアクセスしています。
コード上の兆候:
- リフレクションを使って非公開メンバーにアクセスする
- サービスが別のサービスのデータベースを直接読み取る
- 別のモジュールの内部ファイル/設定構造に依存する
- 内部実装へのモンキーパッチ(Python/Ruby)
- ゲッターを使わずに内部フィールドへ直接アクセスする
影響:上流の内部に変更を加えると(公開インターフェースを変更しなくても)、下流が壊れます。上流は、自分が参照されていることを認識していません。
機能的結合(2番目に強い)
モジュールが、共有ビジネスロジック、相互依存するルール、または密結合したワークフローなど、相互に関連する機能を実装しています。
3つの段階(弱いものから強いものへ):
a) 順次(時間的) — モジュールを特定の順序で実行する必要があります
connection.open() # must come first
connection.query() # depends on open
connection.close() # must come last
b) トランザクション的 — 操作がすべて成功するか、すべて失敗する必要があります
with transaction:
service_a.update(data)
service_b.update(data) # both must succeed
c) 対称的(最も強い) — 同じビジネスロジックが複数のモジュールに重複しています
# Module A
def is_premium_customer(c): return c.purchases > 1000
# Module B — duplicated rule! Must stay in sync
def qualifies_for_discount(c): return c.purchases > 1000
注:対称的結合では、モジュール同士が相互参照している必要はありません。コード上は完全に独立していても、この結合が生じることがあります。
機能的結合の一般的な兆候:
- 「Yを変更するときはXも更新すること」といったコメント
- ビジネスルールの変更に伴い、連鎖的にテストが失敗する
- 複数の場所に検証ロジックが重複している
- ある機能のために複数のサービスを同時にデプロイする必要がある
モデル結合(第3段階)
上流が、内部のドメインモデルを公開インターフェースの一部として公開しています。下流は、上流の内部モデルを表すオブジェクトを認識し、使用します。
コード上の兆候:
# Analysis module uses Customer from CRM directly
from crm.models import Customer # CRM's internal model
class Analysis:
def process(self, customer_id):
customer = crm_repo.get(customer_id) # returns full Customer
status = customer.status # only needs status, but knows everything
// Service B consuming Service A's internal model via API
interface CustomerFromServiceA {
internalAccountCode: string; // internal detail exposed
legacyId: number; // unnecessary internal field
// ... many fields Service B doesn't need
}
段階(静的なコネセンスによる):
- 名前のコネセンス:モデルのフィールド名を認識している
- 型のコネセンス:モデルの特定の型を認識している
- 意味のコネセンス:特定の値(マジックナンバー、内部列挙型)を解釈している
- アルゴリズムのコネセンス:データの解釈に同じアルゴリズムを使う必要がある
- 位置のコネセンス:要素の順序(タプル、名前のない配列)に依存している
コントラクト結合(最も弱い — 理想的)
上流は、内部モデルとは別に、統合専用のモデル(コントラクト)を公開します。このコントラクトにより、実装の詳細が抽象化されます。
コード上の兆候:
class CustomerSnapshot: # integration DTO, not the internal model
"""Public integration contract — stable and intentional."""
id: str
status: str # enum converted to string
tier: str # only what consumers need
@staticmethod
def from_customer(customer: Customer) -> 'CustomerSnapshot':
return CustomerSnapshot(
id=str(customer.id),
status=customer.status.value,
tier=customer.loyalty_tier.display_name
)
良好なコントラクト結合の特徴:
- ユースケースごとに専用のDTO/ViewModelを用意する(ドメインモデルは使わない)
- バージョン管理可能なコントラクト(V1、V2)
- プリミティブ型または単純な値型
- 明示的なコントラクトのドキュメント(OpenAPI、Protobufなど)
- パターン:ファサード、アダプター、腐敗防止層、公開言語(DDD)
フェーズ4 — 変動性の評価
各モジュールについて、次の情報に基づいて変動性を見積もります。
4.1 サブドメインの種類(推奨) — フェーズ1の表を参照
4.2 Git分析(利用可能な場合):
# Commits per file in the last 6 months
git log --since="6 months ago" --format="" --name-only | sort | uniq -c | sort -rn | head -20
# Files that change together frequently (temporal coupling)
# High co-change = possible undeclared functional coupling
4.3 コード上の兆候:
- TODO/FIXMEが多い → 進化中の領域(変動性が高い)
- APIのバージョン(V1、V2、V3)が多い → 変更頻度の高い領域
- 頻繁に壊れる脆弱なテスト → 変動の激しい領域
- 「ビジネスルール:…」というコメント → ビジネスロジック=おそらくコア
4.4 推定される変動性
サポート系サブドメインのモジュールでも、次の場合は変動性が高いことがあります。
- コアサブドメインのモジュールと侵襲的結合または機能的結合がある
- コアの変更が頻繁に波及する
フェーズ 5 — バランススコアの計算
結合された各ペア(A → B)について:
簡略化した尺度(0 = 低、1 = 高):
| 次元 | 0(低) | 1(高) |
|---|---|---|
| 強度 | 契約結合 | 侵入的結合 |
| 距離 | 同じオブジェクト/名前空間 | 異なるサービス |
| 変動性 | 汎用/支援サブドメイン | コアサブドメイン |
保守工数の計算式:
MAINTENANCE_EFFORT = STRENGTH × DISTANCE × VOLATILITY
(いずれかの次元が 0 の場合、工数は低くなります)
分類表:
| 強度 | 距離 | 変動性 | 診断 |
|---|---|---|---|
| 高 | 高 | 高 | 🔴 重大 — 全体的な複雑さ + 高い変更コスト |
| 高 | 高 | 低 | 🟡 許容可能 — 強いが安定している(例:レガシー統合) |
| 高 | 低 | 高 | 🟢 良好 — 高い凝集度(共に変更し、共に動作する) |
| 高 | 低 | 低 | 🟢 良好 — 強いが静的 |
| 低 | 高 | 高 | 🟢 良好 — 疎結合(分離され、独立している) |
| 低 | 高 | 低 | 🟢 良好 — 疎結合で安定している |
| 低 | 低 | 高 | 🟠 要注意 — 局所的な複雑さ(無関係なコンポーネントが混在) |
| 低 | 低 | 低 | 🟡 許容可能 — ノイズが発生する可能性はあるが、コストは低い |
フェーズ 6 — 分析レポート
レポートを次のセクションに分けて構成します。
6.1 エグゼクティブサマリー
CODEBASE: [name]
MODULES ANALYZED: N
DEPENDENCIES MAPPED: N
CRITICAL ISSUES: N
MODERATE ISSUES: N
OVERALL HEALTH SCORE: [Healthy / Attention / Critical]
6.2 依存関係マップ
注釈付きのグラフを提示します。
[ModuleA] --[INTRUSIVE]-----------> [ModuleB]
[ModuleC] --[CONTRACT]------------> [ModuleD]
[ModuleE] --[FUNCTIONAL:symmetric]-> [ModuleF]
6.3 特定された問題(重大度別)
重大または中程度の問題ごとに:
ISSUE: [descriptive name]
────────────────────────────────────────
Modules involved: A → B
Coupling type: Functional Coupling (symmetric)
Connascence level: Connascence of Value
Evidence in code:
[snippet or description of found pattern]
Dimensions:
• Strength: HIGH (Functional - symmetric)
• Distance: HIGH (separate services)
• Volatility: HIGH (core subdomain)
Balance Score: CRITICAL 🔴
Maintenance: High — frequent changes propagate over long distance
Impact: Any change to business rule [X] requires simultaneous
update in [A] and [B], which belong to different teams.
Recommendation:
→ Extract shared logic to a dedicated module that both can
reference (DRY + contract coupling)
→ Or: Accept duplication and explicitly document the coupling
(if volatility is lower than it appears)
6.4 見つかった良いパターン
✅ [ModuleX] uses dedicated integration DTOs — contract coupling well implemented
✅ [ServiceY] exposes only necessary data via API — minimizes model coupling
✅ [PackageZ] encapsulates its internal model well — low implementation leakage
6.5 優先順位を付けた推奨事項
優先度:高(影響が大きく、進化を妨げるもの):
- ...
優先度:中(アーキテクチャの健全性を向上させるもの):2. ...
優先度:低(段階的な改善):3. ...
クイックリファレンス:パターン → 統合の強さ
| 見つかったパターン | 統合の強さ | 対応 |
|---|---|---|
| リフレクションによる非公開メンバーへのアクセス | 侵入的 | 至急リファクタリングする |
| 別のサービスの DB を読み取る | 侵入的 | 至急リファクタリングする |
| ビジネスロジックの重複 | 機能的(対称) | 共有モジュールに抽出する |
| 分散トランザクション/Saga | 機能的(トランザクション型) | 凝集度を高めるほうがよいか評価する |
| 実行順序の必須化 | 機能的(逐次型) | プロトコルを文書化するか、カプセル化する |
| リッチなドメインオブジェクトを返す | モデル結合 | 統合 DTO を作成する |
| 内部 enum を外部と共有する | モデル結合 | 公開契約用の enum を作成する |
| ユースケース固有の DTO | 契約結合 | ✅ 正しいパターン |
| バージョン管理された公開インターフェイス/プロトコル | 契約結合 | ✅ 正しいパターン |
| アンチコラプション層 | 契約結合 | ✅ 正しいパターン |
クイックヒューリスティクス
統合の強さを評価するには:
- 「モジュール X の内部の詳細を変更した場合、ほかにいくつのモジュールを変更する必要がありますか?」
- 「統合の契約は公開を前提に設計されていますか? それとも偶然そうなっているだけですか?」
- 「手動で同期する必要がある、重複したビジネスロジックはありますか?」
距離を評価するには:
- 「両方のモジュールに影響する変更を行うには、どれくらいのコストがかかりますか?」
- 「これらのモジュールを保守するチームは、デプロイの調整が必要ですか?」
- 「一方のモジュールが失敗すると、もう一方も動作しなくなりますか?」
変動性を評価するには:
- 「このモジュールは、競争上の優位性となるビジネス上の強みをカプセル化していますか?」
- 「ビジネスチームは、この領域の変更を頻繁に依頼しますか?」
- 「この領域で、これまでに多くのリファクタリングが行われていますか?」
バランスを評価するには:
- 「一緒に変更する必要があるコンポーネントは、コード内でも一緒に配置されていますか?」
- 「独立したコンポーネントは適切に分離されていますか?」
- 「変動性が高く、かつ距離のあるコンポーネントと強く結合している箇所はどこですか?」(→これが主な問題です)
既知の制限
- 変動性の推定には、静的解析だけでなく、実際の Git データを使うのが最適です
- 対称的な機能結合を把握するには、コードを意味的に読み解く必要があります。静的解析ツールでは、一般に検出できません
- 組織上の距離(異なるチーム間の距離)の把握には、ユーザーからの情報が必要です
- 動的なコンナセンス(タイミング、値、同一性)は、実行時の観察なしに検出するのが困難です
- 分析は出発点です。結論は常に、ビジネスの背景を踏まえて精緻化されます
書籍の参考文献
これらの概念は、Vlad Khononov 著 Balancing Coupling in Software Design(Addison-Wesley)に基づいています。