『ソフトウェア設計の結合バランス』解説:疎結合至上主義を超えた新しい設計原則
この記事はAIによって生成されています。内容の正確性は保証されず、記事の利用による損害について一切の責任を負いません。この記事を読み進めることで、利用規約に同意したものとみなされます。
- 想定読者: ソフトウェアエンジニア、アーキテクト、技術リード
- 前提知識: オブジェクト指向プログラミング、基本的なソフトウェア設計概念
- 所要時間: 25分
概要
「高凝集・疎結合」は、ソフトウェア設計の黄金律として50年以上にわたり語り継がれてきました。しかし、マイクロサービス、分散システム、クラウドネイティブアーキテクチャが主流となった現代において、このスローガンだけでは適切な設計判断ができない場面が増えています。
Vlad Khononovの『Balancing Coupling in Software Design』1(2024年出版、邦訳:『ソフトウェア設計の結合バランス 持続可能な成長を支えるモジュール化の原則』2、2025年10月出版)は、従来の「疎結合至上主義」を超えた新しいアプローチ、結合のバランス化(Balancing Coupling)を提案しています。
本記事では、この書籍の核心概念を解説し、以下のトピックを扱います:
- 従来の結合・凝集概念の歴史と限界
- 結合の3次元(強度・距離・変動性)
- Connascence(コナーセンス):結合度の精緻な尺度
- Cynefin(クネビン)理論と複雑性の理解
- 結合バランスモデルの実践的適用
注記:
本記事は、Vlad Khononovの書籍『Balancing Coupling in Software Design』の全文を読んだ書評ではなく、公式サイト(coupling.dev)、書評、技術コミュニティの解説、著者インタビュー等の公開情報から、結合バランスの核心概念(結合の3次元、Connascence、Cynefin理論)を調査し、体系的に解説したものです。書籍の詳細なニュアンスや著者の意図を完全に反映できていない可能性があります。
また、本記事に掲載されているコード例は、説明のための例示であり、実際に実行して動作を検証したものではありません。実際のプロジェクトで使用する際は、適切なテストと検証を行ってください。
なぜ今「結合バランス」が重要なのか
「疎結合」スローガンの限界
「疎結合・高凝集」というスローガンは、1974年にStevens、Myers、Constantineが発表した論文『Structured Design』3で初めて提唱されました。50年以上経った今も、この原則は広く支持されています。
しかし、現代のソフトウェア開発では、このスローガンだけでは解決できない問題が顕在化しています:
1. マイクロサービスのジレンマ
マイクロサービスアーキテクチャは、サービス間の結合を減らすことを目的としていますが、過度な分割は以下の問題を引き起こします:
- ネットワークレイテンシの増加
- 分散トランザクションの複雑性
- デバッグとモニタリングの困難さ
- 運用コストの増大
2. 抽象化のコスト
完全な疎結合を目指すと、過度な抽象化レイヤーが生まれます:
- 理解困難な多層アーキテクチャ
- 不必要なインダイレクション
- パフォーマンスのオーバーヘッド
3. 変更コストの見誤り
すべての結合が等しく悪いわけではありません。変更頻度が低い安定したコンポーネントへの結合は、むしろコストが低い場合があります。
Khononovの提案:結合をツールとして使う
Khononovは、結合を「避けるべき悪」ではなく、「管理すべきツール」として再定義します14:
「結合はソフトウェアシステムを複雑性に向かわせることもあれば、モジュール性に向かわせることもできる」
重要なのは、ゼロ結合を目指すことではなく、状況に応じた適切なバランスを取ることです。
従来の結合・凝集の概念と限界
Structured Design(1974):結合と凝集の誕生
Stevens、Myers、Constantineの論文3は、以下の概念を導入しました:
結合(Coupling)の主要な種類(弱い→強い):
- データ結合(Data Coupling):単純なデータ型を引数として渡す
- スタンプ結合(Stamp Coupling):構造体を渡すが、一部のフィールドのみ使用
- 制御結合(Control Coupling):制御情報を渡して振る舞いを制御
- 共通結合(Common Coupling):グローバル変数への依存
- 内容結合(Content Coupling):他モジュールの内部実装に直接依存
凝集(Cohesion)のレベル(低い→高い):
- 偶発的凝集(Coincidental Cohesion):無関係な機能の寄せ集め
- 論理的凝集(Logical Cohesion):似た機能を一箇所に集約
- 時間的凝集(Temporal Cohesion):同時に実行される機能
- 手続き的凝集(Procedural Cohesion):特定の順序で実行される機能
- 通信的凝集(Communicational Cohesion):同じデータを操作する機能
- 逐次的凝集(Sequential Cohesion):出力が次の入力になる機能
- 機能的凝集(Functional Cohesion):単一の明確な目的を持つ機能
従来の分類の限界
Structured Designの分類は画期的でしたが、以下の限界があります:
1. 定性的で曖昧
「弱い結合」「強い結合」という表現は定性的で、具体的な判断基準が不明確です。
2. 一次元的な評価
結合の強弱だけを評価し、他の重要な側面(距離、変動性など)を考慮していません。
3. 現代的なパターンに対応していない
依存性注入(Dependency Injection)、イベント駆動アーキテクチャ、マイクロサービスといった現代的なパターンを十分に評価できません。
結合の3次元:Khononovの革新的フレームワーク
Khononovは、結合を3つの次元で評価する革新的なフレームワークを提案しています14。
1. 強度(Strength / Integration Strength)
結合の密度や依存性の程度を表します。
評価基準:
- 弱い結合:単純なデータ型(int、string等)のみに依存
- 中程度の結合:構造体やインターフェースに依存
- 強い結合:具体的な実装クラス、グローバル変数、内部実装に依存
例:データベースアクセスの結合強度
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
# 注: 以下は概念を示すための疑似コード例です
# 強い結合:具体的なデータベース実装に直接依存
class OrderService:
def __init__(self):
self.db = MySQLConnection("localhost", "user", "pass")
def create_order(self, order_data):
self.db.execute("INSERT INTO orders ...")
# 弱い結合:抽象化(インターフェース)に依存
class OrderService:
def __init__(self, repository: OrderRepository):
self.repository = repository
def create_order(self, order_data):
self.repository.save(order_data)
2. 距離(Distance / Locality)
モジュール間の物理的・論理的な離隔を表します。
距離のレベル(近い→遠い):
- 同一関数/メソッド内
- 同一クラス内
- 同一パッケージ/モジュール内
- 同一アプリケーション内
- 異なるサービス間(マイクロサービス)
- 異なる組織のシステム間
Khononovの原則4:
「強度が高い結合は距離を縮める」
悪い例:強い結合 × 遠い距離
1
2
3
4
5
6
7
8
9
10
11
12
import requests
# マイクロサービスA(注文サービス)
class OrderService:
def process_order(self, order):
# マイクロサービスBの具体的な実装に依存
user = requests.get(
f"http://user-service/api/users/{order.user_id}"
).json()
# user-serviceの内部データ構造に依存
if user["subscription"]["tier"] == "premium":
discount = 0.2
問題点:
- マイクロサービスB(user-service)の内部データ構造(
subscription.tier)に強く依存 - user-serviceがデータ構造を変更すると、order-serviceが壊れる
改善例:弱い結合 × 遠い距離
1
2
3
4
5
6
7
8
9
import requests
# マイクロサービスA(注文サービス)
class OrderService:
def process_order(self, order):
# 抽象化されたAPIに依存
user_discount = requests.get(
f"http://user-service/api/users/{order.user_id}/discount"
).json()["discount_rate"]
3. 変動性(Volatility)
変更可能性と影響範囲を表します。
変動性のレベル(安定→不安定):
- 標準ライブラリ:変更頻度が極めて低い(例:Python標準ライブラリ、Java SE API)
- サードパーティライブラリ:メジャーバージョン間で安定(例:Django、React)
- 社内共通ライブラリ:プロジェクト間で共有、定期的に更新
- アプリケーション固有のコード:頻繁に変更
- ビジネスルール:市場や規制の変化により頻繁に変更
Khononovの原則4:
「変動性が低いなら強度の高さを許容し得る」
例:変動性を考慮した設計判断
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
# 許容される:標準ライブラリへの強い結合
import json
data = json.loads(json_string) # 標準ライブラリなので変更リスクが低い
# 問題あり:変動性の高いビジネスルールへの強い結合
class DiscountCalculator:
def calculate(self, order):
# ビジネスルールが直接ハードコードされている
if order.total > 10000:
return order.total * 0.1
return 0
# 改善:ビジネスルールを外部化
class DiscountCalculator:
def __init__(self, discount_rules: DiscountRulesRepository):
self.rules = discount_rules
def calculate(self, order):
applicable_rules = self.rules.get_applicable_rules(order)
return self._apply_rules(order, applicable_rules)
結合の3次元評価マトリクス
| 結合タイプ | 強度 | 距離 | 変動性 | 評価 |
|---|---|---|---|---|
| 標準ライブラリへの依存 | 中〜高 | 近い | 極めて低い | ✅ 許容 |
| 同一モジュール内のクラス間依存(抽象化経由) | 低〜中 | 近い | 中 | ✅ 許容 |
| マイクロサービス間の抽象化されたAPI依存 | 低 | 遠い | 中 | ✅ 許容 |
| マイクロサービス間の具体的な実装依存 | 高 | 遠い | 高 | ❌ 問題 |
| 複数モジュールから変動性の高いビジネスロジックへの直接依存 | 高 | 中〜遠い | 高 | ❌ 問題 |
Connascence:結合度の精緻な尺度
Connascenceとは
Connascence(コナーセンス)は、Meilir Page-Jonesが1992年に提唱した概念5で、Khononovの書籍でも第6章で詳しく解説されています6。
定義5:
2つのソフトウェア要素AとBの間にコナーセンスが存在するとは、Aに対する変更がBの変更(または慎重なチェック)を要求する場合、またはAとBの両方を同時に変更する必要がある場合を指す。
Connascenceは、結合と凝集を統一的に評価する指標として、Structured Designの概念を現代的に再構築したものです7。
Connascenceの3次元
Connascence自体も3つの次元で評価されます6:
- 強度(Strength):変更の難しさとコスト
- 度合い(Degree):結合の数(何個の要素が依存しているか)
- 距離(Locality):関連要素間の近さ
Connascenceの種類(弱い→強い)
静的コナーセンス(Static Connascence)
ソースコードレベルで検出可能なコナーセンス。
1. 名前のコナーセンス(Connascence of Name, CoN)
同じ名前を参照する必要がある。
1
2
3
4
5
6
# 関数名のコナーセンス
def calculate_total(items):
return sum(item.price for item in items)
# この関数を呼び出す側は、名前 "calculate_total" に依存
result = calculate_total(my_items)
最も弱いコナーセンスで、リファクタリングツールで容易に変更可能。
2. 型のコナーセンス(Connascence of Type, CoT)
同じ型を使用する必要がある。
1
2
3
def process_order(order: Order) -> OrderResult:
# OrderとOrderResult型に依存
...
静的型付け言語では型チェッカーが検出。
3. 意味のコナーセンス(Connascence of Meaning, CoM)
特定の値が特定の意味を持つ(マジックナンバー、マジックストリング)。
1
2
3
4
5
6
7
# 悪い例:意味のコナーセンス
if user.status == 1:
send_email(user)
# 改善:名前のコナーセンスへ
if user.status == UserStatus.ACTIVE:
send_email(user)
4. 位置のコナーセンス(Connascence of Position, CoP)
要素の順序が重要。
1
2
3
4
5
6
7
8
9
10
# 悪い例:位置のコナーセンス
create_user("John", "Doe", 30, "[email protected]")
# 改善:名前のコナーセンスへ
create_user(
first_name="John",
last_name="Doe",
age=30,
email="[email protected]"
)
5. アルゴリズムのコナーセンス(Connascence of Algorithm, CoA)
同じアルゴリズムを使用する必要がある。
1
2
3
# 暗号化と復号化は同じアルゴリズムに依存
encrypted = encrypt(data, algorithm="AES-256")
decrypted = decrypt(encrypted, algorithm="AES-256")
動的コナーセンス(Dynamic Connascence)
実行時にのみ検出可能なコナーセンス。静的コナーセンスよりも強い。
6. 実行のコナーセンス(Connascence of Execution, CoE)
実行順序が重要。
1
2
3
4
5
6
7
8
# 悪い例:実行順序に依存
open_connection()
execute_query()
close_connection()
# 改善:コンテキストマネージャーで順序を保証
with DatabaseConnection() as conn:
conn.execute_query()
7. タイミングのコナーセンス(Connascence of Timing, CoTi)
実行タイミングが重要(競合条件)。
1
2
3
4
5
6
7
8
9
10
# 悪い例:競合条件
balance = account.get_balance()
if balance >= amount:
account.withdraw(amount) # 他のスレッドが同時にwithdrawする可能性
# 改善:トランザクション
with transaction():
balance = account.get_balance(lock=True)
if balance >= amount:
account.withdraw(amount)
8. 値のコナーセンス(Connascence of Value, CoV)
複数の値が特定の関係を維持する必要がある。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
# 悪い例:値の整合性を手動管理
class ShoppingCart:
def __init__(self):
self.items = []
self.total = 0 # itemsとtotalを別々に管理
def add_item(self, item):
self.items.append(item)
self.total += item.price # 手動で同期
# 改善:値を派生させる
class ShoppingCart:
def __init__(self):
self.items = []
@property
def total(self):
return sum(item.price for item in self.items)
9. 同一性のコナーセンス(Connascence of Identity, CoI)
複数の要素が同じオブジェクトインスタンスを参照する必要がある。
1
2
# 同じシングルトンインスタンスへの依存
config = ConfigManager.get_instance()
Connascenceのリファクタリング原則
- 強いコナーセンスを弱いコナーセンスに変換
- 意味のコナーセンス → 名前のコナーセンス
- 位置のコナーセンス → 名前のコナーセンス
- 度合い(Degree)を減らす
- 多くのモジュールが依存している場合、抽象化を導入
- 距離(Locality)を縮める
- 強いコナーセンスは同一モジュール内に留める
Cynefin理論と複雑性の理解
Cynefin(クネビン)フレームワークとは
Khononovの書籍第2章8では、Cynefin(クネビン)フレームワークを用いて複雑性を理解し、適切な設計判断を行う方法が解説されています。
Cynefin(ウェールズ語で「生息地」の意味)は、David J. Snowdenが1990年代終わりに開発した意思決定フレームワークで、問題を4つのドメインに分類します9:
Cynefinの4つのドメイン
1. Simple(単純)領域
特徴:
- 因果関係が明確で予測可能
- ベストプラクティスが存在
- 「感知 → 分類 → 対応」のアプローチ
ソフトウェア設計の例:
- CRUD操作の実装
- 標準的なデータバリデーション
- 確立されたデザインパターンの適用
結合の判断:
- 標準的なパターンに従う
- 既知のベストプラクティスを適用
- 過度な抽象化は不要
2. Complicated(煩雑)領域
特徴:
- 分析すれば因果関係が判明
- 専門知識が必要
- 複数の正解が存在し得る
- 「感知 → 分析 → 対応」のアプローチ
ソフトウェア設計の例:
- パフォーマンス最適化
- セキュリティ実装
- データベーススキーマ設計
結合の判断:
- 専門知識に基づいて3次元(強度・距離・変動性)を評価
- トレードオフを慎重に検討
3. Complex(複雑)領域
特徴:
- 因果関係が複雑で事前に予測不可能
- 探索と実験が必要
- 創発的なソリューション
- 「調査 → 感知 → 対応」のアプローチ
ソフトウェア設計の例:
- 新しいドメインのモデリング
- マイクロサービスの境界決定
- 革新的なアーキテクチャパターン
結合の判断:
- 小さく始めて反復的に改善
- 早期のフィードバックループ
- 過度な前提を置かない
4. Chaotic(混沌)領域
特徴:
- 因果関係が不明確
- 即座の行動が必要
- 「行動 → 感知 → 対応」のアプローチ
ソフトウェア設計の例:
- 本番障害対応
- セキュリティインシデント対応
結合の判断:
- 安定化が最優先
- 後で改善(まずは動くようにする)
Cynefinと結合バランスの関係
Khononovは、Cynefin理論を用いて、システムの複雑性レベルに応じた適切な結合戦略を提案します8:
| ドメイン | 推奨される結合戦略 |
|---|---|
| Simple | 標準パターンに従う、過度な抽象化を避ける |
| Complicated | 3次元評価を慎重に行い、専門知識でバランスを取る |
| Complex | 柔軟性を重視、早期のフィードバックを得やすい設計 |
| Chaotic | まず安定化、後でリファクタリング |
実践例:マイクロサービスの境界決定
マイクロサービスの境界決定はComplex(複雑)領域の問題です:
- 調査:既存のコードベース、ビジネスケイパビリティ、チーム構造を分析
- 感知:小規模な境界で試験的に分割
- 対応:フィードバックに基づいて境界を調整
この過程で、結合の3次元を継続的に評価し、バランスを調整します。
結合バランスモデルの実践
バランス化の基本原則
Khononovは、以下の実践的な判断基準を提示しています4:
許容される結合:
- 強度が低く、変動性が低い
- 例:標準ライブラリへの依存
- 理由:変更リスクが極めて低い
- 強度が高いが、距離が近い
- 例:同一クラス内のメソッド間依存
- 理由:変更の影響範囲が限定的
- 距離が遠いが、強度が低く、変動性が低い
- 例:マイクロサービス間の抽象化されたAPI依存
- 理由:契約が安定している
問題のある結合:
- 強度が高く、距離が遠く、変動性が高い
- 例:マイクロサービス間での具体的な実装への依存
- 理由:変更の影響が広範囲に及ぶ
ケーススタディ:レイヤードアーキテクチャのリファクタリング
典型的な3層アーキテクチャ(Presentation、Business Logic、Data Access)を例に、結合バランスの実践を見ていきます。
問題のある設計:密結合
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
# Presentation層
class OrderController:
def create_order(self, request):
# Business Logic層の具体的なクラスに直接依存
service = OrderService()
# Data Access層の具体的なクラスに直接依存
service.repository = MySQLOrderRepository()
return service.process_order(request.data)
# Business Logic層
class OrderService:
def __init__(self):
# Data Access層の具体的な実装に直接依存
self.repository = MySQLOrderRepository()
self.email_sender = SMTPEmailSender()
def process_order(self, order_data):
order = self.repository.save(order_data)
self.email_sender.send_confirmation(order)
return order
問題点:
- Presentation層がData Access層に直接依存(レイヤー境界違反)
- 具体的な実装クラス(MySQL、SMTP)に強く結合
- テストが困難(実際のデータベースとメールサーバーが必要)
3次元評価:
| 結合 | 強度 | 距離 | 変動性 | 問題 |
|---|---|---|---|---|
| Controller → MySQLOrderRepository | 高 | 遠い | 中 | ❌ |
| OrderService → MySQLOrderRepository | 高 | 中 | 中 | ❌ |
| OrderService → SMTPEmailSender | 高 | 中 | 中 | ❌ |
改善された設計:適切なバランス
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
from abc import ABC, abstractmethod
# Domain層(抽象化)
class OrderRepository(ABC):
@abstractmethod
def save(self, order_data) -> Order:
pass
class EmailSender(ABC):
@abstractmethod
def send_confirmation(self, order: Order):
pass
# Business Logic層
class OrderService:
def __init__(
self,
repository: OrderRepository,
email_sender: EmailSender
):
self.repository = repository
self.email_sender = email_sender
def process_order(self, order_data):
order = self.repository.save(order_data)
self.email_sender.send_confirmation(order)
return order
# Data Access層(具体的な実装)
class MySQLOrderRepository(OrderRepository):
def save(self, order_data) -> Order:
# MySQL固有の実装
...
class SMTPEmailSender(EmailSender):
def send_confirmation(self, order: Order):
# SMTP固有の実装
...
# Presentation層
class OrderController:
def __init__(self, order_service: OrderService):
self.service = order_service
def create_order(self, request):
return self.service.process_order(request.data)
# 依存性注入(DI Container)
def configure_dependencies():
repository = MySQLOrderRepository()
email_sender = SMTPEmailSender()
service = OrderService(repository, email_sender)
controller = OrderController(service)
return controller
改善後の3次元評価:
| 結合 | 強度 | 距離 | 変動性 | 評価 |
|---|---|---|---|---|
| OrderService → OrderRepository(抽象) | 低 | 近い | 低 | ✅ |
| OrderService → EmailSender(抽象) | 低 | 近い | 低 | ✅ |
| Controller → OrderService | 中 | 近い | 中 | ✅ |
メリット:
- レイヤー境界が明確
- 抽象(インターフェース)への依存により強度が低減
- テストが容易(モックやスタブを使用可能)
- データベースやメールサーバーの実装を変更しても、Business Logic層は影響を受けない
ケーススタディ:マイクロサービスの境界決定
ECサイトのモノリシックアプリケーションをマイクロサービス化する際の結合バランス適用例。
シナリオ:
以下のドメイン領域があります:
- 商品管理(Product Catalog)
- 在庫管理(Inventory)
- 注文管理(Order)
- 顧客管理(Customer)
- 決済処理(Payment)
ステップ1:Cynefin分類
マイクロサービスの境界決定はComplex(複雑)領域。探索と実験が必要。
ステップ2:結合の3次元で評価
| サービス間の関係 | 強度 | 距離 | 変動性 | 評価 |
|---|---|---|---|---|
| Order ↔ Customer | 中 | 遠い | 中 | ⚠️ |
| Order ↔ Payment | 高 | 遠い | 高 | ❌ |
| Order ↔ Inventory | 高 | 遠い | 高 | ❌ |
| Product ↔ Inventory | 中 | 遠い | 中 | ⚠️ |
ステップ3:境界の調整
オプションA:Order、Payment、Inventoryを統合
OrderとPayment、Inventoryの間に強い結合があるため、これらを単一サービスにまとめる。
- メリット:トランザクション境界が明確、ネットワークレイテンシなし
- デメリット:サービスサイズが大きくなる、独立したデプロイが困難
オプションB:イベント駆動アーキテクチャを導入
結合の強度を下げるため、イベント駆動パターンを採用。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
# Order Service
class OrderService:
def create_order(self, order_data):
# 注文を作成
order = self.repository.save(order_data)
# イベントを発行(弱い結合)
self.event_bus.publish(OrderCreatedEvent(order))
return order
# Payment Service(イベントリスナー)
class PaymentService:
def on_order_created(self, event: OrderCreatedEvent):
# 決済処理を開始
self.process_payment(event.order_id, event.amount)
# Inventory Service(イベントリスナー)
class InventoryService:
def on_order_created(self, event: OrderCreatedEvent):
# 在庫を引き当て
self.reserve_inventory(event.items)
改善後の3次元評価:
| サービス間の関係 | 強度 | 距離 | 変動性 | 評価 |
|---|---|---|---|---|
| Order → イベントバス | 低 | 遠い | 低 | ✅ |
| Payment ← イベントバス | 低 | 遠い | 低 | ✅ |
| Inventory ← イベントバス | 低 | 遠い | 低 | ✅ |
トレードオフ:
- メリット:結合の強度が低減、独立したデプロイが可能
- デメリット:結果整合性(Eventual Consistency)、デバッグの複雑性増加
ステップ4:反復的改善
Complex領域の問題なので、小規模から開始し、フィードバックに基づいて調整:
- 最も変動性の高い領域(例:Payment)を最初に分離
- 運用経験を積む
- 結合のバランスを再評価
- 必要に応じて境界を調整
まとめ
Vlad Khononovの『ソフトウェア設計の結合バランス』1は、50年以上続く「疎結合至上主義」を超えた新しいアプローチを提案しています。
本記事の要点
1. 結合の3次元評価
結合を強度(Strength)、距離(Distance)、変動性(Volatility)の3次元で評価することで、より精緻な設計判断が可能になります。
2. Connascence(コナーセンス)
Meilir Page-Jonesが提唱したConnascenceは、結合度をより細かく分類し、リファクタリングの指針を提供します。
3. Cynefin理論と複雑性
システムの複雑性レベル(Simple、Complicated、Complex、Chaotic)に応じて、適切な結合戦略を選択します。
4. バランスの重要性
重要なのは「ゼロ結合」を目指すことではなく、状況に応じた適切なバランスを取ることです。
実践的な設計原則
許容される結合:
- 強度が低く、変動性が低い(例:標準ライブラリ)
- 強度が高いが、距離が近い(例:同一クラス内)
- 距離が遠いが、強度が低く、変動性が低い(例:安定したAPI)
問題のある結合:
- 強度が高く、距離が遠く、変動性が高い
リファクタリング指針:
- 強い結合は距離を縮める
- 変動性の高い要素への結合は強度を下げる
- Connascenceの種類を弱いものに変換する
現代的な適用
マイクロサービス、分散システム、クラウドネイティブアーキテクチャが主流となった現代において、結合バランスの考え方は極めて重要です。
- マイクロサービスの境界決定:3次元評価で最適な粒度を判断
- イベント駆動アーキテクチャ:結合の強度を下げる手段
- 依存性注入(DI):距離を維持しつつ強度を下げる技法
次のステップ
本記事で解説した理論は、以下のような実践的なシナリオに応用できます:
- レガシーシステムのリファクタリング
- 新規アーキテクチャの設計
- コードレビューの観点
- チームの設計原則の確立
関連記事:
- AIペアプログラミングが生む密結合の罠:結合バランスで読み解く技術的負債 - 本記事で解説した結合バランスの理論を、AI生成コードの品質問題に応用した実践的な記事
Khononovが述べるように、ソフトウェア設計において重要なのは「疎結合至上主義」ではなく、状況に応じた適切なバランスです。この原則は、ソフトウェア開発の普遍的な真理として、今後も価値を持ち続けるでしょう。
参考資料
その他参考資料(本文中で番号引用なし)
本文中では直接引用していないが、記事作成時に参照した資料を記載。
Thoughts on Coupling in Software Design - Codurance (2016). 【信頼性: 中】 結合に関する考察。
Beyond Basic Coupling: Understanding Connascence to Build Truly Robust Systems - Mohammed Sallam, Medium. 【信頼性: 中】 コナーセンスの実践的解説。
SE Radio 662: Vlad Khononov on Balancing Coupling in Software Design - Software Engineering Radio (2025). 【信頼性: 中〜高】 Vlad Khononovへのインタビューポッドキャスト。
引用の正確性について:
本記事で引用した研究・資料は、以下の方法で検証しています:
- 学術データベース(Google Scholar、ACM Digital Library等)での確認
- 公式ウェブサイトでの情報確認
- 複数の独立した情報源による相互検証
一部の書籍については、全文PDFへの直接アクセスが制限されている場合がありますが、書籍情報、著者情報、および主要な概念については、公式の情報源および信頼できる書評・解説を通じて確認しています。
Balancing Coupling in Software Design: Universal Design Principles for Architecting Modular Software Systems - Vlad Khononov (2024). Addison-Wesley. 【信頼性: 高】 結合の3次元(強度、距離、変動性)を提示し、結合のバランス化アプローチを提案。 ↩︎ ↩︎2 ↩︎3 ↩︎4
ソフトウェア設計の結合バランス 持続可能な成長を支えるモジュール化の原則 - Vlad Khononov, 島田浩二(訳) (2025). インプレス. 【信頼性: 高】 英語版の日本語訳。2025年10月17日出版。 ↩︎
Structured Design - Stevens, W. P., Myers, G. J., Constantine, L. L., IBM Systems Journal (1974). 【信頼性: 高】 結合(coupling)と凝集(cohesion)の概念を初めて提唱した古典的論文。 ↩︎ ↩︎2
Balancing Coupling in Software Design: Core Concepts - Vlad Khononov (2024). 【信頼性: 高】 結合の3次元(強度、距離、変動性)の詳細解説。公式サイト。 ↩︎ ↩︎2 ↩︎3 ↩︎4 ↩︎5
Connascence - Wikipedia. 【信頼性: 中〜高】 Meilir Page-Jonesが1992年に提唱したコナーセンスの概念を解説。 ↩︎ ↩︎2
『ソフトウェア設計の結合バランス 持続可能な成長を支えるモジュール化の原則』 - snoozer05’s blog (2025). 【信頼性: 中】 書籍レビュー。第6章がコナーセンスに特化していることを報告。 ↩︎ ↩︎2
Connascence: Coupling, Cohesion & Connascence - Khalil Stemmler. 【信頼性: 中】 コナーセンスの実践的解説。 ↩︎
Balancing Coupling in Software Design - Chapter 2: Coupling and Complexity: Cynefin - Vlad Khononov (2024). 【信頼性: 高】 書籍第2章。Cynefin理論と複雑性を解説。 ↩︎ ↩︎2
クネビンフレームワークとソフトウェアエンジニアリング - mtx2s’s blog (2021). 【信頼性: 中】 Cynefin理論のソフトウェア開発への応用を解説。 ↩︎