結合度とは?

公開日:
最終更新日:

イントロダクション:結合度を一言で言うと? 🔗

結合度(Coupling)とは、 「モジュール同士がどれくらい強く依存し合っているか」 を表す指標です。

ここでの「モジュール」は、クラス・関数・ファイル・パッケージなど 「ひとまとまりの単位」 だとイメージしてください。

あるモジュールを変えたときに、 他のモジュールまで次々と直さないといけない状態が「結合度が高い」 と言い、 影響を受ける範囲が小さく済む状態を 結合度が低い」 と言います。 設計の世界では、 「高凝集・低結合」 が理想とされます。

1. なぜ「結合度」が大事なの? 🧯

モジュール間の結合度が高いと、次のような「現場あるある」が起きやすくなります。

  • ちょっとした修正が連鎖する
    Aモジュールを直したら、BもCも動かなくなり、あちこちを連鎖的に修正する羽目になる。
  • 影響範囲が読みにくい
    「この変更はどこまで影響するのか?」が分かりづらく、 レビューやテストの工数が膨らむ。
  • 置き換え・再利用がしにくい
    別の実装に差し替えたいだけなのに、細かい前提条件までベッタリ結びついていて、 差し替えが大工事になってしまう。

逆に、結合度が低い設計では、 「ここを変えたら、主にここだけが影響を受ける」 と考えやすくなり、 変更やリファクタリングがかなり楽になります。 疎結合アーキテクチャを目指すうえで欠かせない観点です。

2. 結合度のレベル(強い → 弱い)

結合度にも、いくつかの段階があります。 ここでは、クイズで使っているレベル分けに沿って、 レベル1(最悪)からレベル6(望ましい) までを整理します。

レベル1:内容結合(最悪)

他モジュールの内部に直接アクセスしたり書き換えたりする状態(最悪) です。 片方を直すともう片方も壊れやすく、 モジュールの「中身」にべったり依存しているため、変更に極端に弱くなります。

レベル2:共通結合

グローバル変数(どこからでも見える変数)を一緒に使っている状態 です。 どのモジュールがいつ値を変えたのか追いにくく、 予期しない副作用の温床になりやすい結合です。

レベル3:外部結合

外部宣言(publicな変数・関数など)を共有している状態 です。 インターフェースは表向きに見えているものの、 まだ結びつきは強く、 「相手の公開メンバーの細かい都合」に引きずられやすい段階です。

レベル4:制御結合

フラグ(0/1などの切り替え変数)で相手の振る舞いを細かく指示している状態 です。 「このフラグが1の時はこう動いて、0の時はこう動く」といった前提で組んでいるため、 相手モジュールの中身をよく知っている必要があり、結局べったりな関係になりがちです。

レベル5:スタンプ結合

構造体やクラスなどの複合データを丸ごと渡してしまう状態 です。 呼び出し側はそのうちの一部の項目しか使わないのに、 実際には使わない項目まで含まれてしまっています。 「何を本当に必要としているのか」が曖昧な結合です。

レベル6:データ結合(望ましい)

本当に必要な単体の値(スカラ値)だけを引数として渡す状態 です。 モジュール間でやり取りする情報が最小限でハッキリしており、 もっとも望ましい結合度とされています。

実務では、常にデータ結合だけにできるわけではありませんが、 「内容結合や共通結合は避ける」「スタンプ結合を減らし、できるだけデータ結合に寄せる」 といった意識が設計の質を大きく左右します。

3. 結合度を下げる(疎結合に近づける)ための考え方 🪄

結合度を下げるポイントは、 「相手モジュールの中身・事情をできるだけ知らなくて済むようにする」 ことです。

  • インターフェースでやり取りする
    クラスや関数の「中身」ではなく、 「こう呼べば、こう振る舞う」 という外側の契約(インターフェース)を決めて、その経由でやり取りするようにします。
  • 本当に必要なデータだけ渡す
    「とりあえず全部渡しておく」ではなく、 「この処理に必要な値」だけ を引数にすることで、スタンプ結合をデータ結合に近づけます。
  • フラグで振る舞いを細かく指示しすぎない
    「このフラグが0の時はこっち、1の時はあっち」のような制御結合が増えてきたら、 ポリモーフィズムや戦略パターン などを検討し、 「相手に任せる設計」に変えられないか考えます。
  • 依存の向きを統一する(DI / DIP)
    具象クラスに直接依存せず、 抽象(インターフェースや抽象クラス) に依存するように設計すると、 実装の差し替えがしやすくなり、結合度も下げやすくなります。

図解で見る「高結合度」と「低結合度(疎結合)」

モジュール同士が「グローバル変数や内部実装にベッタリ依存している状態(高結合)」と、 「インターフェースと最小限のデータだけでゆるくつながっている状態(低結合)」をイメージできる図解です。

高結合度:相手の中身や共通状態にベッタリ依存している例

モジュール同士が同じグローバル変数を共有し、 フラグで細かく振る舞いを指示し合い、 相手の内部実装まで前提にしているイメージです。 1つを変えると他も連鎖的に壊れやすくなります。

モジュールA

Bの内部フィールドを書き換えたり、 debugフラグを直接切り替えたりしている。

共通グローバル変数 フラグで細かく指示 内部フィールドへの直接アクセス
モジュールB

外から直接いじられてしまう前提で作られており、 内部構造を変えにくい。

「相手の事情をよく知っていないと動かない関係」 になっていて、変更のたびに双方の調整が必要になるイメージです。

低結合度(疎結合):契約と最小限のデータだけでつながる例

モジュール同士が「こう呼べば、こう返す」というインターフェースだけを共有し、 本当に必要なデータだけを受け渡しするイメージです。 内部実装はお互いに知らなくてもよくなります。

モジュールA(データ取得)

ユーザー情報を取得し、インターフェースが約束する形 (例:id と displayName)で返すだけを担当する。

インターフェース / 契約 最小限のデータ id・名前など明示的な引数
モジュールB(表示)

渡されたデータをどう表示するかだけに集中し、 「どこから来たデータか」や「内部の保存形式」は気にしない。

「相手の中身を知らなくても使える関係」 になっているため、片方を差し替えたり、内部実装を変えたりしても、 インターフェースさえ守れば影響を最小限にできます。

JavaScriptで見る「強い結合」と「弱い結合(疎結合)」の例

ユーザー一覧の表示を題材に、「グローバル状態や内部実装にベッタリ依存した強い結合」と、 「インターフェース越しに最小限のデータだけやり取りする疎結合」の違いを示すコード例です。※コードのコメントを読むだけでも理解できるかと思います。

強い結合の例:相手モジュールの中身とグローバル状態に依存

グローバル状態(共通結合)とビューの内部フィールド(内容結合)を直接書き換え、 フラグで振る舞いを細かく指示する(制御結合)など、結合度が高い例です。

// 強い結合の例:モジュールAがモジュールBの中身やグローバル状態に依存している

// 共通結合:複数モジュールから直接触れるグローバル状態
const appState = {
	users: [
		{ id: 1, name: 'Alice', role: 'admin' },
		{ id: 2, name: 'Bob', role: 'member' }
	],
	debugMode: true
};

// モジュールB:ユーザーリストを表示するビュー
const userListView = {
	elementId: 'highCouplingList',
	// 本来は外から触られたくない内部情報
	_internalTemplate: '<li>{id}: {name} ({role})</li>',

	render(users, showIdFlag, showRoleFlag) {
		const ul = document.getElementById(this.elementId);
		ul.innerHTML = '';

		// グローバル状態に依存
		if (appState.debugMode) {
			ul.style.border = '1px dashed red';
		}

		users.forEach(user => {
			let label = user.name;

			// 制御結合:フラグで細かく振る舞いを指示
			if (showIdFlag) {
				label = user.id + ': ' + label;
			}
			if (showRoleFlag) {
				label += ' (' + user.role + ')';
			}

			const li = document.createElement('li');
			li.textContent = label;
			ul.appendChild(li);
		});
	}
};

// モジュールA:ビューの内部事情まで知っているコントローラ
function showUsersHighCoupling() {
	// 内容結合:ビューの内部フィールドを書き換えている
	userListView.elementId = 'highCouplingList';
	userListView._internalTemplate = '[DEBUG] {id}: {name}';

	// グローバル状態もここで直接変更
	appState.debugMode = document.getElementById('debugFlag').checked;

	const showIdFlag = true;
	const showRoleFlag = document.getElementById('showRoleFlag').checked;

	// users 配列をそのまま渡していて、「何が必要なのか」が曖昧(スタンプ結合寄り)
	userListView.render(appState.users, showIdFlag, showRoleFlag);
}

弱い結合(疎結合)の例:契約と最小限のデータだけでやり取り

「ユーザー情報をどう取得するか」と「どう表示するか」を分け、 必要な情報だけを引数で渡すことで、モジュール間の結合をゆるくした例です。

// 弱い結合(疎結合)の例:モジュール間のやり取りを「契約」と最小限のデータに絞る

// データ取得モジュール:公開関数の戻り値が契約になる
function loadUserSummaries() {
	const users = [
		{ id: 1, name: 'Alice', role: 'admin' },
		{ id: 2, name: 'Bob', role: 'member' }
	];

	// ビューに本当に必要な情報だけを渡す形に変換しておく
	return users.map(user => ({
		id: user.id,
		displayName: user.name
	}));
}

// 表示モジュール:必要な情報だけを引数でもらう
function renderUserList(element, summaries, options) {
	element.innerHTML = '';

	summaries.forEach(summary => {
		const li = document.createElement('li');
		li.textContent = options.showId
			? summary.id + ': ' + summary.displayName
			: summary.displayName;
		element.appendChild(li);
	});
}

// UI をつなぐ薄い層:依存の向きをまとめる
function showUsersLowCoupling() {

	const ul = document.getElementById('lowCouplingList');
	const showId = document.getElementById('showIdFlagLow').checked;

	// データ取得 ※中身(どこから取っているか)はここでは気にしない
	const summaries = loadUserSummaries();

	// 表示
	renderUserList(ul, summaries, { showId });

}

まとめ:結合度を「モジュール間のつながり」の物差しにする

  • 結合度は、 モジュール同士がどれくらい強く依存し合っているか を表す指標で、低いほど疎結合な設計に近づきます。
  • 内容結合・共通結合のような強い結合は避け、 できるだけデータ結合に寄せていく ことが、変更に強いコードへの第一歩です。
  • 「相手の中身を知らなくても使えるか?」 を基準に設計を見直すと、 インターフェース設計・依存関係・引数の取り方などが自然と整理されていきます。
  • 凝集度と合わせて、 「高凝集・低結合」 をモジュール設計のゴールラインとして意識することで、 長く保守しやすいシステムに近づけます。

まずは、 「このモジュール同士、本当にここまでくっついている必要がある?」 と問いかけるところから、 結合度の感覚を育てていきましょう。

このページの著者

もちもちみかん(システムエンジニア)

社内SEとしてグループ企業向けの業務アプリを要件定義〜運用まで一気通貫で担当しています。

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

得意:PHP・JavaScript・MySQL・CSS

個人実績:フォーム生成基盤クイズ学習プラットフォーム

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

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

もちもちみかん.comとは


このサイトでは、コーディングがめんどうくさい人向けのお助けツールとして、フォームやCSSをノーコードで生成できる、
 もちもちみかん.forms
 もちもちみかん.css1
 もちもちみかん.css2
と言ったジェネレーターを用意してます。

また、このサイトを通じて、「もちもちみかん」のかわいさを普及したいとかんがえてます!