python-fastapi-ddd-skill について
dddpy の参照実装に基づき、Python の DDD と Onion Architecture で FastAPI バックエンドを設計するガイドです。ドメインコードを独立させつつ、ドメイン、インフラ、ユースケース、プレゼンテーションを整理するバックエンド開発者向けです。
主な機能
- 014 層アーキテクチャの責務整理
- 02エンティティと値オブジェクトのモデル化
- 03ドメイン層のリポジトリーインターフェース
- 04ユースケース単位のアプリケーション処理
- 05依存性注入と DTO の変換
活用シーン
- 01FastAPI バックエンドの層とディレクトリー設計
- 02業務ルールをドメインモデルに集約
- 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.yamlreferences/ARCHITECTURE.mdENTITIES.mdREPOSITORIES.mdUSECASES.mdVALUE_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() を実装 |
| Presentation | HTTP 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 を参照してください。
ベストプラクティス
- ドメインレイヤーを純粋に保つ:ドメインコードではフレームワークをインポートしません(FastAPI や SQLAlchemy を使用しません)。
- レイヤー間の境界には DTO を使用する:
to_entity()/from_entity()メソッドを使って、ドメインエンティティとインフラストラクチャモデルを相互に変換します。 - 依存性注入:FastAPI の
Depends()を使用して、セッション → リポジトリ → ユースケース → ハンドラーを接続します。 - 1 つのユースケースには 1 つの責務:各ユースケースが持つ公開
executeメソッドは 1 つだけです。 - 値オブジェクトで検証する:ビジネスルールは、凍結されたデータクラスの
__post_init__に記述します。 - ドメイン例外:ビジネスルール違反に対して、具体的な例外クラスを作成します(例:
TodoNotFoundError、TodoAlreadyCompletedError)。 - ファクトリー関数:実装を作成するための
new_*ファクトリー関数を公開し、具象クラスは実装の詳細として扱います。