balanced-coupling について
balanced-couplingは、Vlad Khononovの結合モデルを解説するリファレンススキルです。統合の強さ、距離、変動性から、結合がモジュール性や変更コストに与える影響を考えるために使えます。
主な機能
- 014段階の統合強度を解説
- 02コンポーネント間の距離を分析
- 03変動性を考慮
- 04結合とモジュール性の関係を説明
- 05ドメイン駆動設計との関連を整理
活用シーン
- 01システム設計の結合を評価
- 02コンポーネント間の変更コストを検討
インストール
コマンドをコピーしてターミナルで実行します。
npx skills add https:/ / github.com/ vladikk/ modularity --skill balanced-couplingインストール後、Claude Code で/balanced-couplingを入力して読み込まれたか確認します。
詳細
バランスの取れた結合モデル
Vlad Khononov が説明するバランスの取れた結合モデルを理解するための包括的なリファレンスです。このドキュメントでは、coupling.dev の関連記事をもとに、モデル全体をまとめています。基盤となる考え方、各次元、バランスの仕組み、従来の結合モデルとの関係、ドメイン駆動設計とのつながりを扱います。
1. 基礎:結合が重要な理由
1.1 結合は敵ではありません
「結合」という用語は長らく、悪い設計と同義とされてきました。バランスの取れた結合モデルは、この前提に異議を唱えます。辞書によれば、結合とは単に部品をつなぐための装置です。システムが、目標を達成するために相互作用するコンポーネントの集合であるなら、結合とはコンポーネントをつなぎ、目標を達成できるようにするものです。結合こそが、システムの価値を各部分の価値の総和よりも大きくします。
完全に独立したコンポーネントからシステムを構築することはできません。それでは、そもそもの「システム」の定義に反してしまいます。問うべきなのは、結合するかどうかではなく、どのように結合するかです。結合の形によってはモジュール性が高まり、別の形では複雑さが生まれます。バランスの取れた結合モデルでは、結合を排除すべき厄介なものではなく、意図的に活用する設計ツールとして捉えます。
1.2 複雑さ(Cynefin に基づく)
このモデルでは、Cynefin フレームワークにおける複雑さの定義を採用しています。
- 明確(単純): 変更を加えると、結果が正確にわかります。
- 込み入った状態: 結果はわかりませんが、専門家はわかっているため、相談できます。
- 複雑: 結果を知る唯一の方法は、変更を加えて何が起こるかを観察することです。原因と結果を特定できるのは、事後に限られます。
- カオス: 事後であっても、行動と結果の間に特定可能な関係がありません。
ソフトウェア設計における複雑さとは、変更の結果が予測できないシステムを意味します。モジュール設計の目標は、変更の影響を事後になって初めて特定できる状況を避けることです。
重要なのは、複雑さは主観的であるという点です。複雑さは、システム設計と私たちの認知能力の限界の両方によって決まります。
complexity = f(system design, cognitive limits)
研究によると、人間が作業記憶に同時に保持できる情報は、わずか 4 +/- 1 個程度です。変更に必要な情報がこの認知能力を超えると、その設計は複雑になります。
1.3 モジュール性:複雑さの対極
複雑さによって変更の結果が予測できなくなるのに対し、モジュール性はその対極にあります。モジュール設計は、次の 2 つの基準を満たします。
- システムのどの部分を変更する必要があるかが明確であること。
- 変更の結果が明確で、予測可能であること。
モジュール性は、システムの目標を将来にわたって支えます。将来の要件を先回りして実装するという意味ではありません。それは不可能です。必要な認知負荷を最小限に抑えることで、妥当な将来の変更を容易に実装できるようにすることです。
システムとは、目標を達成するために相互作用するコンポーネントの集合です。「泥団子」のようなシステムであっても、現在の目標は達成できます。モジュール設計は、目標が変化してもシステムが目標を達成し続けられるようにすることで、その目標を将来へとつなげます。
1.4 共通の原因
複雑さとモジュール性は対照的な概念ですが、同じ根本的な原因、つまり結合によって左右されます。コンポーネント同士のつながり方が、システムがモジュール化されるか、複雑になるかを決定します。
2. 結合の 3 つの次元
2 つのコンポーネントが結合されている場合、モジュール性や複雑さを決めるのはコンポーネントそのものではなく、両者のつながりです。バランスの取れた結合モデルでは、このつながりを統合の強さ、距離、変動性という 3 つの次元で評価します。
2.1 統合の強さ(知識)
統合には、コンポーネント同士が互いに関する知識を交換する必要があります。共有される知識が多いほど、あるコンポーネントの変更がほかのコンポーネントにも連鎖的な変更を引き起こす可能性が高くなります。
知識を定量的に「測定」しようとするのではなく、このモデルでは知識の種類を分類します。それぞれの種類で、共有される知識の量は大きく異なります。これが統合の強さモデルで、最も強い/共有される知識が最も多いものから、最も弱い/最も少ないものまで、4つのレベルを定義します。
侵襲的結合(最も強い)
統合にプライベートインターフェースや実装の詳細(内部データベース、プライベートオブジェクト、ドキュメント化されていない API など)を使用する場合に発生します。コンポーネントの実装に関するすべての知識が共有されると考える必要があります。侵襲的結合は脆弱であると同時に暗黙的です。「侵入された」コンポーネントの作成者は、統合が存在することすら知らない場合があります。
古典的なモジュール結合モデルの内容結合(病理的結合)に相当します。
機能的結合
コンポーネントの実装の 方法 ではなく、実装する 内容、すなわち機能要件に焦点を移します。複数のコンポーネントがビジネス要件に関する知識を共有し、その要件が変化すると一緒に変更する必要がある場合に発生します。
極端な例として、知識の重複があります。同じビジネスルールをフロントエンドとバックエンドの両方に実装するケースです。仕様の変更が両方に同時に反映されないと、システムは整合性のない状態になります。
侵襲的結合と同様に、機能的結合も暗黙的になり得ます。明示的には結合されていないコンポーネント間でビジネスロジックが重複していても、一緒に変更する必要がある場合があります。
古典的なモジュール結合モデルの共通結合、外部結合、制御結合に相当します。
モデル結合
コンポーネントがビジネスドメインモデルに関する知識を共有する場合に発生します。新たなドメインの知見によってモデルが変更された場合、結合されたすべてのコンポーネントもそれに応じて変更する必要があります。
ドメイン駆動設計では、単一の巨大で包括的なモデルではなく、複数の特化したモデルを扱うことが重視されます。コンポーネントがこれらのモデルのいずれかを共有すると、モデル結合が生じます。
古典的なモジュール結合モデルのスタンプ結合に相当します。
契約結合(最も弱い)
共有される知識が最も少ないレベルです。統合契約は実装の詳細、機能要件、ビジネスモデルをカプセル化し、統合を明示的で安定したものにします。
契約を導入する設計パターンには、Facade、Open-host service/Published language(DDD)、Anti-corruption layer(DDD)、Data transfer objects(DTO)が含まれます。
古典的なモジュール結合モデルのデータ結合に相当し、これを発展させたものです。内部モデルと明示的な統合契約を区別します。
暗黙性から明示性までのスペクトラム
統合の強さの4つのレベルは、共有される知識がどの程度暗黙的または明示的であるかも表します。
- 契約結合 = 最も明示的
- モデル結合 = 明示的だが、より広範
- 機能的結合 = 暗黙的になり得る
- 侵襲的結合 = 最も暗黙的で脆弱
統合の強さの度合い
各レベル内では、コネッサンスのレベルを使って、より細かな比較が可能です。
- 静的コネッサンスのレベル(名前、型、意味、アルゴリズム、位置)を使って、契約結合とモデル結合の度合いを比較できます。
- 動的コネッサンスのレベル(実行、タイミング、値、識別情報)を使って、機能的結合の度合いを比較できます。
2.2 距離
結合されたコンポーネント間の物理的・論理的な距離は、変更コストに影響します。同じファイル内の2つのメソッドを一緒に進化させるほうが、別々のマイクロサービスや独立したシステムにある2つのオブジェクトを一緒に進化させるよりも、はるかに容易です。
抽象化のレベルが上がるにつれて距離は広がります。メソッド -> オブジェクト -> 名前空間/パッケージ -> (マイクロ)サービス -> システムの順です。各レベルで、同時に変更するための認知的労力と調整コストが増加します。
距離は観察する抽象化レベルに相対的です
距離は絶対的な尺度ではなく、分析対象の抽象化レベルに相対的です。このモデルはフラクタルであり、同じバランスのルールが、クラス内のメソッド、モジュール内のクラス、サービス内のモジュール、システム内のサービスのいずれを見る場合にも当てはまります。
特定の抽象化レベルでは、最も大きな距離がそのレベルの境界です。複数のモジュールから成る単一のサービスでプロジェクトが構成されている場合、その文脈ではモジュール間の距離が最も大きくなります。同じ原則が当てはまります。2 つのモジュールの統合強度が高い場合、その結合は不均衡です。システム全体の視点では同じサービス内にあるとしても、です。
距離の大きい結合の問題を抱えるのに、マイクロサービスや分散システムは必要ありません。デプロイ可能な単位が 1 つだけの個人プロジェクトでも、モジュール間の密結合に悩まされることがあります。モジュールレベルの抽象化では、モジュールをまたぐ統合が利用可能な最も大きな距離だからです。
ライフサイクル結合(対抗要因)
変更コストに対抗する要因はライフサイクル結合です。コンポーネント同士が近いほど、それらのライフサイクルは密接に結び付き、同時にテストしてデプロイする必要があります。「モノリスからマイクロサービスへ」のリファクタリングの多くは、主にライフサイクルの依存関係を減らすことを目的としていました。
したがって、距離はトレードオフです。距離が小さいほど、共同進化のコストは低くなりますが、ライフサイクル結合は強くなります。距離が大きいほど、ライフサイクルは独立しますが、共同進化のコストは高くなります。
距離は社会技術的なものです
距離は純粋に技術的なものではありません。組織構造が距離に大きく影響します。
- 同じチームが実装する 2 つのマイクロサービスは、コード構造が同一でも、異なるチームが実装する 2 つのマイクロサービスより実質的な距離が小さくなります。
- 複数のチームが変更を調整する必要がある場合、認知的な労力とコラボレーションのオーバーヘッドが大幅に増加します。
これはコンウェイの法則を反映しています。組織構造がシステムのアーキテクチャを形作ります。
実行時結合
コンポーネント間の実行時の依存関係も距離に影響します。同期的な統合は、非同期的な統合よりもライフサイクル結合を強めます。実行時の密な依存関係はコンポーネントのライフサイクルを結び付け、一方の障害がもう一方に波及する可能性があります。
実行時結合を減らす(例えば、非同期メッセージングを利用する)と、コンポーネント間の実質的な距離は大きくなります。結合のバランスを保つには、統合強度を下げて、この距離の増加を補う必要があります。
2.3 変動性
統合強度は、変更が境界を越えて波及する可能性を表します。距離は、変更が連鎖した場合のコストを決定します。第 3 の次元である変動性は、そもそもコンポーネントに変更が必要となる確率を表します。
変動性が高いほど、設計上の問題は深刻になり、「痛み」を伴うものになります。統合強度と距離がともに大きいコンポーネントでも、変更されなければ実際上の問題は起きません。しかし、同じコンポーネントが頻繁に変更されるなら、絶えず問題の種となります。
DDD のサブドメインで変動性を評価する
未来を予測することは不可能ですが、ドメイン駆動設計におけるサブドメインという概念は、有用なヒューリスティックを提供します。
- コアサブドメイン(競争優位性、「興味深い課題」) -> 最も変動性が高い。企業は継続的に最適化し、改善します。
- 支援サブドメイン(競争優位性がなく、すぐに使えるソリューションもない、「退屈な課題」) -> 変動性が低い。通常、CRUD によるデータ入力や ETL プロセスです。
- 汎用サブドメイン(解決済みの課題、市販のソリューション) -> 機能の変動性は低く、実装の変動性はさまざま。機能自体は成熟しており、めったに変わりません。すでに解決済みの課題だからです。しかし、実装には変動性がある場合があります。プロバイダーの切り替え、別のテクノロジーの採用、複数の実装の並行運用は、いずれも現実的な変更要因です。たとえば、TTS エンジン(AWS Polly)は汎用的な機能ですが、Google TTS、ElevenLabs、セルフホスト型ソリューションへの切り替えは十分に想定されます。そのような場合、プロバイダー固有の知識をカプセル化するには、強固な統合契約が不可欠です。一方で、汎用サブドメインの実装によっては、本質的に変更しにくいものもあります。ID とアクセス管理に Auth0 を選んだ場合、契約の設計にかかわらず、Clerk への切り替えは大きな出来事になります。汎用サブドメインの境界を設計する際は、実装を切り替える、あるいは複数の実装を同時に使用する可能性を評価し、それに応じて統合契約を適用してください。
Wardley Map のコモディティ化軸は、変動性を捉える別の視点を提供します。
本質的な(非)変動性と偶発的な(非)変動性
重要な違いがあります。
- 偶発的な変動性:コミットが頻繁だからといって、ビジネスドメインに変動性があるとは限りません。設計の不備、つまり統合の強度や距離の管理が効果的でないことが、コンポーネントを頻繁に変更させる原因になる場合があります。
- 偶発的な不変性:一見安定しているコンポーネントも、本質的に安定しているとは限りません。ビジネス上は変更を望んでいるものの、設計の不備があるシステムを変更するリスクと労力が大きいため、変更できない場合があります。
したがって、変動性はコミット履歴だけでなく、ビジネスドメインの観点(本質的な変動性)から評価する必要があります。
3. フラクタル幾何学
ソフトウェア設計はフラクタルです。オブジェクトからモジュール、サービス、システム全体にまたがる相互作用まで、さまざまな抽象度でコンポーネントとその相互作用を設計します。バランスの取れた結合モデルは、これらすべてのレベルに適用されます。
ただし、統合強度レベルの意味は、作業している抽象度によって変わります。何が統合契約、実装モデル、機能要件に当たるかは、各レベルで異なります。抽象度の低いレベルでの統合契約(例:クラスの公開インターフェース)は、はるかに高いレベルでは実装の詳細(例:サービス境界内)に当たる場合があります。同様に、同じモジュール内の2つのオブジェクトで共有されるモデルは、オブジェクトレベルではモデル結合ですが、システムレベルではモジュール内部に完全に収まっており、見えず、関係もありません。
距離についても同様です。特定の抽象度では、そのレベルの境界が最も高い距離になります。単一のサービス内のモジュールを設計している場合、モジュール間の境界が最も高い距離になります。システムの視点では、これらのモジュールが同じ場所に配置されているとしても同様です。システム間の相互作用を設計している場合は、システム間の境界が最も高い距離になります。
したがって、このモデルを適用するときは、常にどの抽象度で作業しているかを明確にする必要があります。これによって、次の点が決まります。
- 統合強度:このレベルで何が契約、モデル、機能依存、侵襲的な依存に当たるか。
- 距離:このレベルで何が最も低い距離、最も高い距離に当たるか。
この枠組みがないと、同じ結合関係でも、見る側の視点によってバランスが取れているようにも、取れていないようにも見えます。
4. 次元のバランスを取る
4.1 4つの極端な組み合わせ(強度 × 距離)
統合強度と距離の相互作用は、それらの極端な組み合わせを通じて理解できます。
| 距離が低い | 距離が高い | |
|---|---|---|
| 強度が低い | 凝集度が低い(複雑性) — 無関係なコンポーネントが近くに配置されています。認知負荷が増加します。ビッグボールオブマッドへと向かいます。 | 疎結合(モジュール性) — 強度が低いため、変更の連鎖を最小限に抑えられます。距離が高くてもバランスが取れています。 |
| 強度が高い | 凝集度が高い(モジュール性) — コンポーネントは一緒に進化する必要がありますが、距離が低いため、変更の連鎖を低コストで実施できます。 | 密結合(複雑性) — 変更の連鎖が頻繁に発生し(強度が高い)、実施コストも高くなります(距離が高い)。分散モノリスへの一歩です。 |
4.2 バランスのルール
重要な洞察は、統合強度と距離が互いにバランスを取るとき(片方が高く、もう片方が低い)、モジュール性が生まれるということです。両者が等しいとき(両方とも高い、または両方とも低い)、複雑性が生まれます。
二値論理で表すと、次のようになります。
MODULARITY = STRENGTH XOR DISTANCE
COMPLEXITY = STRENGTH AND DISTANCE
このことから、「疎結合」と「高凝集度」がどちらも望ましい理由が分かります。これらはどちらもバランスの取れた結合の形態であり、次元の値が異なるだけです。
4.3 実用的なバランス(変化しやすさを加える)
Eric Evansは「大規模システムのすべてが適切に設計されているとは限らない」と指摘しました。変化しやすさという次元を加えることで、実用性が考慮されます。
結合のバランスが取れていなくても(強度が高く、距離も高い)、コンポーネントが変更される見込みがない場合は、変化しやすさが低いため、その影響は中和されます。侵襲的な結合度が高く、まったく進化しないレガシーシステムは許容できます。結合は技術的には「悪い」ものの、実用上は無害です。
完全なバランスの式は次のとおりです。
BALANCE = (STRENGTH XOR DISTANCE) OR NOT VOLATILITY
つまり、次のいずれかに当てはまるとき、結合のバランスが取れています。
- 強度と距離が互いに相殺し合っている(XOR)、または
- 強度と距離の関係にかかわらず、コンポーネントの変化しやすさが低い。
注:このブログでは、説明のために簡略化した二値モデルを使用しています。書籍 Balancing Coupling in Software Design には、二値の極端な値ではなく連続値を使った、より精緻な数学モデルが記載されています。
5. ドメイン駆動設計との関連
バランスの取れた結合モデルは、DDD と深く関連しています。多くの DDD のパターンやプラクティスは、結合の各側面に直接関係しています。
戦略的設計
- 境界づけられたコンテキストは、ビジネスドメインのモデルを共有するコンポーネント(モデル結合)に対して、物理的な境界(中程度の距離、ライフサイクルの共有)を定義します。
- 境界づけられたコンテキストの統合パターン(共有カーネル、パートナーシップ、順応者、腐敗防止層、公開ホストサービス、別々の方法)は、知識を共有する度合いを決定します。アドホックなパターンでは、より多くの知識交換が可能になります。正式なパターンでは、それが抑えられます。これは、統合の強さと距離の組織的側面の両方を反映しています。
- 一部の統合パターン(腐敗防止層、公開ホストサービス)は、統合固有の契約(契約結合)の背後に内部モデルをカプセル化します。これは、距離が大きい場合に使用されます。
戦術的設計
- 集約パターンと値オブジェクトパターンは、トランザクション境界(高い機能的結合度)を共有する振る舞いを、同じ場所(距離が小さい)に配置します。これはバランスが取れています。結合の強さが、距離の小ささによって相殺されるためです。
- ビジネスロジックの実装パターン(トランザクションスクリプト、アクティブレコード、ドメインモデル、イベントソーシングによるドメインモデル)は、ドメインの複雑さに応じて選択されます。これは、変動性に直接関係しています。
サブドメインと変動性
- コアサブドメイン = 変動性が最も高い → 結合を最も慎重に管理する必要があります
- 支援サブドメイン = 変動性が低い → DDD では、ここでの実用的な近道が明示的に許容されています(「大規模システムのすべてが、適切に設計されているわけではありません」— Eric Evans)。これは、変動性が低ければ、バランスを欠いた結合が無害化されるためです
- 汎用サブドメイン = 機能面での変動性は低い(問題が解決済みである)が、実装面での変動性はさまざまです。プロバイダーの切り替えや複数の実装の利用が高い確率で見込まれる場合(例:TTS エンジン、決済ゲートウェイ、通知サービス)、プロバイダー固有の知識をカプセル化するため、強固な統合契約を適用します。切り替えコストが本質的に高く、その可能性が低い場合(例:ID プロバイダー、コアデータベース)は、実用的な近道が許容されます。ただし、この前提を検証し、変更につながりそうな要因を洗い出してから決定してください
DDD のサブドメインは、バランスの取れた結合モデルにおいて、コンポーネントの変動性の側面を評価するための主要な手段です。
6. まとめ:モデルの概要
+-----------------------------------------------------+
| BALANCED COUPLING |
| |
| Three Dimensions: |
| +---------------------+ |
| | Integration Strength | -> Likelihood of cascading |
| | (Knowledge shared) | changes |
| | | |
| | Levels: | |
| | Intrusive (highest) | |
| | Functional | |
| | Model | |
| | Contract (lowest) | |
| +---------------------+ |
| +---------------------+ |
| | Distance | -> Cost of cascading |
| | (Socio-technical) | changes |
| | | |
| | Factors: | |
| | Code structure | |
| | Org structure | |
| | Runtime deps | |
| +---------------------+ |
| +---------------------+ |
| | Volatility | -> Probability of change |
| | (Rate of change) | occurring at all |
| | | |
| | Evaluated via: | |
| | DDD subdomains | |
| | Wardley Maps | |
| | (NOT commit history)| |
| +---------------------+ |
| |
| Balance Rule: |
| MODULARITY = STRENGTH XOR DISTANCE |
| BALANCE = (STRENGTH XOR DISTANCE) OR NOT VOLATILITY |
| |
| Key Insight: |
| Loose coupling and high cohesion are BOTH forms of |
| balanced coupling, not separate concepts. |
+-----------------------------------------------------+
核となる原則
- **結合は本質的に悪いものではありません。**結合があるからこそ、システムは機能します。目標は結合をなくすことではなく、バランスを取ることです。
- **結合には3つの側面があります。**1つだけ(例:依存関係の数)を評価しても、全体像は把握できません。
- **モジュール性 = バランスの取れた各側面です。**統合の強さと距離が互いに釣り合うと、設計はモジュール化されます。
- **複雑さ = バランスを欠いた各側面です。**強さと距離の両方が大きい場合(密結合/分散モノリス)、または両方が小さい場合(凝集性の低さ/泥団子状態)、設計は複雑になります。
- **変動性を考慮すると、実用的な判断が可能になります。**変動性が低ければ、バランスを欠いた結合が無害化される場合があります。システムのすべての部分に完璧な設計が必要なわけではありません。
- **このモデルはフラクタルです。**メソッド、オブジェクト、パッケージ、サービス、システムなど、あらゆる抽象化レベルに適用できます。
- **このモデルは社会技術的なものです。**組織構造は、コード構造と同じ程度に距離へ影響します。
- **従来のモデルは置き換えられるのではなく、取り込まれています。**モジュール結合は、統合の強さの各レベルの基盤となります。コンネッセンスは、各レベル内の度合いを示します。バランスの取れた結合モデルは、どちらのモデルにもある盲点に対処します。
ユーザーとのコミュニケーション
ユーザーがドメイン駆動設計の用語に詳しいとは限りません。変動性やサブドメインの分類について説明するときは、平易な言葉で概念を説明してください。
- コアサブドメイン — ビジネスに競争優位性をもたらすシステムの部分であり、組織が積極的に投資している「興味深い課題」です。頻繁に変更されます。
- 支援サブドメイン — ビジネスに必要ですが、差別化にはつながらず、既製のソリューションも存在しないものです。通常は、データ入力、ETL、社内ツールなどの単純なワークフローです。変更されることはほとんどありません。
- 汎用サブドメイン — 認証、決済処理、メール配信など、既に解決済みで既製のソリューションが存在する課題です。機能は成熟していますが、特定のプロバイダーやテクノロジーは変更されることがあります。
DDD の用語を使いつつ、初めて使うときは必ず平易な言葉で簡潔に説明してください。文脈なしでユーザーが「コアサブドメイン」の意味を理解していると想定しないでください。