mcpField
P
python-fastapi-ddd-skill

python-fastapi-ddd-skill

github.com/iktakahiro開発544 回インストール38 週間前に更新
リポジトリ

python-fastapi-ddd-skill について

dddpy の参照実装に基づき、Python の DDD と Onion Architecture で FastAPI バックエンドを設計するガイドです。ドメインコードを独立させつつ、ドメイン、インフラ、ユースケース、プレゼンテーションを整理するバックエンド開発者向けです。

主な機能

  1. 014 層アーキテクチャの責務整理
  2. 02エンティティと値オブジェクトのモデル化
  3. 03ドメイン層のリポジトリーインターフェース
  4. 04ユースケース単位のアプリケーション処理
  5. 05依存性注入と DTO の変換

活用シーン

  1. 01FastAPI バックエンドの層とディレクトリー設計
  2. 02業務ルールをドメインモデルに集約
  3. 03リポジトリーとユースケースの境界設計

インストール

コマンドをコピーしてターミナルで実行します。

$npx skills add https://github.com/iktakahiro/python-fastapi-ddd-skill --skill python-fastapi-ddd-skill

インストール後、Claude Code で/python-fastapi-ddd-skillを入力して読み込まれたか確認します。

同梱ファイル

SKILL.md と一緒にインストールされる参考資料やスクリプト。

agents/
openai.yaml
references/
ARCHITECTURE.md
ENTITIES.md
REPOSITORIES.md
USECASES.md
VALUE_OBJECTS.md

詳細

FastAPI + Python DDD とオニオンアーキテクチャの設計ガイド

dddpy のリファレンス実装(FastAPI + SQLAlchemy + Python 3.13+)に基づき、DDD の原則とオニオンアーキテクチャを用いた FastAPI バックエンドの設計方法を解説します。

アーキテクチャの概要

依存関係が内側を向く、4 つの同心円状のレイヤーで構成されます。

Presentation  →  UseCase  →  Infrastructure  →  Domain (innermost)

重要なルール:内側のレイヤーは外側のレイヤーに依存しません。ドメインレイヤーには外部依存が一切ありません。

レイヤー責務例
Domain中核となるビジネスロジック。フレームワークへの依存なしエンティティ、値オブジェクト、リポジトリインターフェース、例外
Infrastructure外部との連携DB リポジトリ、DTO、DI 設定、SQLAlchemy モデル
UseCaseアプリケーションのワークフローユースケースごとに 1 つのクラスを作成し、execute() を実装
PresentationHTTP API のインターフェースFastAPI ルート、Pydantic スキーマ、エラーメッセージ

アーキテクチャの詳細ガイド:ARCHITECTURE.md を参照してください。

ディレクトリ構成

project/
├── main.py
├── app/
│   ├── domain/
│   │   └── {aggregate}/
│   │       ├── entities/
│   │       ├── value_objects/
│   │       ├── repositories/
│   │       └── exceptions/
│   ├── infrastructure/
│   │   ├── di/
│   │   │   └── injection.py
│   │   └── sqlite/
│   │       └── {aggregate}/
│   │           ├── {aggregate}_dto.py
│   │           └── {aggregate}_repository.py
│   ├── usecase/
│   │   └── {aggregate}/
│   │       └── {action}_{aggregate}_usecase.py
│   └── presentation/
│       └── api/
│           └── {aggregate}/
│               ├── handlers/
│               ├── schemas/
│               └── error_messages/
└── tests/

クイックリファレンス

1. エンティティ

エンティティは一意の識別子と変更可能な状態を持ち、ビジネスロジックをカプセル化します。同値性は属性値ではなく、識別子に基づきます。

class Todo:
    def __init__(self, id: TodoId, title: TodoTitle, status: TodoStatus = TodoStatus.NOT_STARTED):
        self._id = id
        self._title = title
        self._status = status

    def __eq__(self, obj: object) -> bool:
        if isinstance(obj, Todo):
            return self.id == obj.id
        return False

    def start(self) -> None:
        self._status = TodoStatus.IN_PROGRESS

    @staticmethod
    def create(title: TodoTitle) -> "Todo":
        return Todo(TodoId.generate(), title)

詳細ガイド:ENTITIES.md を参照してください。

2. 値オブジェクト

識別子ではなく値によって定義される、不変のオブジェクトです。@dataclass(frozen=True) を使用し、__post_init__ で検証します。

@dataclass(frozen=True)
class TodoTitle:
    value: str

    def __post_init__(self):
        if not self.value:
            raise ValueError("Title is required")
        if len(self.value) > 100:
            raise ValueError("Title must be 100 characters or less")

詳細ガイド:VALUE_OBJECTS.md を参照してください。

3. リポジトリインターフェース

ドメインレイヤーで抽象インターフェースを定義し、インフラストラクチャレイヤーで実装します。

class TodoRepository(ABC):
    @abstractmethod
    def save(self, todo: Todo) -> None: ...

    @abstractmethod
    def find_by_id(self, todo_id: TodoId) -> Optional[Todo]: ...

    @abstractmethod
    def find_all(self) -> List[Todo]: ...

    @abstractmethod
    def delete(self, todo_id: TodoId) -> None: ...

詳細ガイド:REPOSITORIES.md を参照してください。

4. ユースケース

ユースケースごとに 1 つのクラスを作成します。抽象インターフェース、具象実装、ファクトリー関数で構成します。

class CreateTodoUseCase(ABC):
    @abstractmethod
    def execute(self, title: TodoTitle) -> Todo: ...

class CreateTodoUseCaseImpl(CreateTodoUseCase):
    def __init__(self, todo_repository: TodoRepository):
        self.todo_repository = todo_repository

    def execute(self, title: TodoTitle) -> Todo:
        todo = Todo.create(title=title)
        self.todo_repository.save(todo)
        return todo

def new_create_todo_usecase(repo: TodoRepository) -> CreateTodoUseCase:
    return CreateTodoUseCaseImpl(repo)

詳細ガイド:USECASES.md を参照してください。

ベストプラクティス

  1. ドメインレイヤーを純粋に保つ:ドメインコードではフレームワークをインポートしません(FastAPI や SQLAlchemy を使用しません)。
  2. レイヤー間の境界には DTO を使用する:to_entity() / from_entity() メソッドを使って、ドメインエンティティとインフラストラクチャモデルを相互に変換します。
  3. 依存性注入:FastAPI の Depends() を使用して、セッション → リポジトリ → ユースケース → ハンドラーを接続します。
  4. 1 つのユースケースには 1 つの責務:各ユースケースが持つ公開 execute メソッドは 1 つだけです。
  5. 値オブジェクトで検証する:ビジネスルールは、凍結されたデータクラスの __post_init__ に記述します。
  6. ドメイン例外:ビジネスルール違反に対して、具体的な例外クラスを作成します(例:TodoNotFoundError、TodoAlreadyCompletedError)。
  7. ファクトリー関数:実装を作成するための new_* ファクトリー関数を公開し、具象クラスは実装の詳細として扱います。

コメント