結合度とは?
疎結合・密結合との違いとAI時代の見方を図とコードで解説!

公開日:
最終更新日:

結合度(Coupling)とは、モジュールやクラス同士がどれだけ強く依存しているかを表す指標です。結合度が高いほど(密結合なほど)、1か所の変更が別の場所へ波及しやすくなります。

特にAIで実装や改修を進める今は、境界があいまいなコードほど「ここだけ直して」のつもりが、関係ない部分まで巻き込んで壊しやすくなります。結合度は、その危険を見抜くための大事な診断軸です。

このページでは、結合度の意味、疎結合・密結合の違い、影響範囲の見方、改善の方向性までを、図とコードでやさしく解説します!

1. 結合度とは?まずは意味をやさしく整理

結合度とは、モジュールやクラスどうしが、どれくらい強く依存しているかを見る指標です。高いほど変更の影響が広がりやすく、低いほど境界を保ったまま直しやすくなります。

簡易まとめ

  • 密結合:実装にベッタリ依存 → 1か所の修正が別の場所へ波及しやすい
  • 疎結合:契約(インターフェース)に依存 → 変更範囲を局所化しやすい
  • 理想:高凝集・低結合 → 内部はまとまり、外部とは必要最小限につながる
  • AI時代:境界が曖昧だと「ここだけ直して」のつもりが、関係ない場所まで巻き込みやすい

つまり結合度は、コードの良し悪しをふんわり語る言葉ではなく、「この修正はどこまで波及しそうか」を診断するための軸です。

AIで実装や改修を進める今は、この視点が特に大切です。境界があいまいなコードに対して修正を頼むと、AIは関連する別の処理まで触りやすくなり、意図しない変更や手戻りが増えやすくなります。

実際にAIで修正を試してみると、うまく直るケースより、別の処理まで巻き込んで崩れるケースのほうが怖いと感じます。原因を追うと、部品同士が深く結びついていて、どこまでが修正対象かをAIにも人間にも切り分けにくいことが多いです。

このあと本文では、結合度の意味、疎結合・密結合との違い、AI時代に事故が起きやすい依存パターン、改善の方向性までを、図とコードでやさしく整理していきます。

結合度は、変更の影響範囲を診断するための視点です。具体的な改善の方向性は、疎結合のページもあわせて見ると理解しやすくなります。

2. 結合度と疎結合・密結合の違い

結合度は「依存の強さ」を見る指標で、疎結合と密結合はその状態を分かりやすく表した言葉です。まずは比較表で全体像をつかむと、違いが整理しやすくなります。

疎結合と密結合の違い(結論:実装ではなく「契約」に依存する度合いです)
観点 密結合 疎結合
依存しているもの 相手の実装の詳細(内部構造・具体クラス) 契約(インターフェース/入出力の約束)
変更の影響 変更が連鎖しやすい(思わぬ場所が壊れる) 影響を局所化しやすい(直す場所を絞れる)
差し替え 差し替えにくい(修正が広がりがち) 差し替えやすい(実装を入れ替えやすい)
テスト 単体テストしにくい(モックしづらい) 単体テストしやすい(モック/スタブが作りやすい)
AI時代の修正依頼 境界が曖昧で、AIも影響範囲を見積もれない → 手戻り増 境界が明確で、「ここだけ直して」が通りやすい

現場では、「この2つ、ちょっと密結合すぎない?」といった会話で使われることが多いです。ポイントは、つながりがあるかどうかではなく、そのつながりが変更時にどこまで波及するかです。つまり結合度は、「どこまで影響が広がりそうか」を見る診断軸として使えます。

補足として、もう少し噛み砕くと次のように捉えると分かりやすいです。

結合度は「依存の強さ」を表す指標

結合度そのものは「状態の名前」ではなく、依存の強さを測るものさしです。 どこがどこに、どの深さまで依存しているかを見ることで、変更の危険度を判断しやすくなります。

疎結合は「依存が弱い状態」、密結合は「依存が強い状態」

疎結合と密結合は、結合度という指標で見たときの状態の違いです。 密結合は相手の内部実装や共有状態まで前提にしやすく、疎結合は契約や入出力の約束に依存を寄せます。

結合度は「密結合 ↔ 疎結合」の連続体で考える

実際の設計は0か100かではありません。結合度は連続体なので、 「依存があるから全部悪い」ではなく、どこまで波及する依存かを見るのが大事です。

※このページでは、一般的な「6つの結合度」の暗記よりも、 AI時代に重要な「密結合 ↔ 疎結合の判断軸」に絞って整理しています。 疎結合という改善の考え方は 疎結合のページ も参照してください。

3. 結合度が高いと何が起きる?AI時代に起こりやすい事故

AIは局所的には正しそうな修正を返すのが得意ですが、境界が曖昧なコードでは影響範囲の見落としが起きやすくなります。 そのため密結合な構造に対して「ここだけ直して」と頼むと、別の場所まで巻き込んで壊しやすくなります。

  • 共通結合(グローバル変数)
    局所修正のつもりで値を更新しても、離れた機能の振る舞いまで変わりやすいです。
  • 内容結合(内部構造への直接アクセス)
    見えていない内部前提に触るため、1か所の変更が連鎖的な破綻につながりやすいです。
  • プロンプトの肥大化
    密結合だと、1つの機能を直すために「関係する10個のクラス」をすべてAIに読み込ませるみたいな事態に陥りやすいです。
  • ハルシネーションや誤修正の誘発
    依存関係が複雑すぎると、AIも影響範囲を正しく読み取りにくくなります。その結果、修正後に別の場所が動かなくなるコードや、前提の違う変更案を平気で出してくることがあります。

逆に、引数と返り値でつながるデータ結合寄りの設計は、AIにも人間にも「どこまで触ってよいか」が伝わりやすくなります。 つまり 結合度を下げることは、影響範囲を限定し、改修の安全性を上げることです。

4. 図解で見る高結合度(密結合)と低結合度(疎結合)の違い

図では、依存の置き方しだいで「どこまで巻き込まれるか」がどう変わるかを見ています。 図だけで閉じずに言い換えると、高結合度は境界の外まで前提を共有している状態、低結合度は契約だけを共有している状態です。

高結合度:境界が曖昧で副作用が広がる状態

共有状態・内部アクセス・フラグ制御が混ざると、修正点は1つでも前提が広く散っているため、副作用が別モジュールへ飛びやすくなります。

モジュールA

Bの内部とグローバル状態を前提に呼び出す。

共通結合(グローバル) 制御結合(フラグ) 内容結合(内部参照)
モジュールB

内部変更がA側の破壊につながりやすい。

この図のポイントは、AとBが「何を渡すか」ではなく「相手の中身をどう使うか」でつながっていることです。 そのぶん、局所修正でも影響範囲を説明しにくくなります。

低結合度(疎結合):境界が明確で安全に変更できる状態

契約と必要最小限のデータだけを共有すると、モジュール内部を変えても外へ波及しにくくなります。

モジュールA

契約に沿って必要データだけ渡す。

契約(IF) データ結合 影響範囲が明確
モジュールB

内部を変更しても契約が同じならAは維持される。

ここでは「どこを変えてもよいか」が境界で区切られています。 図で見ると単純ですが、実務ではこの明確さがレビュー・テスト・AI改修の安全性に効きます。

5. コードで見る代表的な結合パターン

結合度は抽象概念に見えますが、コードでは「何に依存しているか」でかなり具体的に見分けられます。 危険な結合ほど、AIも人間も境界を誤解しやすくなります。

共通結合(グローバル):影響範囲が読みにくい

共有状態は便利に見えても、どこが値を書き換えるかを追いにくく、1回の修正で別機能の結果まで変わりやすい結合です。

// 擬似コード(JS/TS風)
globalState.discountRate = 0.2;

function calcOrderTotal(order) {
	// 別ファイルで変更された globalState に依存
	return order.subtotal * (1 - globalState.discountRate);
}

function updateCampaign() {
	// AIがこの修正を入れると、他機能の計算が一斉に変わる恐れ
	globalState.discountRate = 0.35;
}

内容結合(内部構造への直接アクセス):境界違反が起きやすい

相手の内部構造を知っている前提なので、外から見える契約ではなく実装詳細に依存しています。 こうしたコードは、AIが内部まで触る提案を混ぜやすい箇所でもあります。

// 擬似コード(JS/TS風)
class UserRepo {
	_internalCache = new Map();
}

const repo = new UserRepo();

function patchUserName(id, name) {
	// 内容結合: 本来非公開の内部へ直接アクセス
	repo._internalCache.get(id).name = name;
}

データ結合(引数・返り値):AIでも境界を守りやすい

やり取りが引数と返り値に閉じていると、何を受け取り何を返すかが明確です。 そのぶん修正範囲も限定しやすく、テストもしやすくなります。

// 擬似コード(JS/TS風)
type PromptRequest = { prompt: string };
type PromptResponse = { text: string };

function askAi(req: PromptRequest): PromptResponse {
	// 実装詳細はここに閉じ込める
	return { text: "..." };
}

function summarizeArticle(articleText: string) {
	const res = askAi({ prompt: articleText });
	return res.text;
}

6. AI時代の改修で、結合度はどこを見る?安全に進める3つの視点

影響範囲を限定してAI生成を安全にする

境界が明確なほど、AIは「どこまで触ってよいか」を判断しやすくなります。 データ結合寄りにすると、無関係な場所への副作用を減らし、レビューとテストの焦点も合わせやすくなります。

AIモデルや外部サービスは差し替え前提でつなぐ

GPT-4o、Claude、Geminiのように主役モデルは入れ替わります。 呼び出しコードを各所にベタ書きすると、差し替え時の修正範囲が拡大します。 「AIへの窓口」を1つに寄せ、入出力をシンプルな契約に絞ると、心臓部だけを交換しやすくなります。

App/UseCase
   |
   v
AiGateway (唯一の窓口)
   |
   +--> OpenAI Provider
   +--> Claude Provider
   +--> Gemini Provider

自動リファクタリングに備えて境界を明確にする

将来、AIエージェントが自動で置換・分割・移動を行うほど、低結合な構造の価値が上がります。 低結合は独立性を判定しやすく、密結合はスパゲッティ化して解きほぐしが難しくなります。 低結合は、AI自動メンテの恩恵を最大化するための事前準備です。

7. 結合度を下げるには?改善の方向性

依存をインターフェース越しにする

具体クラスや内部実装に直接つなぐのではなく、外から見える契約に依存を寄せると、差し替えや追加をしやすくなります。 特に外部APIやAIモデルのように変わりやすい部分では効果が大きいです。

共有状態や内部参照を減らす

グローバル状態、隠れたフラグ、内部プロパティへの直アクセスは、影響範囲を読みづらくします。 引数・返り値にやり取りを寄せ、内部構造は所有者の内側に閉じ込めるだけでも結合度は下げやすくなります。

変更しやすさ・テストしやすさで見直す

改善の目安は「抽象化したかどうか」ではなく、「この修正の影響範囲を説明できるか」「単体で試せるか」です。 人間にもAIにも説明しやすい境界になっているなら、その設計はかなり良い方向へ進んでいます。

8. 実際に見直して感じた結合度レビューの迷いどころ

最初は「依存がある = 全部悪い」と見がちですが、実際に効いたのは依存の有無より どこまで影響が波及するかを見ることでした。

AIに修正を任せると、内部構造へ触りに行くコードや、共有状態を前提にした修正が混ざりやすい場面があります。 そこで人間が本当に見るべきポイントは、「境界をまたいで何に触っているか」です。

結合度レビューは、依存をゼロにする作業ではなく、危ない依存を見つけて波及範囲を狭める作業だと捉えると判断しやすくなります。

もちもちみかんの体験談

実際に迷いやすかったのは、DRY(Don't Repeat Yourself)のつもりで進めた共通部品の汎用化です。昔は「似た処理を1つにまとめれば保守しやすい」と考えていましたが、使い回す場面が増えるたびに条件分岐や例外対応が増え、気づけば呼び出し元ごとの事情を大量に抱え込んだ部品になっていました。

1か所を直したつもりでも、別画面や別機能の挙動まで変わることがあり、振り返ると、共通化できていたのではなく、複数の前提を1つの実装に押し込めて結合度を上げていた状態だったのだと思います。

それ以降は、「重複しているからまとめる」ではなく、「本当に同じ責務か」「変更は同じ方向に起きるか」を先に見るようになりました。共通化そのものが悪いのではなく、呼び出し側の事情まで抱え込む設計になると、AIにも人間にも影響範囲が読みにくくなります。結合度を意識するようになってからは、条件分岐を増やして延命するより、責務ごとに分け直したほうが安全に直せる場面が多いと感じています。

教訓:
修正する理由が異なるものは、たとえコードが似ていても「あえて分ける」勇気が、低い結合度(=保守性の高さ)を守る秘訣です。

FAQ:結合度でよくある疑問

結合度が低ければ低いほど良いのですか?

いいえ。低ければよいというより、変更しやすさに対してちょうどよい距離感が大切です。 変化の少ない場所まで過剰に抽象化すると、逆に読みにくくなることがあります。

結合度と凝集度の違いは何ですか?

結合度はモジュールどうしの依存の強さ、凝集度は1つのモジュール内部がどれだけ自然にまとまっているかです。 外との依存は弱く、中の責務はまとまっている状態が理想です。

疎結合にすれば設計は必ず良くなりますか?

必ずではありません。疎結合は有効な改善方向ですが、やりすぎると抽象化が増えて追いにくくなります。 差し替えや変更が起きやすい境界を優先して整えるのが現実的です。

まとめ:結合度は「変更の危険度」を見る診断軸

結合度は、依存の有無ではなく、変更がどこまで波及するかを見るための指標です。 結合度を診断することは、変更の危険度を見積もり、AI時代の改修を安全にすることにつながります。

まずは「相手の内部まで前提にしていないか」「影響範囲を説明できるか」を確認し、 危ない依存から順に疎結合へ寄せていきましょう。

おまけ:設計レビュー用チェックリスト(AI時代編)

  • [ ] グローバルな状態(共通結合)に頼っていないか?

    「どこからでも書き換えられる変数」を使っていると、AIも人間もデバッグで迷子になります。

  • [ ] 相手の「中身」に詳しすぎないか?(内容結合)

    他のモジュールの内部変数やプライベートな処理に直接触っていないかチェック。窓口(メソッド)だけを通しましょう。

  • [ ] やり取りは「引数と返り値」で完結しているか?(データ結合)

    必要なデータだけを渡し、結果を受け取る。このシンプルさが最強の疎結合です。

  • [ ] AIへの「窓口」が散らばっていないか?

    プロンプトやAI呼び出しのロジックがあちこちに散らばると、モデル変更時の修正箇所が一気に増えます。「AI担当」の部品を1つにまとめましょう。

  • [ ] 変更時の影響を「一言」で説明できるか?

    「ここを直すと、あっちの画面にも影響が出るかも…」と不安になるなら、それは結合度が高すぎるサインです。

おみやげ:結合度チェック用AIプロンプト

以下のコードの「結合度」を診断してください。特に次の観点でレビューしてください。

1. 依存の強さ
このクラス/関数を修正したとき、想定外の場所(他のモジュール)に影響が出るリスクはありますか?
また、その依存は「契約(インターフェース/入出力)」に対するものですか?それとも「実装の詳細」に対するものですか?

2. 単体テストのしやすさ
外部データベースや他クラスを大量に準備しなくても、このコードを単体でテストできますか?
テストしづらい場合、どの依存が原因ですか?

3. 改善案
もし「密結合」になっている部分があれば、インターフェースの導入、依存性の注入(DI)、責務の分割などを使って、どう疎結合に寄せられるか提案してください。

4. 出力形式
- 結合度が高い箇所
- 影響範囲が広がりそうな理由
- テストしづらい理由
- 疎結合に寄せる改善案
を箇条書きで整理してください。

コード:
[ここにコードを貼る]

このサイトの運営者

もちもちみかん(社内SE)

運営者は、グループ企業向けの業務アプリを要件定義から運用まで担当している社内SEです。PHP・JavaScript・MySQL・CSSを使った実務経験をもとに、一次情報や実際の運用で得た気づきを整理しています。

AIにコードを書かせて終わりではなく、どこで迷ったか・どこを人がレビューすべきかまで含めて、 やさしく噛みくだいてまとめています。

経験:Webアプリ・業務システム

得意:PHP・JavaScript・MySQL・CSS

制作・運用中:フォーム生成基盤クイズ学習プラットフォームhtmx逆引きレシピ

AI時代のエンジニアタイプ診断:CSPF/とろとろみかん

詳しいプロフィールはこちら!  もちもちみかんのプロフィール

もちもちみかん0系くん
TOPへ

もちもちみかん.comとは


もちもちみかん.com は、AI時代に必要なプログラミングの基礎・設計・改善の考え方を、やさしく学べるサイトです。


『プリンシプル オブ プログラミング』の原則まとめ、用語集、クイズ、htmx逆引きレシピを通じて、「分かったつもり」で終わらず、実際に使える判断軸まで身につくようにしています。


フォームジェネレーターなどの便利ツールも用意しつつ、AIにコードを書かせる時代にこそ大切な設計・責務・レビューの視点を、実務と検証の目線で届けます。


むずかしい内容でも親しみやすく学べるように、「もちもちみかん」らしいやわらかさも大切にしています!