レイヤードアーキテクチャとは、アプリケーションを役割ごとの層に分け、責務と依存関係を整理する基本的な設計方法です。
一言でいうと
レイヤードアーキテクチャは「画面、処理、業務ルール、保存」を混ぜないための整理法です。
代表的には、プレゼンテーション層、アプリケーション層、ドメイン層、インフラ層に分けます。
代表的な層
| 層 | 主な責務 | 例 |
|---|---|---|
| プレゼンテーション層 | 入出力、画面、HTTP | Controller、View、API Route |
| アプリケーション層 | ユースケースの進行 | RegisterUser、CreateOrder |
| ドメイン層 | 業務ルール | Entity、Value Object、Domain Service |
| インフラ層 | 技術詳細 | DB、外部API、メール、ファイル |
層を分ける目的は、ファイルを増やすことではありません。変更理由の違うコードを混ぜないことです。
処理の流れ
ユーザー登録を例にします。
| 順番 | 層 | 処理 |
|---|---|---|
| 1 | プレゼンテーション | HTTPリクエストを受け取る |
| 2 | アプリケーション | 登録ユースケースを開始する |
| 3 | ドメイン | メール形式や重複ルールを確認する |
| 4 | インフラ | DBに保存する |
| 5 | プレゼンテーション | レスポンスを返す |
Controllerが直接DBへ保存し、同時に業務ルールも判断している場合、層の役割が混ざっています。
依存方向
素朴なレイヤード設計では、上の層が下の層を呼びます。
Presentation
-> Application
-> Domain
-> Infrastructure
ただし、ドメイン層がインフラ層に依存すると、業務ルールがDB都合に引っ張られます。大きなアプリでは、Repositoryのインターフェースを内側に置き、実装をインフラ層に置く形がよく使われます。
よくある失敗
Controllerが太る
Controllerにバリデーション、業務判断、DB保存、レスポンス整形を全部書くと、テストも変更も難しくなります。Controllerは入力を受け、ユースケースへ渡す役割に寄せます。
Serviceが何でも屋になる
UserService のような名前で全処理を集めると、層を分けた意味が薄れます。ユースケース単位で名前を付けると責務が見えやすくなります。
層をまたいだショートカットが増える
画面からDBへ直接アクセスする、ドメインからHTTPクライアントを呼ぶ、といったショートカットは依存関係を読みにくくします。
小さく始める形
小さなWebアプリでは、最初から複雑な構成にする必要はありません。
| 規模 | 現実的な分け方 |
|---|---|
| 小さい | Controller / UseCase / Repository |
| 中くらい | Presentation / Application / Domain / Infrastructure |
| 大きい | Bounded Contextごとに層を分ける |
最初は「HTTPを受ける場所」「ユースケース」「DBアクセス」を分けるだけでも効果があります。
チェックリスト
- Controllerに業務ルールが増えすぎていないか
- DBアクセスがあちこちに散らばっていないか
- ユースケース名が操作の目的を表しているか
- ドメイン層がHTTPやDBの型を知っていないか
- 層を増やしたことで逆に読みにくくなっていないか
まとめ
レイヤードアーキテクチャは、設計の基本形です。複雑な概念に見えますが、出発点は「役割の違うコードを混ぜない」ことです。
層の名前より、どの変更がどこに閉じ込められるかを意識することが重要です。
参考リソース
- Martin Fowler: PresentationDomainDataLayering
- Microsoft: Common web application architectures
- Microsoft: Architectural principles