=============================================
Webアプリケーションのアーキテクチャは、時代とともに構造が整理されてきた。
本記事では、その変遷をJavaの技術スタックを軸に、2層構造(Model 1)からMVCパターン(Model 2)、レイヤードアーキテクチャ、そしてヘキサゴナルアーキテクチャ・クリーンアーキテクチャに至るまでの流れを図解して整理する。
本記事では、以下の流れでアーキテクチャの変遷を追っていく。
各構造は「前の構造の課題を解決するために生まれた」という因果関係でつながっている。
#アーキテクチャ概要前の構造の課題1Model 1(JSP中心)JSPが表示・ロジック・画面遷移をすべて担う構造―2Model 2 / MVCパターンServlet(Controller)・JSP(View)・JavaBean(Model)に役割を分離Model 1の密結合3伝統的レイヤードアーキテクチャService・DAO・DTO等で層を分割Modelの肥大化(Fat Model)4エヴァンス本初期提唱時のレイヤードアーキテクチャドメイン層を独立させた4層構造Serviceの肥大化(Fat Service)5DIP適用レイヤードアーキテクチャドメイン層がインフラ層に依存しない構造ドメイン層がインフラの影響を受ける6ヘキサゴナルアーキテクチャポートとアダプターで外部との接点を抽象化層の上下関係に縛られた構造の限界7オニオンアーキテクチャ同心円状の層でドメインを中心に保護する構造ポート/アダプターの層構造が未整理8クリーンアーキテクチャ同心円状の依存ルールでアーキテクチャを統合的に整理各アーキテクチャの思想の統合以降、各構造を順に詳しく見ていく。
Webシステムの黎明期に主流だった構造。JSPがリクエストの受付・ビジネスロジック・画面表示をすべて担っており、プレゼンテーションとロジックが密結合していた。そのため、UIを変更するとビジネスロジックも影響を受けるなど、変更に弱い構造であった。

MVCはModel-View-Controllerの略で、ビジネスロジック(Model)、ユーザーインターフェース(View)、制御ロジック(Controller)を分離するアーキテクチャパターン。これにより、変更に強い構造となる。
2層の課題を解決する為、3層構造が普及し始めた
Web開発ではMVCと3層構造が組み合わされることが多い
ここでは、3層構造とMVCパターンの組み合わせで提示している

上述の様に3層、MVCパターン採用時は、Modelが肥大化していた。当時はModelがデータもビジネスロジックもDB操作も指してしまっていた。バリデーションルールもアーキテクチャとしては明確ではなく、Controllerで入力値のフォーマットチェック、Modelで業務ロジックのチェックを行うなど、責務の境界が曖昧であった。
この時代のレイヤードは「データアクセス層」に依存するアーキテクチャであった。
DBテーブル設計を最初に行い、テーブルと対になるEntityを定義し、EntityをDAOからServiceに渡して、業務ロジックに合う形でEntityからDTOに加工してViewに渡す流れであった。
MVCパターンで課題であったFat Model(モデルの肥大化)は解決できた。但し、業務ロジックがServiceに集中しすぎてしまい、Fat ModelがFat Serviceに変化し得るという面もあった。
バリデーションの配置について、個人的経験では役割に応じたValidatorクラスを定義して整理していたプロジェクトもあった。ただし、これはプロジェクト固有の工夫であり、アーキテクチャとして標準化されたものではなかった。

伝統的レイヤードアーキテクチャでは、業務ロジックがService層に集中し、Fat Serviceが課題となっていた。これは、Serviceが「ユースケースの調整(トランザクション管理、処理の順序制御など)」と「純粋な業務ルール(計算、判定、状態遷移など)」の両方を担っていたことに起因する。
エヴァンスが提唱したDDD(領域駆動設計)では、この2つの責務を明確に分離した。Application層はユースケースの調整役に徹し、Domain層に純粋な業務ルールを凝集させる。これにより、Serviceは薄くなり、業務ルールはドメインオブジェクト(Entity、Value Object等)に閉じ込められるため、Fat Serviceが解消される。
この考え方に基づき、以下の4層構造が提案された

エヴァンス本初期提唱時のレイヤードアーキテクチャでは、ドメイン中心で考えるべき「ドメイン層」がインフラの影響を受けてしまう課題があった。これを解決するために考えられたのが、DIPを適用したアーキテクチャである。
「ドメインを技術基盤(Infra)から完全に独立させる」スタイルである。
ドメイン層にRepositoryという名のインターフェースを置き、インフラ層にそのインターフェースをimplementsした実装クラス(SQL発行など)を置く。
これにより「依存性の逆転(DIP)」が起き、インフラ層がドメイン層に依存する構造となり、DDDの理想の形が実現される

DIP適用レイヤードアーキテクチャでは、ドメインをインフラから独立させることに成功した。しかし、依然として「上位層→下位層」という層の上下関係が前提にあり、外部との接点が「上(UI)」と「下(DB)」に固定的に捉えられがちであった。実際のシステムでは、外部APIの呼び出し、メッセージキュー、バッチ起動など、UIやDBに収まらない多様な入出力が存在する。
アリスター・コーバーンが提唱したヘキサゴナルアーキテクチャ(別名:Ports and Adapters)は、この課題に対して「層の上下」という概念自体を捨て、アプリケーションの中心にドメインを置き、外部とのすべての接点を「ポート(インターフェース)」と「アダプター(実装)」で抽象化する構造である。
ポートには2種類ある。
この構造により、ドメインは入出力の技術的詳細を一切知らず、ポートを差し替えるだけでUIをWebからCLIに変更したり、DBをRDBからNoSQLに変更したりすることが可能となる。DIP適用レイヤードアーキテクチャで実現した「ドメインの独立」を、層の上下関係に縛られない、より汎用的な形で表現したアーキテクチャである。

ヘキサゴナルアーキテクチャの構造を、引き続き「レストランの経営」を例に理解を深めてみる。
レイヤードアーキテクチャは「上(お客さん)→ 下(厨房・倉庫)」という縦の階層構造であった。しかし実際のレストランには、お客さんやDB(倉庫)以外にも、Uber Eatsの配達員、食材の仕入れ業者、予約サイト、電話注文など、多様な外部との接点が存在する。これらを「上」と「下」に無理やり分類するのは不自然である。
ヘキサゴナルアーキテクチャは、この「上下」の概念を捨て、レストランの中心にキッチン(アプリケーション)を置き、外部とのすべての接点を「窓口のルール(ポート)」と「窓口の担当者(アダプター)」で整理する。
ヘキサゴナルアーキテクチャ(別名:ポート&アダプター)の最大の特徴は、「ビジネスの核心(レシピと調理)」を「外部の手段(注文方法や仕入れ先)」から完全に切り離すことにあります。
六角形の中心にあるのは、お店の価値そのものであるレシピです。
役割: 「ハンバーグには肉を200g使う」「焼き時間は5分」といった、ビジネス上の絶対的なルールを定義します。
ポイント: レシピは紙に書かれた純粋な手順書です。電話で注文が来ようが、ネット予約だろうが、レシピの内容(ビジネスルール)は変わりません。
レシピを熟知し、実際に料理を完成させる司令塔です。
役割: 「注文票を受け取る」→「レシピ通りに焼く」→「お皿に盛り付ける」という一連の作業(ユースケース)を遂行します。
ポイント: シェフは「誰が注文したか(UI)」や「どこの肉屋から届いたか(DB)」の詳細は気にしません。目の前の「注文票(ポート)」に従って動きます。
図にある「点線の枠」です。中(シェフ)と外(店員や業者)をつなぐ標準的な窓口(インターフェース)です。
ドライビングポート(入力側): 「標準注文票」。店員もアプリも、この形式でシェフに注文を伝えなければなりません。
ドリブンポート(出力側): 「食材発注書」。シェフが「肉が欲しい」と叫ぶための決まったルールです。
図にある「外側の箱」です。特定の技術や道具を使って、ポートとやり取りするための翻訳機です。
ドライビングアダプター(入力側)
店員: お客さんの「声」を「標準注文票」に書き換えます。
モバイルアプリ: 「タップ操作」を「標準注文票」データに変換します。
ドリブンアダプター(出力側)
精肉店 (RDB): シェフの発注書を受け取り、冷蔵庫(データベース)から肉を取り出します。
野菜市場 (外部API): 発注書を受け取り、外部の市場から野菜を調達します。
この設計のメリット
ポイント:「窓口のルール」を差し替えるだけで外部が変わる
この構造の最大の利点は、キッチン(アプリケーション)は窓口のルール(ポート)だけを知っていればよいという点である。
レイヤードアーキテクチャでは「上(UI)」と「下(DB)」に固定されていた外部との接点が、ヘキサゴナルアーキテクチャでは六角形の各辺にポートを自由に配置できる。これにより、入出力の種類がいくら増えても、キッチン(アプリケーション)は一切影響を受けない構造が実現される。
ヘキサゴナルアーキテクチャは「層の上下」を捨て、ポートとアダプターで外部との接点を抽象化した。しかし、アプリケーション内部の層構造(ドメイン層、アプリケーションサービス層、インフラ層など)をどう整理するかについては明確な指針を示していなかった。
ジェフリー・パレルモが提唱したオニオンアーキテクチャは、ヘキサゴナルアーキテクチャの「ドメインを中心に据える」思想を受け継ぎつつ、アプリケーション内部の層を同心円状に整理した構造である。玉ねぎの皮のように、内側から外側へ向かって層が重なる。
同心円は内側から以下の順で構成される。
依存のルールはヘキサゴナルアーキテクチャと同様に「外側から内側へ」のみ許可される。ヘキサゴナルアーキテクチャが「外部との接点をどう扱うか」に焦点を当てたのに対し、オニオンアーキテクチャは「アプリケーション内部の層をどう分割するか」を明確にした点に意義がある。

オニオンアーキテクチャの構造を、引き続き「レストランの経営」を例に理解を深めてみる。
ヘキサゴナルアーキテクチャでは、六角形の内側を「アプリケーション」としてひとまとめに扱い、外部との境界をどう扱うかに焦点を当てていた。しかし、「キッチンの中をどう組織するか」については明確な指針がなかった。
オニオンアーキテクチャは、このキッチンの内部を玉ねぎの皮のように同心円状に整理する。中心に最も大事なものを置き、外側に向かって「変わりやすいもの」を配置していく。
同心円をレストランで例えると
オニオンの層(内側→外側) / レストランの例え / 説明
ヘキサゴナルとの違い:「キッチンの中」を整理した
ヘキサゴナルアーキテクチャでは「キッチン全体」と「外の世界」の境界に注目していた。オニオンアーキテクチャは、そのキッチンの中をさらに整理し、「レシピ(Domain Model)」「調理ルール(Domain Services)」「料理長の段取り(Application Services)」という層に分けた。
これにより、以下のことが明確になる。
ヘキサゴナルアーキテクチャが「キッチンと外の世界の境界をどう扱うか」を解決したのに対し、オニオンアーキテクチャは「キッチンの中をどう組織するか」を明確にしたアーキテクチャである。

ヘキサゴナルアーキテクチャ、オニオンアーキテクチャ、DIP適用レイヤードアーキテクチャは、いずれも「ドメインを中心に据え、外部の詳細から独立させる」という同じ思想を持っていた。しかし、これらは別々の文脈で提唱されたため、用語や構造の表現が異なり、統一的な理解が難しかった。
ロバート・C・マーティン(Uncle Bob)が提唱したクリーンアーキテクチャ(Clean Architecture)は、これらの思想を統合し、同心円状の図で依存ルールを明確にしたものである。
中心となるルールは1つだけである。「依存の方向は常に外側から内側へ向かう。内側の円は外側の円について何も知らない」。
同心円は内側から以下の順で構成される。
クリーンアーキテクチャは新しいアーキテクチャパターンを発明したというよりも、既存の「ドメイン中心」のアーキテクチャ群が共有していた本質的なルール(依存は外から内へ)を、統一的かつ視覚的に整理したものと捉えるのが適切である。
一言でいうと、「大事なもの(ビジネスルール)を中心に置いて、外側の都合に振り回されないようにする設計の考え方」です。

同心円図だけでは「実際の処理がどう流れるのか」が分かりにくいので、処理フローも追記する。
Controller(インターフェースアダプター層)がInput Port(ユースケース層のインターフェース)を呼び出し、Use Case Interactor(ユースケース層の実体である実装クラス)が業務ロジックを実行する。結果はOutput Port(ユースケース層のインターフェース)を通じてPresenter(インターフェースアダプター層)に渡される。
ここで重要なのは、PresenterはOutput Portを実装(implements)する側であるという点である。つまり、インターフェースアダプター層がユースケース層のインターフェースに依存しており、依存性の逆転(DIP)が適用されている。これにより、ユースケース層は外側の層について何も知らないという依存ルールが守られる。

クリーンアーキテクチャの構造を「レストランの経営」を例に示しながら理解を深めてみる。
一番内側:Entities(レシピ・味の基準)
2番目:Use Cases(注文〜提供の流れ)
3番目:Interface Adapters(ホールスタッフ・伝票システム)
一番外側:Frameworks & Drivers(店舗・食券機・Uber Eats)
処理フローをレストランで例えると
クリーンアーキテクチャの登場人物 / レストランの例え / 役割
処理の流れ:
ここでのポイントは、料理長(Use Case Interactor)はホールスタッフ(Controller)や盛り付け担当(Presenter)が誰であるかを知らないという点である。料理長は「注文受付窓口のルール」と「料理の受け渡しルール」というインターフェースだけを知っている。そのため、ホールスタッフがアルバイトからベテランに交代しても、配膳方法がテーブルサービスからカウンター受け取りに変わっても、料理長の仕事は一切変わらない。これが依存性の逆転(DIP)の効果であり、クリーンアーキテクチャの「内側は外側を知らない」というルールの本質である。

なぜ嬉しいのか?
メリット / レストランの例
クリーンアーキテクチャは、DIP適用レイヤード・ヘキサゴナル・オニオンの思想を統合したものである。しかし「結局何が違うの?」という疑問は残りやすい。ここでは、レストランの例を使って4つのアーキテクチャの違いを整理する。
DIP適用レイヤードアーキテクチャとの違い
DIP適用レイヤードアーキテクチャは、「レストランの縦の指揮系統を整理した」構造である。
クリーンアーキテクチャとの違いは以下の通り。
DIP適用レイヤードは「縦の指揮系統の中で依存を逆転させた」のに対し、クリーンアーキテクチャは「縦横の概念を捨て、レシピを中心に全方位を整理した」構造である。
ヘキサゴナルアーキテクチャとの違い
ヘキサゴナルアーキテクチャは、「レストランと外の世界の境界線を整理した」構造である。
クリーンアーキテクチャとの違いは以下の通り。
ヘキサゴナルが「レストランの外壁と窓口の設計図」だとすれば、クリーンアーキテクチャは「外壁・窓口に加えて、キッチン内部の組織図まで含めた総合設計図」である。
オニオンアーキテクチャとの違い
オニオンアーキテクチャは、「キッチンの内部を同心円状に整理した」構造であり、クリーンアーキテクチャと最も似ている。
では何が違うのか?
オニオンアーキテクチャが「キッチン内部の層を整理した」のに対し、クリーンアーキテクチャは「層の整理に加えて、注文の受け渡し方(Input Port / Output Port)や、ホールスタッフ・盛り付け担当(Interface Adapters)の役割まで具体的に定義した」構造である。
4つのアーキテクチャの関係を一言で
レストランの設計に例えると、4つのアーキテクチャは以下のように段階的に整理が進んだものである。
クリーンアーキテクチャは「新しい料理法の発明」ではなく、「先人たちが試行錯誤してきたキッチン設計のベストプラクティスを、一枚の設計図にまとめたもの」と理解するのが最も正確である。
クリーンアーキテクチャは「新発明」ではなく、ヘキサゴナルアーキテクチャやオニオンアーキテクチャが共有していた「大事なものを中心に、外側の都合から守る」という思想を、同心円の図と「依存は外から内へ」というシンプルなルールで統一的に整理したものです。
本記事で扱った8つのアーキテクチャは、すべて「前の構造の課題を解決するために生まれた」という因果関係でつながっている。以下の比較表で全体を俯瞰する。
#アーキテクチャ何が課題だったかどう解決したか依存の方向1Model 1(JSP中心)―JSPが全部やる(表示もロジックも)分離なし2MVC(Model 2)表示とロジックが密結合Controller・View・Modelに役割を分離Controller → Model → View3伝統的レイヤードModelが肥大化(Fat Model)Service・DAO・DTO等で層を分割上位層 → 下位層(一方向)4エヴァンス本レイヤードServiceが肥大化(Fat Service)Domain層を独立させ、業務ルールをドメインオブジェクトに凝集上位層 → 下位層(一方向)5DIP適用レイヤードドメイン層がインフラに依存Repositoryインターフェースで依存性を逆転インフラ層 → ドメイン層(逆転)6ヘキサゴナル層の上下関係に縛られるポートとアダプターで外部との接点を抽象化外側 → 内側7オニオンアプリ内部の層構造が未整理同心円状にDomain Model・Domain Services・Application Services・Infraを整理外側 → 内側8クリーン各アーキテクチャの思想がバラバラ既存の思想を統合し「依存は外から内へ」のルールで統一外側 → 内側
本記事ではレストランの経営を例に各アーキテクチャを説明した。最後に、レストランの登場人物がどのアーキテクチャのどの要素に対応するかを整理する。
レストランの登場人物 / 対応するアーキテクチャの要素 / 役割
8つのアーキテクチャを見てきたが、変遷を通じて一貫しているメッセージは1つである。
「大事なもの(ビジネスルール)を中心に置いて、変わりやすいもの(UI・DB・外部サービス等)の都合に振り回されないようにする」
Model 1の時代は全部が混ざっていた。MVCで役割を分け、レイヤードで層を分け、DDDでドメインを独立させ、ヘキサゴナルで上下の概念を捨て、クリーンアーキテクチャで思想を統一した。アプローチは異なるが、目指しているゴールは同じである。
「なぜこのアーキテクチャが提唱されたのか」という点に着目する事で、現在提唱されているアーキテクチャを理解する一歩に繋がるかと思う
What's Hexagonal Architecture?
原文出處:https://qiita.com/yut-nagase/items/21703af242e7ebfc37a9