レイヤードアーキテクチャ
プレゼンテーション・ビジネスロジック・データアクセスなど層に分けてシステムを構成するレイヤードアーキテクチャの原則を学ぶ
レイヤードアーキテクチャとは
レイヤードアーキテクチャは、システムを役割ごとの「層(レイヤー)」に 水平に分割する、最も古典的で広く使われているアーキテクチャパターンです。それぞれの層は特定の関心事だけを 担当し、隣接する層とだけやり取りします。
目的は関心の分離です。「画面の表示方法」と「ビジネスルール」と 「データの永続化方法」を1つのクラスに混在させると、どれか1つを変更したいだけなのに全体を読み解く必要が 出てきます。層を分けることで、変更の影響範囲を局所化できます。
典型的な4層構成
層の数や名前は文献によって異なりますが、代表的には次の4層に分けられます。
+-------------------------------------+
| 1. Presentation Layer |
+-------------------------------------+
| 2. Application Layer |
+-------------------------------------+
| 3. Domain Layer |
+-------------------------------------+
| 4. Infrastructure Layer |
+-------------------------------------+
depends on (top -> bottom, one direction only)1. Presentation Layer(プレゼンテーション層)
画面表示・APIハンドラなど、外部との入出力を担当
2. Application Layer(アプリケーション層)
ユースケースの処理フローを組み立てる
3. Domain Layer(ドメイン層)
ビジネスルールそのものを表現する中核
4. Infrastructure Layer(インフラ層)
DBアクセス・外部API呼び出しなど技術的な実現手段
依存の向きのルール
レイヤードアーキテクチャの核となるルールは単純です。上位層は下位層を呼び出せるが、 下位層は上位層のことを一切知らない、という一方向の依存です。
擬似コードで表すと次のような呼び出し関係になります。
// OK: 上位層 -> 下位層
function PresentationHandler(request):
result = ApplicationService.execute(request)
return renderResponse(result)
function ApplicationService.execute(input):
entity = DomainRule.apply(input)
InfrastructureRepository.save(entity)
// NG: 下位層 -> 上位層への逆依存
function InfrastructureRepository.save(entity):
PresentationHandler.notifyUser(entity) // 違反: 下位層が上位層を知っているこの逆依存が発生すると、Infrastructure層の変更がPresentation層に波及したり、 Infrastructure層を単体でテストできなくなったりします。
メリットとトレードオフ
レイヤードアーキテクチャは万能ではなく、次のようなメリットと代償を天秤にかけて採用します。
メリット
- • 変更の影響範囲が層の中に留まりやすい
- • 新しいメンバーが「どこに何を書くか」を理解しやすい
- • 各層を独立してテストしやすい
代償・注意点
- • 単純な処理でも複数層を経由し、記述量が増えやすい
- • 層の分け方が曖昧だと、Domain層が薄い「anemic」な構造になりやすい
- • 小規模プロジェクトでは過剰設計になりうる
ポイント
- レイヤードアーキテクチャは責任ごとに層を分け、上位層→下位層への一方向の依存を保つ
- 典型的にはPresentation / Application / Domain / Infrastructureの4層に分けられる
- 層を分ける恩恵と、間接参照が増えるコストはトレードオフであり、規模に応じて粒度を調整する
確認クイズ
1 / 3レイヤードアーキテクチャで「上位層は下位層に依存し、下位層は上位層を知らない」というルールを破っている状態はどれか?