はじめに
先日、とあるエンジニアから「設計について教えてほしい」と言われた。ベトナムでエンジニアからこんな話を聞く時が来るなんて、ちょっと感動である。
ただ「設計」といっても範囲はかなり広い。話を聞いてみると、具体的にはソフトウェア内部の構造をどう扱うかを知りたいようだった。
一方で、PO は SRE に近い運用・モニタリング系の設計に関心を寄せており、Tech Lead は「マイクロサービス化すべきか?」といったトポロジー系の設計を検討していた。QA/QC は(Testability が低い構造であることを棚に上げて)「バグが多い」と詰められて悩んでいた。
それぞれが、より良いサービス・マネジメントのために “Architecture” を改善しようとしているのだが、話しているレイヤーがバラバラなので噛み合わない。
設計の議論は、
- Microservices?
- Clean Architecture?
- REST / gRPC / Event-driven?
…と、とっ散らかりがちである。
理由はすでに述べたとおり、「設計・アーキテクチャ」という言葉が、異なる複数のレイヤーの話をまとめて指してしまうからである。
というわけで、一度整理して資料にまとめた。
アーキテクチャの5つのレイヤー
まずは、アーキテクチャの議論が迷子になる最大の要因である「ごちゃまぜ」を、5つのレイヤーに分けて整理する。
1. Structural Styles(アプリ内部構造)
近年の議論では、Hexagonal / Onion / Clean など 依存方向ルール(Dependency Rule) を中核としたスタイルが実務で強く定着し、アプリ内部構造の中心的トピックとして扱われてきた。
2. System Topologies(システム構成・粒度)
モノリスからマイクロサービス、さらにサーバレスやエッジに至るまで、アプリケーションの配置戦略を扱う領域。近年の進化が最も顕著なカテゴリである。
3. Integration Styles(通信・連携方式)
REST、gRPC、Event-driven、Service Mesh など、サービス間通信の方式と統合パターンを扱う。
4. Data & Analytics Architecture(データ構造・分析基盤)
従来の DWH や Data Lake から、CQRS・Event Sourcing による操作分離、Data Mesh による分散責務まで、データ設計の進化を整理している。
5. Cross-cutting & Socio-technical(運用・文化・品質)
DevOps、SRE、Observability、Zero Trust、Team Topologies など、技術基盤だけではなく組織・運用・文化が関わる領域を扱う。
アーキテクチャ議論の歴史的トレンドをざっくりまとめると、
- 依存方向ルールを前提としたスタイルが実務で強く定着した
- これらが 2000〜2010 年代にかけて、アプリ内部構造の主要トピックとして深化した
- 対して近年は、System Topologies や Integration、Data など「より外側のレイヤー」の進化が中心になってきている
といった流れになる。
これら 5 つのレイヤーは対立軸ではなく、組み合わせるものだ。さらにいえば、アプリ内部の Structural Styles の中にも、Data-centric / Layered & Domain / UI / Flow & Pipeline / Microkernel / Reactive & Actor などいくつかの系統があり、こちらも状況に応じて組み合わせる。
まずは「いま、どのレイヤーの話をしているのか」を明確にして議論することが大事になる。
アーキテクチャの選定方法
では、どのように選ぶのか?
「Microservices が流行っているから採用しよう」などと、小さなチームが意思決定すると痛い目にあう。ソフトウェアアーキテクチャは流行ではなく、目的と制約に応じて選択する技術 である。
最初に考えるべき軸として、例えば次のようなものがある。
- 変更容易性(Changeability)
- スケール要求(Scalability)
- データ整合性(Consistency)
これらはそれぞれ、主にヒットするレイヤーが異なる。
これらの要件を 「状況・組織・制約」から逆算して構造を決定する のが、アーキテクチャ選定である。
特定のスタイルに固執するのではなく、どの問題を解決するためにどの構造を選ぶのかを明確にすることが重要である。
こうした話をもう少し体系的にまとめたので、少し早いが年末年始に暇だったら読んでもらえると嬉しい。
フレームワークのアーキテクチャ風味
とはいえ、多くのエンジニアにとって日々の実務や関心事は、担当範囲や与えられた権限の都合上、まず プログラミング言語やフレームワークの選定 であることが多い。
多くのフレームワークは、特定のアーキテクチャスタイルを強制するわけではない が、それぞれに 「こう設計すると自然にしっくりくる」傾向(flavor) が存在する。
例えば、
- Rails は Active Record の思想が強い
- React / SwiftUI は MVU(Elm Architecture)に近い
- Spring Boot / NestJS は Clean / Hexagonal に寄せやすい
- Node.js は Event Loop(非同期 I/O)中心の構造を誘導する
つまり、フレームワークがアーキテクチャを決めるのではなく、フレームワークが自然と誘導する方向性を理解することが重要である。
皆さんの扱うソフトウェアは、何らかのフレームワークを採用しているだろうか? 採用しているのであれば、どうしてそのフレームワークを採用したのだろうか
例えば…
「PHP は学習・教育コストが低く、人材採用も比較的容易である。その中で事例やドキュメントが豊富な Laravel を採用した。」
これは、前述の 5 つのレイヤーで言えば、Cross-cutting & Socio-technical(運用・文化・品質)的な意思決定である。
しかし、「ドメインモデルの分割をしっかりやりたい」という要求があった場合、Eloquent が Active Record 的な Laravel では、実装者の工夫やそれを実現する高い技術力が必要になる。状況によっては微妙な選択かもしれない。
というわけで、モダンなフレームワークのアーキテクチャ風味をざっくりまとめてみる。フレームワークの裏で動いているアーキテクチャ思想を理解することで、身近なフレームワークへの理解を深め、最適な選択への手がかりとなる。
● UI 系フレームワークの Flavor
React
- MVU 系 / Elm Architecture の影響下
- 単方向データフロー、immutability、宣言的 UI
- Redux との組み合わせは MVU 風味をさらに強める
UI 系スタイルの「MVU」の代表例。
Vue.js (3.x)
- Options API は MVVM に近い
- Component(VM)・Template(View)・Service(Logic)
UI 系スタイルの典型例として扱いやすい。
SwiftUI / Jetpack Compose
- 完全に MVU 系
- 単一ソースの状態、再計算、宣言的 UI
近年の Declarative UI の最も純粋な実装。
● Data-centric 系フレームワークの Flavor
Ruby on Rails
- Active Record をコアに据えた典型例
- MVC だが、実質的に Fat Model / Transaction Script になりがち
Data-centric の代表例。
Laravel
- Eloquent が Active Record 的
- 直感的だが、ドメインモデルの分割は開発者の工夫次第
Laravel は Rails と共通して、小規模開発ではスピードが出しやすいが、
- DB テーブル = モデル
- モデル = ビジネスロジックの中心
となりやすいため、Fat Model になりがちで、DDD が入りにくいなど、Active Record の世界観から抜けにくいという点もある。
Django
- MVT(Model-View-Template)で MVC に近い
- ORM は Data Mapper に寄る
Data-centric の中では Table Module / Data Mapper 寄りの代表例。
● Layered / Dependency Rule 系フレームワークの Flavor
Spring Boot
- Clean / Hexagonal を作りやすい構造
- Controller → Service → Repository の分割が自然
- DI による依存方向の制御がやりやすい
Clean Architecture 実装例が最も多いフレームワークのひとつ。
NestJS
- モジュール構造・DI・デコレータが Spring に酷似
- Port / Adapter / UseCase の実装が明確に作れる
Node.js 界の Clean / Hexagonal の代表例。
.NET / ASP.NET Core
- Clean Architecture テンプレートが標準化
- DDD / CQRS / Hexagonal の文献・実例が非常に豊富
Clean / Layered 系の実務標準プラットフォーム。
● Reactive / Actor 系フレームワークの Flavor
Node.js
- Event Loop ベース構造そのもの
- 非同期 I/O、コールバック、Promise、イベント駆動
Event Loop の代表例。
Erlang / Elixir / Akka
- Actor Model のガチ実装
- メッセージパッシング・スーパービジョンが言語レベル
Reactive 系の純粋なサンプル。
● Topologies、Integration 系フレームワークの Flavor
Next.js(App Router)
- Topologies(SSR / Edge)+ Integration(UI + API 統合)寄り
- SSR / SSG / ISR / Edge Rendering など、レンダリング戦略そのものがアーキテクチャを決定する
- API Routes / Route Handlers / Server Actions により、UI と API(バックエンド)が同居する構造
- ファイルベースルーティングにより、機能単位のフォルダ構成が自然に強制される
→ Vertical Slice / Feature-based に近いプロジェクト構成になりやすい
React(MVU)を内包しているが、Next.js 自体は構造アーキテクチャというより、アプリの全体構成(Topology / Integration)を既定する存在。
フレームワークの Flavor まとめ
| 構造スタイル | 代表フレームワーク / 技術 |
|---|---|
| MVU | React / Redux, SwiftUI, Jetpack Compose |
| MVVM | Vue(Options API), Angular |
| MVC / MVT | Rails, Django |
| Active Record | Rails(ActiveRecord), Laravel(Eloquent) |
| Data Mapper 寄り | Django ORM |
| Layered / Clean / Hexagonal | Spring Boot, NestJS, .NET |
| Event Loop | Node.js |
| Actor Model | Erlang / Elixir, Akka |
フレームワークのアーキテクチャ風味を理解すると、「やりたいこと」と「どこで戦うべきか」がかなり明確になる。
例えば、
- React で Clean Architecture したい → UI レイヤーには適している
- Rails で DDD したい → Active Record の制約をどう扱うかがカギ
- Node.js で同期的な重い処理をしたい → Reactive / Event Loop の制約を理解すべき
といった具合に、「フレームワークの誘導」を踏まえたうえで、意図的に設計を選択できるようになる。
おわりに
ソフトウェアアーキテクチャ・設計の学習は、フレームワークよりも抽象度が高いため、難易度が高い。
しかし、
- アーキテクチャは複数レイヤーで構成されるという前提
- フレームワークには Flavor があるという視点
を知ることで、設計の世界はかなりクリアになり、運用上の逸脱も減らすことができる。
なお、プログラミング言語が違う問題
とはいえ、「PHP エンジニアを集めているので Laravel から Spring Boot(Java)に切り替えるのは無理」といった問題に直面することもあるだろう。
ただ、AI が浸透した現代、プログラミング言語の学習コストは以前に比べて著しく下がっている。基本的にはオブジェクト指向という基礎をしっかり理解し、そのうえで今回紹介したような Flavor を理解していれば、言語やフレームワークの切り替えはそこまで大きな問題ではなくなる。
実際、弊社でもさまざまな言語やフレームワークを取り扱っているが、そこが本質的なボトルネックになったことはない。
AI に対する適切なプロンプティングなども含めて考えると、現代の企業が払うべき教育コストや、個人が払うべき学習コストは、特定の言語やフレームワークではなく、よりコアな基礎と「立ち位置を見失わないための俯瞰」に投資すべきである。これが、AI 時代における新しい “Flavor” と言えるのかもしれない。
今回の「ソフトウェアアーキテクチャの地図」は、デザインパターン・チュートリアルの最終章として公開しており、各アーキテクチャスタイルにおいて、それを支えるデザインパターンにも触れている。より深い理解の助けになれば幸いである。
それでは、良いお年を。