🦉

フクロウと学ぶアーキテクチャ #1 ─ レイヤードアーキテクチャ入門

に公開

※本記事は個人の知見と学習の記録であり、所属組織の見解を代表するものではありません。

🦉フクロウと学ぶアーキテクチャ #1

レイヤードアーキテクチャ ─ いちばん素朴で、いちばん残っている基本形

ソフトウェアアーキテクチャの旅。その最初のステップは レイヤードアーキテクチャ(Layered / N-Tier) です。
本記事では概念を学びつつ、あわせて GitHub に用意した最小構成サンプル を使って体験できるようにしています。

👉 サンプルコード(Python / 最小レイヤード構成)
https://github.com/naokky-tech/sample-architecture-journey

歴史が長く、いまでも多くのフレームワークが採用する「基本の地図」。
AI エージェント時代の複雑な設計に進む前に、この“素朴な型”を体で理解しておくと迷子になりにくくなります。


🏛️ レイヤードアーキテクチャとは?

レイヤードとは、その名の通り 責務ごとに層(Layer)を積み重ねる構造 です。
代表的には次の4層で表現されます。

  • Presentation Layer(UI / Controller)
  • Application Layer(ユースケース・アプリの振る舞い)

    ※実装では「サービス層が肥大化する」ケースが多いですが、本記事では ユースケースに特化した“薄いアプリケーション層” という整理で統一します。

  • Domain Layer(ビジネスロジック・エンティティ)
  • Infrastructure Layer(Repository / DB / 外部API)

依存方向は 「上 → 下」の一方向
逆方向に依存しないことで、コードが整理され、迷子になりにくくなります。

フレームワークによっては “3層(Controller / Service / Repository)” と簡略化されることもありますが、依存方向の考え方は同じです。

レイヤードアーキテクチャ

📐 依存方向のルール

レイヤードで最重要なのは、依存が 上 → 下 の一方向 に限定されることです。

  • UI → Application → Domain → Infrastructure
  • 逆方向は禁止(インフラがUIを知る…など)

依存方向が守られるだけで、設計が崩れにくくなります。

🚫 やりがちアンチパターン

よくある “ショートカット依存” の例:

  • Controller → Repository へ直接アクセス
  • Domain → DB へ直接アクセス
  • Application があらゆる層に手を伸ばす

このあたりがプロジェクトを“スパゲッティ化”させる温床になります。


🧩 MVCモデルとの違いは?

「レイヤードとMVCって何が違うの?」という疑問をよく聞きます。

結論から言うと “目的が違うため、併用もできる” 別の概念 です。

  • MVC(Model / View / Controller)
    UI や Presentation 層の中での 役割分担モデル
    どこが表示を担当し、どこが入力処理を担当するかを分ける考え方です。
  • Layered Architecture(レイヤード)
    アプリケーション全体の 依存方向と責務の区切り方
    UI、ユースケース、ドメイン、インフラを「層」で分けます。

つまり、MVC は Presentation Layer の中に入れられる “UI の構造”、
レイヤードはアプリ全体の “大きな地図” を示す構造です。

Rails や Django など多くのフレームワークでは
「MVC(風)構造 × レイヤード的な依存方向」
が混ざっているため、両者がよく混同されます。

本記事では MVC は UI 内部の話にとどめ、アプリ全体の構造(レイヤード) にフォーカスしています。


🧪 Pythonで体験するレイヤード

この章では 概念がわかりやすい最小の断片 を抜き出して紹介します。
すべてのコードは GitHub に公開しており、
👉 src/presentation / application / domain / infrastructure がレイヤーごとに分かれています。

フルコードはこちら:
https://github.com/naokky-tech/sample-architecture-journey

処理イメージ

※このシーケンス図は、レイヤードの「典型的な流れ」を示したイメージです。今回の最小サンプルコードでは、理解しやすくするために Domain でのバリデーション処理は省略し、エンティティ中心の“薄い Domain”構成にしています。

実装

📁 ディレクトリ例

GitHub のサンプルと同じ構造は以下の通りです:

src/
  presentation/
    controller.py        # UI層(Web API / CLI などの入り口を想定)
  application/
    user_service.py      # ユースケース実装
  domain/
    user.py              # エンティティ(User)
  infrastructure/
    user_repository.py   # DBアクセス(メモリDBの例)

Presentation Layer → Application Layer(Controller → Service)

GitHub では FastAPI を最小限だけ使い、UI層=HTTPハンドラとして実装しています。

# presentation/controller.py
from application.user_service import get_user as usecase_get_user

def get_user(user_id: int):
    return usecase_get_user(user_id)

※最小構成のため Controller は非常に薄くしています。ハンドラの責務だけを担当し、詳しい処理はすべて Application に委譲しています。

Application Layer → Infrastructure Layer(Service → Repository)

# application/user_service.py
from infrastructure.user_repository import find_by_id

def get_user(user_id: int):
    # ユースケースとして「ユーザー取得」だけに集中
    # ※バリデーション/計算ロジックなどがあれば Domain に寄せる
    return find_by_id(user_id)

Infrastructure Layer(Repository)

# infrastructure/user_repository.py
USERS = {
    1: {"id": 1, "name": "Alice"},
    2: {"id": 2, "name": "Bob"},
}

def find_by_id(user_id: int):
    # 技術的詳細(DBアクセス)はここに閉じ込める
    return USERS.get(user_id)

サンプルコードでも示した通り、 「UI → ユースケース → ドメイン → インフラ」 という流れが崩れないことがレイヤードの強みです。
なお今回の最小サンプルでは、理解しやすくするため
Domain Layer は “薄く” (エンティティ中心)に構成 しています。
本格的な業務ロジックは次回扱う Clean / Hexagonal / DDD の文脈で
Domain に寄せていくイメージを掴むとより理解しやすくなります。
このように、まずは「層ごとの責務」と「依存方向」に集中してから、少しずつ Domain を“太らせていく”ほうが学習の負荷も低くなります。


📦 サンプルコード(GitHub)

本記事で紹介したレイヤードアーキテクチャの 完全なサンプルコード
GitHub リポジトリに公開しています:

🔗 https://github.com/naokky-tech/sample-architecture-journey/tree/main/samples/layered/simple-cli

ローカルでもすぐ動かせるよう、CLI で実行可能な最小構成になっています。


👍 レイヤードのメリット

1. どこに書くか迷わない

UI? → Presentation
処理の流れ? → Application
ビジネスロジック? → Domain
DB? → Infrastructure

これだけで「どこに書くか迷う問題」が劇的に減ります。

2. 小〜中規模にはとても強い

個人開発や初期フェーズでは、まずレイヤードを選ぶのがもっとも安定します。

3. テストしやすい

部品が分かれているため、サービス層のモックが簡単に作れる。


⚠️ レイヤードの限界(次章へのブリッジ)

1. 横の依存関係が増えやすい

Application Layer に処理が集中し(いわゆる “サービス肥大化”)、
結果として “レイヤー崩壊(境界が曖昧になる)” が起きやすくなります。

2. ドメイン境界が見えにくい

あくまで“層”での分割なので、
ビジネス的な意味の境界までは表現できません。

これが次回扱う
Clean Architecture / Hexagonal / DDD(ドメイン中心)
へ進むモチベーションそのものになります。


🦉 まとめ:レイヤードは“旅の最初の1ページ”

レイヤードアーキテクチャは、最初に学ぶのに最適な構造です。

  • 素朴でわかりやすい
  • 書く場所に迷わない
  • 次のステップへの「地図」になる

AI エージェント時代のような複雑な設計に進む前に、まずはこの“基本の地図”を持っておくと理解がスムーズになります。


📎 次回予告

次回は ドメイン中心(Clean / Hexagonal / DDD) を扱います。

レイヤードでは表現しきれない“境界”をどう扱うのか?
ここから設計として一段深い世界へ入っていきます。

📚 用語集(この記事で使うレイヤー名)

  • Presentation Layer
    UI や Controller が所属する層。外部入力を受け取り、Application Layer に橋渡しする役割。

  • Application Layer
    アプリケーションの振る舞いやユースケースを実行する層。本記事では“薄いユースケース層”として定義。

  • Domain Layer
    ビジネスロジックとエンティティの中心となる層。「アプリが何をすべきか」を表現する中核。

  • Infrastructure Layer
    DB、外部API、ファイルなど技術的詳細を扱う層。Repository はここに属する。

Discussion