#0095（2025/04/06） オニオンアーキテクチャ実践

# オニオンアーキテクチャを用いたタスク管理アプリの構築 – 実践ハンズオン

この記事では、オニオンアーキテクチャの概要とその実践方法について、シンプルなタスク管理アプリを例に解説します。最初はモックデータによる処理を実装し、最終的には Docker 上の PostgreSQL を利用して永続化する仕組みまで対応しています。さらに、テストコードの実装や、各層の役割・関係性についても詳しく説明します。

---

## オニオンアーキテクチャの概要

**オニオンアーキテクチャ**は、アプリケーションの各層を内側から外側へと明確に分離する設計思想です。  
その基本的な考え方は以下の通りです。

- **中心部（Domain 層）**  
  ビジネスロジックやエンティティ、値オブジェクトなど、アプリケーションの核となる部分を構成します。  
  ここでは、ビジネスルールに忠実なモデル設計を行い、アプリケーションの根幹となるデータやロジックを担います。

- **その周囲に Use Case 層（アプリケーション層）**  
  Domain 層のエンティティを利用して、具体的なユースケース（タスクの作成、更新、削除、一覧取得など）を実現します。  
  この層は、Domain 層が定義するインターフェースに依存し、具体的な実装は外部に任せることで**依存性逆転の原則 (DIP)** を実現しています。

- **さらに外側に Presentation 層（UI層）**  
  ユーザーとのインターフェースを担当し、CLI、Web API、GUI などで実装されます。  
  ユーザー入力とユースケースの実行ロジックが明確に分離されるため、**インターフェース分離の原則 (ISP)** にも配慮されています。

- **最外層に Infrastructure 層**  
  データベースやファイルシステム、外部APIなどの外部システムとの連携を担当します。  
  この層では、Domain や Use Case 層で定義されたリポジトリの抽象インターフェースを具体的な実装（初期はモック、最終的には Docker 上の PostgreSQL など）で満たします。

このように、各層が独立しているため、たとえばビジネスロジックを変更しても、UI や外部システムとの連携部分に影響を与えにくいというメリットがあります。

---

## タスク管理アプリの概要

本アプリは、シンプルなタスク管理機能を提供するもので、以下の機能を実装しています。

- **タスクの作成**  
  タスクのタイトル、説明などの情報を元に、新たなタスクエンティティを生成し、リポジトリに保存します。

- **タスクの取得・一覧表示**  
  保存されたタスクを一覧で取得できるようにし、ユーザーが登録したタスクの情報を確認できます。

- **タスクの更新**  
  タスクのタイトル、説明、完了状態などを変更する機能を提供します。

- **タスクの削除**  
  不要になったタスクを削除できるようにします。

初期段階では、モック（InMemory）でタスクを管理し、後に Docker 上で稼働する PostgreSQL と連携する形で永続化対応を実施します。また、テストコードを用いて各層の動作確認も行います。

---

## ディレクトリ構成

以下は、本プロジェクトのディレクトリ構成の一例です。

``` shell
my_onion_app/
├── domain/
│   ├── entities.py        # タスクエンティティ、ビジネスロジック
│   └── repositories.py    # 抽象的なリポジトリインターフェース
├── usecase/
│   └── task_service.py    # タスクに関するビジネスロジック（ユースケース）
├── presentation/
│   └── app.py             # FastAPI を用いた API エンドポイントの実装
├── infrastructure/
│   ├── repository_impl.py           # モック実装（InMemoryTaskRepository）
│   └── repository_impl_postgres.py  # PostgreSQL 用リポジトリ実装（SQLAlchemy 使用）
├── tests/
│   └── test_task.py       # ユニットテスト、エンドポイントのテストコード
├── run_data_operations.py # PostgreSQL を用いたデータ操作のサンプルスクリプト
└── docker-compose.yml     # Docker で PostgreSQL コンテナを起動するための設定
```

---

## 各ファイルの役割

### Domain 層

- **entities.py**  
  タスク管理に必要なエンティティ（Task クラス）を定義。  
  タスクの属性（タイトル、説明、状態、作成日、更新日など）と基本的なビジネスバリデーション（例：タイトルが空であってはならない）を実装。

- **repositories.py**  
  タスクの永続化に必要な操作（追加、取得、更新、削除、一覧取得）を抽象化したインターフェースを定義。  
  この抽象インターフェースにより、Use Case 層は具体的な実装に依存せず、ビジネスロジックに集中できるようになる。

### Use Case 層

- **task_service.py**  
  ドメインエンティティを利用して、タスクの作成、取得、更新、削除、一覧取得などのユースケースを実装。  
  この層は、Domain 層と Infrastructure 層のリポジトリ実装（モックや PostgreSQL 実装）を仲介し、ビジネスルールを実行する役割を持つ。

### Presentation 層

- **app.py**  
  FastAPI を用いて RESTful API を実装。  
  ユーザーからの HTTP リクエストを受け取り、Use Case 層のメソッドを呼び出して結果を返す。  
  また、Pydantic を使ったリクエスト・レスポンスのデータモデルで入力検証と出力整形を実施する。

### Infrastructure 層

- **repository_impl.py**  
  モック実装として、InMemoryTaskRepository を定義。  
  開発初期段階や単体テストのために、実際のデータベースを使用せず、メモリ上でタスクデータを管理する。

- **repository_impl_postgres.py**  
  Docker 上で稼働する PostgreSQL を利用するためのリポジトリ実装。  
  SQLAlchemy を用いて ORM モデル（TaskModel）を定義し、データベースとの CRUD 操作を実現する。  
  また、データベース初期化用の `init_db()` 関数や、セッション生成のための設定も含む。

### テストコード

- **tests/test_task.py**  
  pytest を利用して、Use Case 層と FastAPI のエンドポイントのテストを実装。  
  各テストケースで、リポジトリのモック実装や実際の DB を使った動作確認を行う。

### データ操作サンプルスクリプト

- **run_data_operations.py**  
  PostgreSQL 用リポジトリ（PostgresTaskRepository）を利用して、実際にタスクの作成、更新、削除などの操作を行うサンプルスクリプト。  
  これにより、Docker 上の PostgreSQL に対する永続化が正しく動作するかを検証する。

### Docker コンテナ

- **docker-compose.yml**  
  PostgreSQL コンテナを起動するための設定ファイル。  
  ユーザー名、パスワード、データベース名を環境変数で指定し、ローカル環境で簡単にデータベースを立ち上げることができる。

---

## 各ファイルの関係性

オニオンアーキテクチャでは、内側の層は外側の層に依存せず、依存性逆転の原則 (DIP) によって抽象に依存します。

- **Domain 層**は、ビジネスルールの核として、Task クラスとリポジトリインターフェースを提供。  
- **Use Case 層**は、Domain 層のエンティティと抽象リポジトリに依存し、具体的なユースケースを実現する。  
- **Presentation 層**は、Use Case 層を呼び出すことでユーザーインターフェースを実現し、データの入出力を担当する。  
- **Infrastructure 層**は、Domain 層で定義された抽象リポジトリインターフェースの具体的な実装を提供。  
  - 開発初期は InMemoryTaskRepository を使い、後に PostgresTaskRepository に切り替えることが容易にできるように設計されている。  
  - 切り替えは、環境変数や設定ファイルで実行時にどのリポジトリ実装を利用するかを制御する仕組みで対応。

この関係性により、ビジネスロジックやユーザーインターフェースを変更しても、永続化の実装部分を最小限の影響で差し替えられるため、システム全体の柔軟性と保守性が大幅に向上します。

---

## まとめ

本記事では、オニオンアーキテクチャの概念と、その実践としてのタスク管理アプリの構築手順について解説しました。  
- **オニオンアーキテクチャ**の中心にビジネスロジック（Domain 層）を据え、外側にユースケース、プレゼンテーション、インフラ層を配置することで、各層が独立し柔軟な設計が可能となります。  
- **タスク管理アプリ**では、タスクの登録、更新、削除、一覧取得の機能を通して、各層の役割と SOLID 原則（SRP、DIP、ISP）を実践的に学ぶことができます。  
- **ディレクトリ構成**と各ファイルの役割、さらにファイル間の関係性を明確にすることで、将来的な変更や機能拡張が容易な設計となっています。  
- 初期はモック実装で開発・テストを行い、最終的には Docker 上の PostgreSQL と連携する Infrastructure 層の実装に切り替えることで、本番環境に近い永続化を実現しています。