クリーンアーキテクチャ入門——ECサイトで学ぶ4層構造と依存関係の本質
投稿
X LINE B! f

クリーンアーキテクチャ入門——ECサイトで学ぶ4層構造と依存関係の本質

なぜ「クリーンアーキテクチャ」が必要なのか

ソフトウェア開発の現場で長年働いていると、こんな場面に何度も出くわします。「このシステム、DBをMySQLからPostgreSQLに移行したいんだけど、どこを直せばいいかわからない」「フレームワークを新しいバージョンに上げたら、ビジネスロジックまで壊れた」——こういった悩みの根本には、ほぼ必ずといっていいほど「依存関係の混乱」があります。

クリーンアーキテクチャは、Robert C. Martin(通称 Uncle Bob)が2012年に提唱した設計思想です。MVCやレイヤードアーキテクチャなど、それまで存在していた設計パターンの良いところを統合し、「ビジネスロジックを技術的な詳細から守る」ことを最優先に据えた考え方です。20年以上システム開発に携わってきた筆者も、この思想と出会ってからは設計の悩みが大幅に減りました。本記事ではECサイトを例に、クリーンアーキテクチャの本質を丁寧に解説します。

クリーンアーキテクチャの全体像

同心円で表現される4つの層

クリーンアーキテクチャは、よく同心円(玉ねぎ)の図で表現されます。内側から順に、Entities層・Use Cases層・Interface Adapters層・Frameworks & Drivers層という4つの層で構成されています。この構造で最も重要なルールは「依存の方向は常に内側へ」という一点です。

外側の層は内側の層を知っていても構いませんが、内側の層は外側の層を一切知ってはいけません。たとえば、ビジネスロジックを担うEntities層は、DBが何であるか、Webフレームワークが何であるかを知らなくていいのです。これを徹底することで、技術的な変更がビジネスロジックに波及しない、変更に強いシステムが生まれます。

各層の役割まとめ

別名主な役割ECサイトの例
Entitiesエンティティ層不変のビジネスルール注文・商品・顧客のルール
Use Casesユースケース層アプリ固有の処理手順注文確定・キャンセル処理
Interface Adaptersインターフェース層内外のデータ変換ControllerやRepositoryの実装
Frameworks & Driversフレームワーク層技術的な詳細MySQL・Stripe・メール送信

Entities層——変わらないビジネスルールの核心

この層が守るものとは

Entities層は、システムの存在意義そのものを表す場所です。ECサイトであれば「注文には未確定・確定・キャンセルというステータスがある」「確定済みの注文はキャンセルできない」「注文金額は明細の合計である」といったルールがここに入ります。

これらのルールは、DBがMySQLだろうとPostgreSQLだろうと、フレームワークがLaravelだろうとSymfonyだろうと、一切変わりません。だからこそEntities層は外部の何にも依存せず、最も安定した場所として機能するのです。

ECサイトのEntities設計

ECサイトの注文まわりで洗い出せるクラスは以下のようになります。

  • Order(注文)——集約の中心。確定・キャンセルなどのルールを持つ
  • OrderItem(注文明細)——商品1行分の情報と小計計算
  • OrderId(注文ID)——単なる文字列ではなく「注文IDである」という意味を持つ値オブジェクト
  • OrderStatus(注文ステータス)——pending・confirmed・cancelledの状態と遷移ルール
  • Price(金額)——0円以下にはなれないというルールを持つ値オブジェクト

重要なのは、これらのクラスがDBへの保存処理やHTTPリクエストの処理を一切持たないことです。「ビジネス担当者が使う言葉をそのままクラスにする」という原則を守ることで、技術者とビジネス担当者が同じ言語で会話できるようになります。これはDDDのユビキタス言語の概念とも深くつながっています。

Use Cases層——「このシステムで何ができるか」を定義する

ユースケースの粒度

Use Cases層は、アプリケーションとして何ができるかを定義する場所です。「注文を確定する」「注文をキャンセルする」「商品を検索する」——1つのユースケースクラスが1つの操作に対応するのが基本です。

ここで重要なのは、ユースケースはEntities層のルールを使いながら処理の「手順」を記述するという役割分担です。DBの具体的な操作方法は知らず、「リポジトリインターフェース越しに保存して」と指示するだけです。これが後述する依存性逆転の原則につながります。

依存性逆転の原則(DIP)

クリーンアーキテクチャで最も理解しにくいのが、依存性逆転の原則(Dependency Inversion Principle)です。Use Cases層がDBに保存したいとき、直接DB実装クラスに依存するのではなく、インターフェース(抽象)を定義して外側がそれを実装する形を取ります。

この構造により、PlaceOrderUseCaseはMySQLのことを何も知りません。DBをPostgreSQLに変えたいなら、MySQLOrderRepositoryを差し替えるだけでよく、ユースケース層は一切変更不要です。20年以上の実務経験を通じて感じることですが、この「差し替えやすさ」が長期運用プロジェクトでは圧倒的な価値を生みます。

Interface Adapters層——翻訳係としての役割

なぜ翻訳が必要か

HTTPリクエストのJSONと、ドメインオブジェクトの形式は異なります。またDBのテーブル構造と、ビジネスルールを持つEntityの構造も異なります。この変換を担うのがInterface Adapters層です。

ここにControllerやPresenter、Repositoryの実装などが入ります。この層があることで、内側の層(EntitiesやUse Cases)は「外の世界がどんな形式でデータを送ってくるか」を気にせずに済みます。

ECサイトでの変換の流れ

お客さんが「注文する」ボタンを押すと、以下のような流れでデータが変換されながら処理されます。

  1. HTTPリクエストのJSONを受け取る(Frameworks層)
  2. JSONをPlaceOrderInputというDTOに変換(Interface Adapters層)
  3. ユースケースが処理を実行(Use Cases層)
  4. Orderエンティティのルールが判定(Entities層)
  5. DBに保存(Frameworks層)
  6. 結果をJSONに変換してレスポンス(Interface Adapters層)

各層が自分の責務だけを担い、隣の層との窓口となる変換処理だけを行うことで、全体が疎結合に保たれます。

Frameworks & Drivers層——技術的詳細をここに閉じ込める

最も変わりやすい場所

Frameworks & Drivers層は、MySQL・Stripe・SendGridといったDB・外部API・Webフレームワーク本体が入る場所です。最も変わりやすく、最も外側に位置します。

重要なのは、この層の変更が内側に波及しないことです。MySQLをPostgreSQLに変えてもEntities層は壊れない。決済をStripeからPayPalに変えてもUse Cases層は壊れない。この「変更の局所化」こそがクリーンアーキテクチャを採用する最大のメリットです。

MVCとクリーンアーキテクチャの違い

視点が根本的に異なる

LaravelやDjangoといったMVCフレームワークを使い慣れている方は「MVCとどう違うの?」と感じるかもしれません。両者は対立するものではなく、視点が異なります。

観点MVCクリーンアーキテクチャ
主な関心事画面・入力・データの分離ビジネスロジックの保護
Modelの位置づけDBと密結合しやすい純粋なビジネスルール
テストのしやすさDBなしでは難しいDBなしで単体テスト可能
向いている規模小〜中規模中〜大規模・複雑なロジック

MVCのModelはビジネスロジック・DB操作・メール送信などが混在する「Fat Model」になりがちです。クリーンアーキテクチャはその課題への一つの答えであり、MVCのController部分をクリーンアーキテクチャのFrameworks層に位置づけて共存させることもできます。

クリーンアーキテクチャを採用すべきケース・避けるべきケース

どんなシステムにでもクリーンアーキテクチャを適用すべきかというと、答えはNOです。シンプルなCRUDが中心の管理画面などに適用すると、不必要にコード量が増えてチームの負担になります。

採用を検討すべき状況は以下のとおりです。

  • ビジネスルールが複雑で、今後も変化が予想されるシステム
  • 長期間(3年以上)保守・拡張が必要なプロジェクト
  • チームが複数に分かれて並行開発する場合
  • DBやフレームワークを将来的に変更する可能性がある場合

逆に、プロトタイプや短命なシステム、CRUDのみのシンプルな管理ツールには過剰設計になりがちです。設計の選択は「今のシステムに何が必要か」を見極めることが前提です。

まとめ

クリーンアーキテクチャは「依存の方向を内側に保つ」というたった一つのルールから出発します。それがEntities・Use Cases・Interface Adapters・Frameworksという4層の構造に結実し、変更に強く・テストしやすく・長期間保守できるシステムを生み出します。

最初は「コードが増えて面倒」と感じるかもしれません。しかし3年後・5年後にシステムが成長したとき、この設計が意味を持ちます。「DBを変えたいけどビジネスロジックに触れたくない」「新機能を追加したいけど既存コードを壊したくない」——そんな悩みへの根本的な答えが、クリーンアーキテクチャには込められています。