🔗
適切な結合(Appropriate Coupling):Connascence と分散モノリスの罠
疎結合≠良いアーキテクチャ。結合度を科学的に分類するConnascenceの概念と、マイクロサービスで陥りやすい分散モノリスの罠を整理する
「疎結合を目指せ」は正しいか
「疎結合を目指す」は設計原則としてよく聞くが、疎結合にすれば必ず良いアーキテクチャになるわけではない。モジュールを細かく分割しすぎると、ネットワーク越しの呼び出しが増え、障害点が増え、データの整合性を保つのが難しくなる。
進化的アーキテクチャが重視するのは「疎結合」ではなく 「適切な結合(Appropriate Coupling)」 だ。どのモジュール間にどの程度の結合を許容するかを、意識的に設計する。
Connascence(共変性)による結合の分類
Connascence は 1996 年に Meilir Page-Jones が提唱した、結合度を科学的に分類するフレームワークだ。「A を変えると B も変えなければならない」という依存関係を 2 軸で分類する。
静的 Connascence(コンパイル時・コード解析で検出可能)
| 種類 | 意味 | 例 |
|---|---|---|
| Name(名前) | 同じ名前に依存 | 関数名・変数名・カラム名 |
| Type(型) | 同じ型に依存 | パラメータの型、戻り値の型 |
| Meaning(意味) | 暗黙の慣習に依存 | 0=未処理 / 1=処理済み のマジックナンバー |
| Position(位置) | 引数の順序に依存 | createUser(name, email) の順番 |
| Algorithm(アルゴリズム) | 同じアルゴリズムに依存 | ハッシュ関数・エンコード方式を両側で持つ |
動的 Connascence(実行時・分散システムで発生しやすい)
| 種類 | 意味 | 例 |
|---|---|---|
| Execution(実行順序) | 特定の順序で呼び出す必要がある | A の後に必ず B を呼ばなければいけない |
| Timing(タイミング) | 特定のタイミングで呼ばれる必要がある | タイムアウト・レース条件 |
| Identity(同一インスタンス) | 同じオブジェクトを参照する必要がある | グローバル状態・シングルトン |
| Value(値の整合性) | 複数場所の値が一致する必要がある | 分散システムのデータ整合性 |
強度の順序と「改善の方向」
静的 < 動的 の順で結合強度が高くなる。動的な結合ほど実行時エラーになりやすく、テストも難しい。
弱い結合(Static) 強い結合(Dynamic)
Name → Type → Meaning → Position → Algorithm → Execution → Timing → Identity → Value
←─────────────────── 改善の方向(なるべく左へ移す)────────────────────────────────→
改善の方向: Value Connascence を Execution に、Execution を Name に変換できれば、結合度を下げられる。
分散モノリスの罠
マイクロサービスに分割したのに、サービス間の結合が強いまま残ってしまう状態を 分散モノリス と呼ぶ。
【悪い例:分散モノリス】
┌────────────────┐
Order Service ──────────→│ User Service │ DB スキーマを共有
└────────────────┘
│ │
└────────────────────→ └── 同期的 HTTP 呼び出しで強結合
┌────────────────┐
│Payment Service │ 実装の詳細を知っている
└────────────────┘
問題: サービスを個別にデプロイできない(全体を一緒に変更しなければならない)
【良い例:適切な結合】
Order Service ──→ イベント発行 ──→ Message Queue ──→ Payment Service
↑ 非同期・疎結合 ↑ 各自が独立してデプロイ可能
Architecture Quantum(アーキテクチャ量子)
進化的アーキテクチャでは Architecture Quantum という概念を導入する。「独立してデプロイ可能な最小の構造単位」のことで、そのユニットが持つ高い機能的結合を指す。
- 良い: 各マイクロサービスが自分のデータストアを持つ → 独立してデプロイ・スケールできる
- 悪い: 複数サービスが同じ DB を共有する → 一方の変更が他方に波及する(量子が1つになってしまう)
【1 Quantum】 【複数 Quantum】
┌─────────────────────────┐ ┌───────────┐ ┌────────────┐
│ Service A │ Service B │ │ Service A │ │ Service B │
│ ↓ ↓ │ │ DB-A │ │ DB-B │
│ ┌─────────────────┐ │ └───────────┘ └────────────┘
│ │ Shared DB │ │ ↕ ↕
│ └─────────────────┘ │ Event / API(疎結合)
└─────────────────────────┘
変更に引きずられる 独立してデプロイ可能
トレードオフ
| パターン | メリット | デメリット |
|---|---|---|
| モノリス | シンプル・トランザクションが扱いやすい | スケール・デプロイが一体化する |
| 適切な結合のマイクロサービス | 独立デプロイ・スケール | データ整合性の設計が必要 |
| 分散モノリス | (なし) | 両方のデメリットを持つ最悪の構成 |
関連概念
- → 進化的アーキテクチャ概要
- → Dual Write(Value Connascence を安全に扱うパターン)
- → Outbox Pattern(動的結合をイベントで疎結合にする)
出典・参考文献
- Neal Ford et al., Building Evolutionary Architectures, Chapter 3 “Engineering Incremental Change”
- Meilir Page-Jones, Fundamentals of Object-Oriented Design in UML (1996) — Connascence
- 1. 🧬進化的アーキテクチャとは:定義・誕生背景・3原則
- 2. 📐適応度関数(Fitness Functions):アーキテクチャ特性を自動検証する
- 3. 🔗適切な結合(Appropriate Coupling):Connascence と分散モノリスの罠
- 4. 🚀段階的変更(Incremental Change):Feature Toggle・Blue-Green・Canary・Dark Launch
- 5. 🔄Expand-Contract パターン:ゼロダウンタイムでスキーマ変更する
- 6. ✍️Dual Write:マイクロサービス分割時のデータ整合性パターンと落とし穴
- 7. 📤Outbox Pattern:トランザクション境界を越えた安全なイベント発行
- 8. 📡CDC(Change Data Capture):アプリを汚さずに変更を伝播する
- 9. 🐚Unix 哲学を現代アーキテクチャへ翻訳する
- 10. 🧅クリーンアーキテクチャが進化耐性をもたらす理由
- 11. 🏢Conway's Law:組織構造がアーキテクチャを決める
出典: 進化的アーキテクチャ(O'Reilly / Neal Ford, Rebecca Parsons, Patrick Kua)