ストーリー
トレードオフの基本法則
法則1: すべての判断にはトレードオフがある
ヘキサゴナルアーキテクチャを採用する
✅ 得るもの: テスト容易性、変更容易性、技術の交換可能性
❌ 失うもの: シンプルさ、初期開発速度、学習コスト
マイクロサービスを採用する
✅ 得るもの: 独立デプロイ、チームの自律性、スケーラビリティ
❌ 失うもの: 運用の簡便さ、データ整合性、デバッグの容易さ
DDDを適用する
✅ 得るもの: ドメインの正確な表現、ビジネスとコードの一致
❌ 失うもの: 初期設計の工数、シンプルなCRUDでのオーバーヘッド
法則2: コンテキストによって最適解は変わる
同じ「注文管理システム」でも:
スタートアップ(3人チーム、MVP段階):
→ レイヤード + シンプルなCRUD
理由: 市場投入速度が最優先
成長企業(15人チーム、安定成長):
→ モジュラーモノリス + DDD
理由: 変更容易性とチーム分担が重要
大企業(50人チーム、大規模トラフィック):
→ マイクロサービス + DDD
理由: 独立デプロイとスケーラビリティが必須
よくあるトレードオフ
1. 抽象化 vs パフォーマンス
// 高い抽象化(テスト容易、変更容易)
class CreateOrderUseCase {
constructor(private repo: OrderRepository) {} // インターフェース経由
async execute(input: CreateOrderInput): Promise<CreateOrderOutput> {
const order = Order.create(input.customerId, input.items);
await this.repo.save(order); // 変換層のオーバーヘッド
return this.toOutput(order); // 追加の変換コスト
}
}
// 低い抽象化(高パフォーマンス)
async function createOrder(data: any) {
return prisma.order.create({ data }); // 直接DB操作、変換なし
}
| 選択 | メリット | デメリット |
|---|---|---|
| 高い抽象化 | テスト容易、変更容易 | 変換層のオーバーヘッド |
| 低い抽象化 | 高速、シンプル | テスト困難、変更影響大 |
2. 一貫性 vs 可用性(CAP定理)
分散システムでは、以下の3つのうち2つしか同時に満たせない:
- Consistency(一貫性): 全ノードが同じデータを見る
- Availability(可用性): すべてのリクエストに応答する
- Partition Tolerance(分断耐性): ネットワーク分断に耐える
マイクロサービスでは分断耐性(P)は必須なので:
CP: 一貫性を優先(金融系)
AP: 可用性を優先(ECサイト)
3. DRY vs 独立性
// DRY(共有ライブラリ)
// shared/Money.ts を全BCが共有
// ✅ コードの重複がない
// ❌ 変更時に全BCに影響する
// 独立性(各BCが独自に定義)
// ordering/domain/Money.ts
// payment/domain/Money.ts
// ✅ 各BCが独立して進化できる
// ❌ コードが重複する
トレードオフを判断するフレームワーク
ATAM(Architecture Tradeoff Analysis Method)
1. アーキテクチャのプレゼンテーション
2. 品質特性シナリオの作成
3. アーキテクチャ分析
4. トレードオフポイントの特定
5. リスクの特定
6. 結果の文書化
簡易判断フレームワーク
For each architectural decision:
1. 何を得るか(Gains)
- 具体的なメリットを列挙
2. 何を失うか(Costs)
- 具体的なデメリットを列挙
3. 現在のコンテキスト(Context)
- チーム規模、スキルレベル、スケジュール
4. 判断(Decision)
- コンテキストを考慮して、Gainsが上回るか
5. 記録(Record)
- ADRとして記録
実践例: ECサイトのアーキテクチャ判断
# ADR-003: モジュラーモノリスの採用
## 得るもの(Gains)
- デプロイの簡便さ(1つのアーティファクト)
- データ整合性(1つのDB)
- デバッグの容易さ
- 将来のマイクロサービス化への移行パス
## 失うもの(Costs)
- 独立デプロイができない
- チームの自律性が制限される
- 技術スタックの統一が必要
## コンテキスト
- チーム6名
- TypeScript統一
- 月間100万PV(大規模ではない)
- 3ヶ月でMVPリリース必要
## 判断
モジュラーモノリスを採用する。
チーム規模とスケジュールを考慮すると、
マイクロサービスの運用コストは過大。
BCの境界を明確にすることで、
将来必要になった時にサービス分割できる。
アーキテクチャの進化
Time 0: シンプルなモノリス
↓ ドメインが複雑になってきた
Time 6m: モジュラーモノリス(BC分離)
↓ チーム規模が拡大、独立デプロイが必要
Time 18m: 一部のBCをマイクロサービスに分離
↓ さらに成長
Time 36m: 完全なマイクロサービス
重要: 最初から最終形を目指さない
段階的に進化させる(Evolutionary Architecture)
まとめ
| ポイント | 内容 |
|---|---|
| すべてにトレードオフ | メリットとデメリットは表裏一体 |
| コンテキスト重要 | チーム規模、時間、スキルで最適解は変わる |
| 意識的な選択 | 「なんとなく」ではなく根拠を持つ |
| ADRで記録 | トレードオフの判断を文書化する |
| 段階的進化 | 最初から完璧を目指さず、進化させる |
チェックリスト
- 「正解はない、あるのはトレードオフ」を理解した
- 主要なトレードオフ(抽象化 vs パフォーマンス等)を説明できる
- コンテキストに応じた判断ができる
- ADRでトレードオフの判断を記録できる
次のステップへ
次は演習です。ここまで学んだ知識を使って、アーキテクチャ評価レポートを書いてみましょう。
推定読了時間: 30分