なぜクリーンアーキテクチャか
このドキュメントの目的
クリーンアーキテクチャがなぜ生まれたのか、どんな問題を解決しようとしているのかを理解することが目標です。
目次
解決したい問題
ソフトウェアが抱える典型的な問題
┌─────────────────────────────────────────────┐
│ よくある悩み │
├─────────────────────────────────────────────┤
│ │
│ 「フレームワークを変えたいけど、 │
│ ビジネスロジックに入り込んでいて無理」 │
│ │
│ 「DBを変えたいけど、 │
│ SQLがあちこちに散らばっていて無理」 │
│ │
│ 「テストを書きたいけど、 │
│ DBがないと何も動かない」 │
│ │
│ 「UIを変えたいけど、 │
│ ロジックがViewに書いてあって切り離せない」 │
│ │
└─────────────────────────────────────────────┘
これらの問題の根本原因は何でしょうか?
根本原因: 依存の方向
┌─────────────────────────────────────────────┐
│ 問題のあるコード │
├─────────────────────────────────────────────┤
│ │
│ ビジネスロジック │
│ ↓ 依存 │
│ フレームワーク │
│ ↓ 依存 │
│ データベース │
│ │
│ ビジネスロジックが下位層に依存している │
│ → 下位層を変えるとビジネスロジックも変わる │
│ │
└─────────────────────────────────────────────┘
最も重要なもの(ビジネスロジック)が、最も変わりやすいもの(技術的詳細)に依存している。
これが問題の本質です。
なぜこうなるのか
自然に書くとこうなりがちです:
「ユーザーを保存したい」
→ データベースに保存しよう
→ SQLを書こう
→ フレームワークのDB機能を使おう
結果:
ビジネスロジックの中にSQL文やフレームワークの呼び出しが混在
便利なものに直接依存するのは自然な流れです。しかし、これが後々の変更を困難にします。
依存の方向という考え方
依存とは何か
┌─────────────────────────────────────────────┐
│ 依存の意味 │
├─────────────────────────────────────────────┤
│ │
│ AがBに依存している │
│ = AはBを知っている │
│ = AはBがないと動かない │
│ = Bが変わるとAも影響を受ける │
│ │
└─────────────────────────────────────────────┘
何が何に依存すべきか
変わりやすいものと変わりにくいものを考えてみましょう:
┌─────────────────────────────────────────────┐
│ 変わりやすさの比較 │
├──────────────────── ─────────────────────────┤
│ │
│ 変わりにくい: │
│ └── ビジネスルール │
│ 「ユーザーはメールアドレスを持つ」 │
│ 「注文は商品と数量を持つ」 │
│ │
│ 変わりやすい: │
│ ├── 使うフレームワーク │
│ ├── 使うデータベース │
│ ├── UIのデザイン │
│ └── 外部APIの仕様 │
│ │
└────────────── ───────────────────────────────┘
依存の方向を逆転させる
問題のある方向:
ビジネスロジック → フレームワーク → DB
あるべき方向:
DB → フレームワーク → ビジネスロジック
変わりやすいものが、変わりにくいものに依存する
これが**依存性逆転の原則(DIP: Dependency Inversion Principle)**の本質です。
同心円の図が伝えたいこと
よく見る図
┌─────────────────────── ──────────┐
│ Frameworks & Drivers │
│ ┌───────────────────────────┐ │
│ │ Interface Adapters │ │
│ │ ┌─────────────────────┐ │ │
│ │ │ Use Cases │ │ │
│ │ │ ┌───────────────┐ │ │ │
│ │ │ │ Entities │ │ │ │
│ │ │ └───────────────┘ │ │ │
│ │ └─────────────────────┘ │ │
│ └───────────────────────────┘ │
└─────────────────────────────────┘
依存の方向: 外側 → 内側
この図が本当に言いたいこと
┌─────────────────────────────────────────────┐
│ 同心円の意味 │
├─────────────────────────────────────────────┤
│ │
│ 内側ほど: │
│ ├── 重要(ビジネスの本質) │
│ ├── 安定(変わりにくい) │
│ └── 抽象的(具体的な技術に依存しない) │
│ │
│ 外側ほど: │
│ ├── 詳細(技術的な実装) │
│ ├── 不安定(変わりやすい) │
│ └── 具体的(特定の技術に依存) │
│ │
└─────────────────────────────────────────────┘
各層の役割
┌─────────────────────────────────────────────┐
│ Entities(エンティティ) │
├─────────────────────────────────────────────┤
│ ビジネスの核心となる概念とルール │
│ 例: ユーザー、注文、商品 │
│ 「ユーザーは有効なメールアドレスを持つ」 │
└─────────────────────────────────────────────┘
┌─────────────────────────────────────────────┐
│ Use Cases(ユースケース) │
├─────────────────────────────────────────────┤
│ アプリケーション固有のビジネスルール │
│ 例: ユーザー登録、注文処理 │
│ 「登録時にメール確認を送る」 │
└─────────────────────────────────────────────┘
┌─── ──────────────────────────────────────────┐
│ Interface Adapters(インターフェースアダプター)│
├─────────────────────────────────────────────┤
│ 内側と外側の変換 │
│ 例: Controller、Presenter、Gateway │
│ 「HTTPリクエストをユースケースの入力に変換」│
└─────────────────────────────────────────────┘
┌─────────────────────────────────────────────┐
│ Frameworks & Drivers(フレームワーク・ドライバー)│
├─────────────────────────────────────────────┤
│ 外部ツールやフレームワーク │
│ 例: Web Framework、DB、外部API │
│ 「PostgreSQLへの接続」 │
└─────────────────────────────────────────────┘
重要なポイント
┌─────────────────────────────────────────────┐
│ 依存は常に内側に向かう │
├─────────────────────────────────────────────┤
│ │
│ ✓ 外側は内側を知っている │
│ ✗ 内側は外側を知らない │
│ │
│ Controller → UseCase → Entity ✓ │
│ Entity → UseCase → Controller ✗ │
│ │
│ 内側のコードに外側のimport文があってはならない│
│ │
└─────────────────────────────────────────────┘
何が得られるのか
フレームワークからの独立
┌─────────────────────────────────────────────┐
│ フレームワークに依存しないとは │
├─────────────────────────────────────────────┤
│ │
│ ビジネスロジックがフレームワークを知らない │
│ │
│ 結果: │
│ ├── フレームワークを変えてもロジックは無傷 │
│ ├── フレームワークなしでテストできる │
│ └── フレームワークの流行に左右されない │
│ │
└─────────────────────────────────────────────┘
データベースからの独立
┌─────────────────────────────────────────────┐
│ DBに依存しないとは │
├─────────────────────────────────────────────┤
│ │
│ ビジネスロジックがDBの種類を知らない │
│ │
│ 結果: │
│ ├── PostgreSQL → MySQL も比較的容易 │
│ ├── RDB → NoSQL の検討も可能 │
│ └── インメモリDBでテストできる │
│ │
└─────────────────────────────────────────────┘
テスト容易性
┌─────────────────────────────────────────────┐
│ テストしやすいとは │
├─────────────────────────────────────────────┤
│ │
│ ビジネスロジックを単独でテストできる │
│ │
│ なぜ可能か: │
│ ├── DBがなくてもロジックは動く │
│ ├── 外部APIがなくてもロジックは動く │
│ └── 依存は全てインターフェース経由 │
│ │
└─────────────────────────────────────────────┘
まとめ
クリーンアーキテクチャが解決する問題
問題:
最も重要なもの(ビジネスロジック)が
最も変わりやすいもの(技術的詳細)に依存している
解決策:
依存の方向を逆転させる
技術的詳細がビジネスロジックに依存するようにする
同心円の本質
・内側 = 重要・安定・抽象
・外側 = 詳細・不安定・具体
・依存は常に外側から内側へ
得られるもの
・フレームワークからの独立
・データベースからの独立
・テスト容易性
・変更に強い設計
次のステップ
- 依存ルール で依存の方向をどう実現するか学ぶ