【入門】神クラスを作らないためのレイヤードアーキテクチャ
はじめに
アプリケーション開発を学ぶ中で、気づけばすべての処理を1つのクラスに詰め込んでしまう「神クラス(God Class)」を作ってしまった経験はありませんか?
私自身、画面表示、ビジネスロジック、データベースアクセスがすべて混在したコードを書いてしまい、保守が困難になった経験があります。そんな中で出会ったのが「レイヤードアーキテクチャ」という設計手法でした。
この記事では、神クラスを防ぎ、保守しやすいコードを書くために私が学んだレイヤードアーキテクチャの基本概念や実装方法について、自分なりの理解をまとめてみました。同じように勉強中の方の参考になれば幸いです。
レイヤードアーキテクチャとは
レイヤードアーキテクチャ(Layered Architecture)は、ソフトウェアシステムを複数の階層(レイヤー)に分割して構成する設計手法です。各レイヤーは特定の責務を持ち、上位のレイヤーは下位のレイヤーのみに依存するという原則に基づいています。
基本的な構造
一般的なレイヤードアーキテクチャは以下の4層で構成されます。
┌─────────────────────────┐
│ プレゼンテーション層 │ ← UIやAPIエンドポイント
├─────────────────────────┤
│ アプリケーション層 │ ← ビジネスロジックの調整
├─────────────────────────┤
│ ドメイン層 │ ← ビジネスルールの実装
├─────────────────────────┤
│ インフラストラクチャ層 │ ← データベース、外部API等
└─────────────────────────┘
各レイヤーの役割
1. プレゼンテーション層(Presentation Layer)
ユーザーとシステムの接点となる層です。
ビュー層(View Layer)やUI層とも呼ばれます。
責務:
- UIの表示
- ユーザー入力の受け取り
- バリデーション(基本的な形式チェック)
依存関係:
アプリケーション層に依存し、ドメイン層やインフラ層には直接依存しません。
具体例:
- アプリのフォーム画面
2. アプリケーション層(Application Layer)
ビジネスロジックの流れを制御する層です。
ユースケースを実装、ドメインオブジェクトを組み合わせて、一連の処理フローを実現します。
責務:
- ユースケースの実装
- ドメイン層の調整
依存関係:
ドメイン層に依存し、インフラ層には直接依存しません。
上位層(プレゼンテーション層)には依存しません。
具体例:
- ユーザー登録処理
- 注文確定処理
3. ドメイン層(Domain Layer)
ビジネスルールの中核を担う層です。
責務:
- ビジネスロジックの実装
- ドメインモデルの定義
- ビジネスルールの検証
依存関係:
インフラ層に依存します。
上位層(プレゼンテーション層、アプリケーション層)には依存しません。
具体例:
- エンティティ(Entity)
- 値オブジェクト(Value Object)
- ドメインサービス(Domain Service)
4. インフラストラクチャ層(Infrastructure Layer)
技術的な実装を担当する層です。
外部システムとの連携全般を担当します。
責務:
- データベースアクセス
- 外部システムとの連携
依存関係:
ドメイン層のエンティティ(データ構造)に依存します。
ドメイン層のサービスクラスや上位層には依存しません。
具体例:
- リポジトリの実装
- Excel等への出力
- メール送信などの処理
レイヤードアーキテクチャのメリット
1. 関心の分離
各レイヤーが明確な責務を持つため、コードの整理がしやすくなります。
悪い例(レイヤー分けなし):
画面表示のコード、ビジネスロジック、データベースアクセスがすべて1つのクラスに混在している状態。例えば、ボタンクリックのイベントハンドラの中で直接SQLを実行し、その結果を画面に表示するような実装です。
良い例(レイヤー分け):
プレゼンテーション層は画面表示のみを担当し、アプリケーション層がビジネスロジックを調整し、インフラストラクチャ層がデータベースアクセスを担当します。各層が独立しているため、どこに何が書いてあるのかが明確です。
2. 保守性の向上
変更の影響範囲が限定されるため、保守が容易になります。
変更例と影響範囲:
- データベースをMySQLからPostgreSQLに変更 → インフラストラクチャ層のみ修正
- UIをWebからモバイルアプリに変更 → プレゼンテーション層のみ修正
- ビジネスルールの変更(例:消費税率の変更) → ドメイン層のみ修正
このように、変更箇所が特定のレイヤーに限定されるため、他のレイヤーへの影響を最小限に抑えられます。
3. 再利用性
下位レイヤーのコンポーネントを複数の上位レイヤーから利用できます。
具体例:
同じドメイン層とインフラストラクチャ層を、Webアプリケーション、モバイルアプリ、バッチ処理など、複数のプレゼンテーション層から利用することができます。ビジネスロジックを一度実装すれば、異なるインターフェースで再利用できるのです。
デメリット
1. オーバーエンジニアリングのリスク
小規模なアプリケーションでは、レイヤー分けが過剰になる可能性があります。
具体的な問題:
シンプルなCRUD操作(作成・読み取り・更新・削除)だけのアプリケーションで、4層すべてを厳密に分けると、かえってコードが複雑になり開発効率が落ちます。
2. パフォーマンスの懸念
レイヤー間のデータ変換により、パフォーマンスが低下する場合があります。
具体的な問題:
各レイヤーでデータ構造(DTO、エンティティなど)を変換するオーバーヘッドが発生します。特に大量のデータを扱う場合、変換処理がボトルネックになることがあります。
実装のポイント
依存関係のルール
レイヤードアーキテクチャで最も重要なのは、依存関係の方向です。
基本ルール:
- 上位レイヤーは下位レイヤーに依存できる
- 下位レイヤーは上位レイヤーに依存してはいけない
- ただし例外として、インフラ層はドメイン層のエンティティ(データ構造)のみに依存します
依存関係の構造
┌─────────────────────────┐
│ プレゼンテーション層 │
└───────────┬─────────────┘
↓
┌───────────┴─────────────┐
│ アプリケーション層 │
└───────────┬─────────────┘
↓
┌───────────┴─────────────┐
│ ドメイン層 │ ←───────┐
└───────────┬─────────────┘ │
↓ │
┌───────────┴─────────────┐ │
│ インフラストラクチャ層 │ ────────┘
└─────────────────────────┘
双方向の依存
(エンティティのみ例外的に許可)
実例:
基本原則:
プレゼンテーション層はアプリケーション層を呼び出せますが、アプリケーション層はプレゼンテーション層を知りません。これにより、UIを変更してもアプリケーション層に影響を与えずに済みます。
具体的な処理フロー(ユーザー一覧の更新):
-
プレゼンテーション層(UI)
- ユーザーが「リスト更新」ボタンをクリック
- アプリケーション層の
getUserList()を呼び出す - 結果をUI用のDTO(Data Transfer Object)で受け取り、画面に表示
-
アプリケーション層(ユースケース)
-
getUserList()メソッドが呼ばれる - ドメイン層の
UserServiceを使ってユーザー情報を取得 - エンティティをUI用のDTOに変換
- プレゼンテーション層に返却
-
-
ドメイン層(ビジネスロジック)
-
UserServiceがビジネスルールに基づいて処理 - 例:アクティブなユーザーのみ取得する、並び順を制御する
- インフラ層の
UserRepositoryを呼び出してデータ取得 - 取得したエンティティにビジネスロジックを適用(例:ステータス判定)
-
-
インフラストラクチャ層(データアクセス)
-
UserRepositoryがデータベースにアクセス - SQLを実行してユーザー情報を取得
- データベースの結果を
Userエンティティ(ドメイン層のオブジェクト)に変換 - ドメイン層に返却
-
このように、各レイヤーが明確な責務を持ち、上位レイヤーのみが下位レイヤーを知ることで、変更の影響範囲を限定できます。
おわりに
レイヤードアーキテクチャについて、私が学んだことをまとめてきました。
主なポイント:
- 各レイヤーが明確な責務を持つ
- 上位レイヤーは下位レイヤーにのみ依存する(例外あり)
- 保守性と再利用性が向上する
- プロジェクトの規模に応じて適用する
レイヤードアーキテクチャは万能ではありませんが、コードを整理し保守しやすくするための基本的な考え方として、とても役立つ設計手法だと感じました。
特に、すべての処理を1つのクラスに詰め込んでしまう「神クラス(God Class)」を防ぐために効果的だと思います。
また、レイヤードアーキテクチャの発展形として、
クリーンアーキテクチャ(依存性逆転の原則でドメイン層を独立させる)やドメイン駆動設計(DDD)(ビジネスの概念をコードに反映)といった手法があることも知りました。
私もまだ学習中ですが、まずはレイヤードアーキテクチャの基本をしっかり身につけることが、これらの発展的な手法を理解する土台になると思っています。同じように勉強中の方の参考になれば幸いです。