ブログ記事
アーキテクチャとは「依存の方向」の問題だ:Robert C. Martin『Clean Architecture』
「アーキテクチャが良い」とはどういう状態を指すのか——この問いへの答えは意外なほど具体的に示せる。Robert C. Martin(Uncle Bob)の『Clean Architecture 達人に学ぶソフトウェアの構造と設計』は、その答えを「依存の方向」という一つの軸に収束させた一冊だ。
1. アーキテクチャの目的は「オプションを残すこと」
本書が冒頭で述べるアーキテクチャの目的は、機能の実現ではなく「決定を先送りできる余地を作ること」だ。
データベースを MySQL にするか PostgreSQL にするか、フレームワークを何にするか——これらの決定が早い段階でコアのビジネスロジックに影響を与えてしまうと、後から変更するコストが跳ね上がる。良いアーキテクチャとは、これらの技術的選択を「後で決めても動く」状態に保つ設計だ。
この観点では、データベースやフレームワークはアーキテクチャの中心ではなく、交換可能な「詳細」として扱われる。
2. 依存は常に内側へ向ける
本書の中核となる原則が「依存の方向ルール(Dependency Rule)」だ。
ビジネスロジックは外側の技術的な詳細を知らない。逆に、外側のレイヤーは内側に依存する。同心円で表すなら、エンティティ(最内側)→ユースケース→インターフェースアダプタ→フレームワーク/ドライバ(最外側)という順序で、依存の矢印は常に内側に向かう。
これが守られることで、フレームワークやDBを変更しても、ビジネスロジックを表すエンティティとユースケースには手を入れずに済む。「ビジネスルールを変えたいのにDBのコードを読まなければならない」という状況が、この原則の違反から生まれる。
flowchart TD
FW["Frameworks & Drivers\n(フレームワーク・DB・UI)"] --> IA["Interface Adapters\n(Controllers・Gateways・Presenters)"]
IA --> UC["Use Cases\n(アプリケーションビジネスルール)"]
UC --> ENT["Entities\n(エンタープライズビジネスルール)"]
style FW fill:#fce8e8,stroke:#e53935
style IA fill:#fff8e1,stroke:#f5a623
style UC fill:#e8f4fd,stroke:#4a9eda
style ENT fill:#e8f8e8,stroke:#4caf50
3. SOLIDと境界線
本書はSOLIDの各原則を改めて「コンポーネントレベル」と「アーキテクチャレベル」で解説している。
なかでも刺さるのが依存関係逆転の原則(DIP)だ。具象クラスではなく抽象に依存するという原則は、レイヤー間の境界線でも機能する。内側のユースケースが外側のDB実装に直接依存するのではなく、内側が定義したインターフェースに外側が依存することで、依存の方向が逆転する。
境界線はこの逆転を実現する設計上の装置だ。何を境界線の内側に置き、何を外側に置くかが、アーキテクチャの大半の判断を占める。
4. 「叫ぶアーキテクチャ」という視点
本書の中で印象に残る概念として「叫ぶアーキテクチャ」がある。コードベースのディレクトリ構造や依存関係を見たとき、それがシステムの「機能」(例:受注管理システム、医療記録システム)を叫んでいるか、それともフレームワーク(例:Railsアプリ、Springアプリ)を叫んでいるか、という問いだ。
後者の状態では、ビジネスロジックがフレームワークの都合に埋没しており、本質的な問題領域がコードから読み取りにくい。フレームワークは実装の詳細だ。アーキテクチャの主役ではない。
5. どんな詰まりに効くか
「フレームワークをバージョンアップしたら、業務ロジックのあちこちが動かなくなった」「単体テストのはずなのにDBを立ち上げないと通らず、テストが遅く壊れやすい」——こうした詰まりは、ビジネスルールが技術的詳細に依存してしまっていることに原因があることが多い。本書の依存の方向ルールは、この依存を逆転させ、業務ロジックをフレームワークやDBから切り離すための判断軸を与える。
もう一つは、ディレクトリを開いてもどこに業務の核心があるか分からず、機能追加のたびに影響範囲を読み解くのに時間を奪われる状況だ。「叫ぶアーキテクチャ」と境界線の考え方は、コードの構造そのものに問題領域を語らせ、変更点の見通しを立てやすくする。
6. 読むべき人と、まだ早い人
向いている人:
- 関数・クラス単位の品質は身につけ、システム全体の境界や依存の向きを設計する立場に立ったエンジニア
- フレームワークやDBの都合にビジネスロジックが振り回されている実感があり、その構造的な原因を言葉にしたい中級開発者
- レイヤー分割の「なぜ」をチームで共有し、設計レビューの基準を揃えたいテックリード
向いていない人:
- すぐ使える実装パターンやコード例を求めている人(本書は具体実装より、規模を問わず効く設計思想を扱う)
- プログラミングの基礎や関数・クラス設計をこれから学ぶ人(『Clean Code』相当の土台がないと、原則が抽象的に感じられる)
7. 次に開く本と、最初の一歩
本書で「依存の向き」という軸を得たら、次は境界の内側に置くビジネスロジックそのものの設計へ関心が移る。『ドメイン駆動設計をはじめよう』は、境界づけられたコンテキストやドメインモデルという形で「内側に何を、どう置くか」を具体化する道具立てを与え、本書の同心円に中身を持たせる読み方ができる。アーキテクチャスタイルの選択肢そのものを俯瞰したいなら『ソフトウェアアーキテクチャの基礎』へ進むと、依存管理の原則を、どのスタイルを選ぶかという上位の判断につなげられる。なお本書は『Clean Code』で扱う関数・クラス単位の品質を土台に置いており、そちらが手薄なら先に戻るのが近道だ。
最初の一歩としては、担当プロジェクトのモジュール依存を矢印で図に起こし、「内側から外側へ」向いてしまっている依存を1つ見つけて、インターフェースを挟んで逆転させられないか検討してみるのがよい。
筆者の体験から
「良いコード/悪いコード」で関数・クラス単位のレビュー基準はある程度そろえられたと感じていたリード期でも、機能を一つ足すたびにどこまで影響が及ぶか読めない構造に手を焼いていた。ある業務システムの案件では、フレームワークをマイナーバージョンアップするたびにユースケース層まで書き直す作業が発生し、辿ってみるとユースケースがフレームワークのリクエストオブジェクトをそのまま受け取る作りになっていた。本書の依存の方向ルールを読み、それ以降、ユースケース側は自前のデータ構造だけを受け取り、変換はコントローラに寄せる形に直した。次のバージョンアップで手を入れたのは変換部分だけで済み、「あの作業がまた来る」という憂鬱さが減ったのは実感できた変化だった。もっとも4層の同心円モデルをそのまま持ち込むと、規模の小さい現場では層を跨ぐだけの薄いクラスが増えてかえって見通しが悪くなる場面もあり、層の数は現場の規模で調整するものだと割り切っている。
DevBookPath のマップで確認する
この本の前後の読書順は、DevBookPath のグラフで確認できます。
本記事のリンクには Amazon アソシエイト等の広告が含まれる場合があります。リンク経由の購入で運営者に紹介料が支払われることがあります。
この記事を共有
この地図を共有