第2部:AIとアーキテクチャ設計 Step 6 / 36

クリーンアーキテクチャをAIと実装

クリーンアーキテクチャは複雑に見えますが、AIと一緒に進めれば効率的に実装できます。レイヤーごとに役割を理解し、段階的に構築していきましょう。

クリーンアーキテクチャの基本

レイヤー構成

Entities(エンティティ)

ビジネスルールを表現。最も内側で、他に依存しない

Use Cases(ユースケース)

アプリケーション固有のビジネスロジック

Interface Adapters(インターフェースアダプター)

コントローラー、プレゼンター、ゲートウェイ

Frameworks & Drivers(フレームワーク)

DB、Web、外部サービスなど。最も外側

依存関係のルール

内側のレイヤーは外側のレイヤーを知らない。依存は常に外から内へ向かう。

外側 → → → 内側
DB → Repository → Service → Entity

FastAPIでの実装例

AIへの指示:プロジェクト構造の作成

FastAPIでクリーンアーキテクチャを採用したプロジェクト構造を作成してください。

【機能】
タスク管理システム(CRUD)

【要件】
- ドメイン層:Task エンティティ
- ユースケース層:タスクの作成、取得、更新、削除
- インフラ層:SQLAlchemy を使用したリポジトリ
- プレゼンテーション層:FastAPI エンドポイント

まず、フォルダ構造と各ファイルの役割を説明してください。

推奨フォルダ構造

app/
├── main.py                    # FastAPIアプリ起動
├── domain/                    # ドメイン層
│   ├── entities/
│   │   └── task.py           # Taskエンティティ
│   └── repositories/
│       └── task_repository.py # リポジトリインターフェース(抽象)
├── application/               # ユースケース層
│   └── use_cases/
│       └── task_use_cases.py # ビジネスロジック
├── infrastructure/            # インフラ層
│   ├── database/
│   │   ├── connection.py     # DB接続
│   │   └── models.py         # SQLAlchemyモデル
│   └── repositories/
│       └── task_repository_impl.py  # リポジトリ実装
└── presentation/              # プレゼンテーション層
    ├── api/
    │   └── tasks.py          # エンドポイント
    └── schemas/
        └── task_schema.py    # リクエスト/レスポンス

AIと段階的に実装する

1 ドメインエンティティを作成

「domain/entities/task.py を作成してください。
Task エンティティには id, title, description, status, created_at, updated_at を含めます。
ビジネスルールとして、status は "todo", "in_progress", "done" のいずれかです。
フレームワークに依存しない純粋なPythonクラスで実装してください。」
# domain/entities/task.py
from dataclasses import dataclass
from datetime import datetime
from enum import Enum

class TaskStatus(Enum):
    TODO = "todo"
    IN_PROGRESS = "in_progress"
    DONE = "done"

@dataclass
class Task:
    id: str
    title: str
    description: str
    status: TaskStatus
    created_at: datetime
    updated_at: datetime

    def mark_as_done(self) -> None:
        self.status = TaskStatus.DONE
        self.updated_at = datetime.now()

2 リポジトリインターフェースを定義

「domain/repositories/task_repository.py を作成してください。
TaskRepository の抽象基底クラス(ABC)を定義し、
save, find_by_id, find_all, delete メソッドを宣言してください。
この時点ではDBに依存しません。」
# domain/repositories/task_repository.py
from abc import ABC, abstractmethod
from typing import Optional, List
from domain.entities.task import Task

class TaskRepository(ABC):
    @abstractmethod
    def save(self, task: Task) -> Task:
        pass

    @abstractmethod
    def find_by_id(self, task_id: str) -> Optional[Task]:
        pass

    @abstractmethod
    def find_all(self) -> List[Task]:
        pass

    @abstractmethod
    def delete(self, task_id: str) -> None:
        pass

3 ユースケースを実装

「application/use_cases/task_use_cases.py を作成してください。
TaskRepository をコンストラクタで受け取り(依存性注入)、
CreateTask, GetTask, UpdateTask, DeleteTask のユースケースを実装してください。」

4 インフラ層(リポジトリ実装)

「infrastructure/repositories/task_repository_impl.py を作成してください。
TaskRepository インターフェースを実装し、SQLAlchemy を使ってDBアクセスします。
エンティティとDBモデルの変換も行ってください。」

5 プレゼンテーション層(API)

「presentation/api/tasks.py を作成してください。
FastAPI の Router を使い、CRUD エンドポイントを実装します。
ユースケースを依存性注入で受け取り、Pydanticスキーマで入出力を定義してください。」

依存性注入の設定

AIへの指示

「FastAPI の Depends を使って依存性注入を設定してください。
- TaskRepository の実装を TaskRepositoryImpl に差し替え可能にする
- テスト時にモックリポジトリを注入できるようにする
- main.py でのワイヤリング方法を示してください」

依存性注入のコード例

# main.py
from fastapi import FastAPI, Depends
from infrastructure.repositories.task_repository_impl import TaskRepositoryImpl
from application.use_cases.task_use_cases import TaskUseCases
from presentation.api.tasks import router

app = FastAPI()

def get_task_repository():
    return TaskRepositoryImpl()

def get_task_use_cases(repo = Depends(get_task_repository)):
    return TaskUseCases(repo)

app.include_router(router)

クリーンアーキテクチャのメリット

メリット

  • ✓ テストが書きやすい(モック注入可能)
  • ✓ フレームワークの変更に強い
  • ✓ ビジネスロジックが明確に分離
  • ✓ チーム開発で責任範囲が明確

注意点

  • △ 小規模プロジェクトには過剰かも
  • △ ファイル数が増える
  • △ 学習コストがある
  • △ シンプルなCRUDには向かない場合も

まとめ

  • レイヤーを理解する - エンティティ→ユースケース→アダプター→フレームワーク
  • 内側から外側へ実装 - エンティティ→リポジトリIF→ユースケース→実装
  • 依存性注入を活用 - テスト容易性と柔軟性を確保
  • AIに段階的に依頼 - レイヤーごとに指示を出す
AIに設計を相談する 次へ:既存コードのリファクタリング