关于 domain-driven-design
domain-driven-design 是帮助开发者用领域驱动设计建模复杂业务逻辑的技能。内容涉及实体、值对象、聚合、仓储和限界上下文,也说明何时不宜采用该方法。
主要功能
- 01实体、值对象与聚合设计
- 02业务规则与聚合不变量
- 03仓储和工作单元模式
- 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) |
| 仓储范围 | 每个聚合根一个 |
| 领域事件 | 在实体中收集,持久化后发布 |
| 上下文边界 | 根据业务能力划分,而非技术 |
规则快速参考
| 规则 | 影响 | 涵盖内容 |
|---|---|---|
aggregate-boundaries(加载 rules/aggregate-boundaries.md) | HIGH | 聚合根设计、按 ID 引用、每个事务一个 |
aggregate-invariants(加载 rules/aggregate-invariants.md) | HIGH | 业务规则实施、规格模式 |
aggregate-sizing(加载 rules/aggregate-sizing.md) | HIGH | 合理确定大小、何时拆分、最终一致性 |
不适用场景
实体少于 5 个?完全跳过 DDD。仪式性开销大于收益。
| 模式 | 面试 | 黑客松 | MVP | 成长期 | 企业级 | 更简单的替代方案 |
|---|---|---|---|---|---|---|
| 聚合 | 过度设计 | 过度设计 | 过度设计 | 酌情采用 | 适用 | 带验证的普通 dataclass |
| 限界上下文 | 过度设计 | 过度设计 | 过度设计 | 临界 | 适用 | 导入关系清晰的 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 技能 |
本技能会专门保留两个主题,而不指向上游文档:仓储和工作单元的实现,完整内容见 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、事件排空顺序、防腐层边界、源代码布局 |
repositories.md | 仓储模式、工作单元、SQLAlchemy 映射 |
能力详情
entities
关键词: 实体、标识、生命周期、可变、领域对象
解决的问题: 按 ID 进行标识相等性判断,以及 references/ork-delta.md 中的本项目 UUIDv7 ID 规则。数据类机制请参考上游文档。
value-objects
关键词: 值对象、不可变、冻结、数据类、结构相等性
解决的问题: 何时使用值对象而非实体。frozen=True 语义和继承字段顺序请参考上游文档。
domain-services
关键词: 领域服务、业务逻辑、跨聚合、无状态 解决的问题: 何时使用领域服务、跨聚合的逻辑
repositories
关键词: 仓储、持久化、集合、IRepository、协议 解决的问题: 实现仓储模式、抽象数据库访问、ORM 映射
bounded-contexts
关键词: 限界上下文、上下文映射、防腐层、子域、统一语言
解决的问题: references/ork-delta.md 中的本项目防腐层边界和上下文优先源代码布局。上下文映射和集成模式请参考上游文档。