domain-driven-design について
domain-driven-designは、複雑な業務ロジックをドメイン駆動設計でモデル化する開発者向けスキルです。エンティティ、値オブジェクト、集約、リポジトリ、境界づけられたコンテキストを扱い、適用が不要な場合も示します。
主な機能
- 01エンティティ、値オブジェクト、集約の設計
- 02業務ルールと集約の不変条件
- 03リポジトリとUnit of Workパターン
- 04境界づけられたコンテキストと領域境界
- 05DDDの適用可否の判断
活用シーン
- 01複数オブジェクトにまたがる複雑なルールのモデル化
- 02業務サブドメインとコンテキスト境界の分割
- 03集約の永続化とトランザクション処理の整理
インストール
コマンドをコピーしてターミナルで実行します。
npx skills add https:/ / github.com/ yonatangross/ orchestkit --skill domain-driven-designインストール後、Claude Code で/domain-driven-designを入力して読み込まれたか確認します。
同梱ファイル
SKILL.md と一緒にインストールされる参考資料やスクリプト。
test-cases.jsonreferences/ork-delta.mdrepositories.mdrules/_sections.md_template.mdaggregate-boundaries.mdaggregate-invariants.mdaggregate-sizing.mdscripts/entity-template.pyrepository-template.pyvalue-object-template.py詳細
ドメイン駆動設計の戦術パターン
エンティティ、値オブジェクト、境界づけられたコンテキストを使って、複雑なビジネスドメインをモデル化します。
概要
- 複雑なビジネスロジックのモデル化
- ドメインとインフラストラクチャの分離
- サブドメイン間の明確な境界の確立
- 振る舞いを備えた豊かなドメインモデルの構築
- コードへのユビキタス言語の実装
ビルディングブロックの概要
┌─────────────────────────────────────────────────────────────┐
│ DDD Building Blocks │
├─────────────────────────────────────────────────────────────┤
│ ENTITIES VALUE OBJECTS AGGREGATES │
│ Order (has ID) Money (no ID) [Order]→Items │
│ │
│ DOMAIN SERVICES REPOSITORIES DOMAIN EVENTS │
│ PricingService IOrderRepository OrderSubmitted │
│ │
│ FACTORIES SPECIFICATIONS MODULES │
│ OrderFactory OverdueOrderSpec orders/, payments/ │
└─────────────────────────────────────────────────────────────┘
クイックリファレンス
エンティティ(識別子を持つ)
from dataclasses import dataclass, field
from uuid import UUID
from uuid_utils import uuid7
@dataclass
class Order:
"""Entity: Has identity, mutable state, lifecycle."""
id: UUID = field(default_factory=uuid7)
customer_id: UUID = field(default=None)
status: str = "draft"
def __eq__(self, other: object) -> bool:
if not isinstance(other, Order):
return NotImplemented
return self.id == other.id # Identity equality
def __hash__(self) -> int:
return hash(self.id)
ID の生成方法は好みではなく、プロジェクトの規約です:Read("references/ork-delta.md")。
値オブジェクト(不変)
from dataclasses import dataclass
from decimal import Decimal
@dataclass(frozen=True) # MUST be frozen!
class Money:
"""Value Object: Defined by attributes, not identity."""
amount: Decimal
currency: str
def __add__(self, other: "Money") -> "Money":
if self.currency != other.currency:
raise ValueError("Cannot add different currencies")
return Money(self.amount + other.amount, self.currency)
標準的な Address/DateRange の定型コードは、ここでは繰り返しません。以下のアップストリームのカバレッジ表を参照してください。
重要な判断
| 判断 | 推奨 |
|---|---|
| エンティティか VO か | 一意の ID とライフサイクルがある場合はエンティティ。それ以外は VO |
| エンティティの同等性 | 属性ではなく ID で判定 |
| 値オブジェクトの可変性 | 常に不変(frozen=True) |
| リポジトリの範囲 | 集約ルートごとに 1 つ |
| ドメインイベント | エンティティで収集し、永続化後に発行 |
| コンテキストの境界 | 技術的な区分ではなく、ビジネス能力で定める |
ルールのクイックリファレンス
| ルール | 影響 | 対象範囲 |
|---|---|---|
aggregate-boundaries(rules/aggregate-boundaries.md を読み込む) | 高 | 集約ルートの設計、ID による参照、トランザクションごとに 1 つ |
aggregate-invariants(rules/aggregate-invariants.md を読み込む) | 高 | ビジネスルールの適用、仕様パターン |
aggregate-sizing(rules/aggregate-sizing.md を読み込む) | 高 | 適切なサイズ設定、分割のタイミング、結果整合性 |
使用しない場合
エンティティが 5 個未満の場合は、DDD を使わないでください。形式的な手順にかかるコストが、メリットを上回ります。
| パターン | 面接 | ハッカソン | MVP | 成長期 | エンタープライズ | よりシンプルな代替案 |
|---|---|---|---|---|---|---|
| 集約 | 過剰 | 過剰 | 過剰 | 選択的に適用 | 適切 | バリデーション付きの通常のデータクラス |
| 境界づけられたコンテキスト | 過剰 | 過剰 | 過剰 | 境界的 | 適切 | インポートを明確にした Python パッケージ |
| CQRS | 過剰 | 過剰 | 過剰 | 過剰 | 正当な理由がある場合 | 読み取り/書き込み共通の単一モデル |
| 値オブジェクト | 過剰 | 過剰 | 境界的 | 適切 | 必須 | エンティティ上の型付きフィールド |
| ドメインイベント | 過剰 | 過剰 | 過剰 | 選択的に適用 | 適切 | サービス間の直接的なメソッド呼び出し |
| リポジトリパターン | 過剰 | 過剰 | 境界的 | 適切 | 必須 | サービス層での直接的な ORM クエリ |
経験則: DDD を導入すると、コード量が約 40%増えます。ドメインの複雑さが本当に必要とする場合(複数のオブジェクトにまたがる不変条件を持つエンティティが 5 個以上)のみ、導入する価値があります。CRUD アプリで DDD を使うのは危険信号です。
アンチパターン(禁止)
# NEVER have anemic domain models (data-only classes)
@dataclass
class Order:
id: UUID
items: list # WRONG - no behavior!
# NEVER leak infrastructure into domain
class Order:
def save(self, session: Session): # WRONG - knows about DB!
# NEVER use mutable value objects
@dataclass # WRONG - missing frozen=True
class Money:
amount: Decimal
# NEVER have repositories return ORM models
async def get(self, id: UUID) -> OrderModel: # WRONG - return domain!
上流のカバレッジ(ここでは再掲しません)
以下のトピックは公式ドキュメントで説明されています。ここで独自に導き出すのではなく、公式ドキュメントを参照してください。プロジェクト固有のルールのみ、references/ork-delta.md に記載しています。
| トピック | 参照先 |
|---|---|
エンティティ/値オブジェクトのデータクラスの仕組み:frozen、__post_init__、継承時のフィールド順序、kw_only | https://docs.python.org/3/library/dataclasses.html |
| ドメインイベントの定義、遅延ディスパッチ、ハンドラーの接続、コミット前後のディスパッチ | https://learn.microsoft.com/en-us/dotnet/architecture/microservices/microservice-ddd-cqrs-patterns/domain-events-design-implementation |
| 境界づけられたコンテキスト、コンテキストマップ、ユビキタス言語、統合パターン(共有カーネル、顧客とサプライヤー、追従者、オープンホストサービス、公開言語) | https://learn.microsoft.com/en-us/azure/architecture/microservices/model/domain-analysis |
| 腐敗防止層:変換する対象とそのコスト | https://learn.microsoft.com/en-us/azure/architecture/patterns/anti-corruption-layer |
| UUIDv7 の生成方法(サーバー側および Python) | https://www.postgresql.org/docs/18/functions-uuid.html and https://github.com/aminalaee/uuid-utils |
| 最小通貨単位での支払い金額、小数部のない通貨 | https://docs.stripe.com/currencies |
Redis Stream へのイベントの公開(XADD のフィールドマップ、パイプライン処理) | https://redis.io/docs/latest/commands/xadd/ |
| レイヤードアーキテクチャの強制、プロジェクト構成の検証、テスト標準 | このプラグインの architecture-patterns スキル |
意図的にこのスキルに残しているトピックは 2 つあります。リポジトリと Unit of Work の実装(全容は references/repositories.md に記載)と、集約境界、不変条件、規模の決定(全容は rules/ に記載)です。
関連スキル
rules/aggregate-boundaries.md、rules/aggregate-invariants.md、rules/aggregate-sizing.md- 集約設計(このスキル内)ork:architecture-patterns- レイヤー境界とプロジェクト構成の検証ork:distributed-systems- 集約をまたぐ調整ork:database-patterns- DDD のスキーマ設計
参考資料
Read("references/<file>") で必要に応じて読み込みます。
| ファイル | 内容 |
|---|---|
ork-delta.md | プロジェクト固有のルール:UUIDv7、イベントのドレイン順序、ACL 境界、ソースの配置 |
repositories.md | リポジトリパターン、Unit of Work、SQLAlchemy マッピング |
機能の詳細
entities
キーワード: エンティティ、同一性、ライフサイクル、可変、ドメインオブジェクト
解決すること: ID による同一性の等価性と、references/ork-delta.md に記載されたプロジェクト固有の UUIDv7 ID ルールです。データクラスの仕組みについては上流の資料を参照してください。
value-objects
キーワード: 値オブジェクト、不変、frozen、データクラス、構造的等価性
解決すること: 値オブジェクトとエンティティの使い分けです。frozen=True のセマンティクスと継承時のフィールド順序については、上流の資料を参照してください。
domain-services
キーワード: ドメインサービス、ビジネスロジック、集約をまたぐ、ステートレス
解決すること: ドメインサービスを使う場面と、複数の集約にまたがるロジックです。
repositories
キーワード: リポジトリ、永続化、コレクション、IRepository、プロトコル
解決すること: リポジトリパターンの実装、DB アクセスの抽象化、ORM マッピングです。
bounded-contexts
キーワード: 境界づけられたコンテキスト、コンテキストマップ、ACL、サブドメイン、ユビキタス言語
解決すること: references/ork-delta.md に記載されたプロジェクト固有の ACL 境界と、コンテキストを起点とするソースの配置です。コンテキストマッピングと統合パターンについては、上流の資料を参照してください。