Communitygithub.com

领域驱动设计 — 模式与实践

为AI助手提供的便捷、即用型工程技能和最佳实践。

领域驱动设计 — 模式与实践 是什么?

该技能为AI助手(如Claude Code、Cursor、Codex等)提供了一套完整的领域驱动设计(DDD)模式和实践指南。 它涵盖了何时使用DDD(复杂业务逻辑、多领域专家、企业级应用)以及何时避免使用(简单的CRUD应用、黑客马拉松/MVP、缺乏领域专家)。 技能内容分为战略设计和战术设计两部分。战略设计包括限界上下文和上下文映射图;战术设计包括实体、值对象、聚合、领域事件、领域服务和仓储模式。 此外还提供了标准的DDD目录结构,并明确指出了贫血领域模型、大聚合、跨聚合事务等反模式。该技能适用于任何需要构建健壮业务领域模型的AI Agent平台。

兼容平台✓Claude Code~Codex CLI~Cursor
npx skills add kok-o/koko-contextos-agents

在你喜欢的 AI 中提问

打开一个已预加载此 Agent Skill 的新对话。

文档

领域驱动设计 — 模式与实践 是做什么的?

何时使用 DDD

使用场景:

  • 超越CRUD的复杂业务逻辑
  • 拥有不同术语的多个领域专家
  • 领域模型是竞争优势
  • 企业级应用

避免使用场景:

  • 简单的CRUD应用
  • 黑客马拉松/MVP(过度设计)
  • 没有领域专家可用

战略设计

限界上下文

DDD中最重要的单一概念。限界上下文是一个边界,在该边界内定义并适用一个特定的模型。

示例 — 电子商务:

[订单上下文]          [支付上下文]       [物流上下文]
  - 订单                  - 支付               - 货运
  - 订单项                - 交易               - 追踪编号
  - 客户(引用)          - 退款               - 地址
  - 地址(值对象)        - 发票               - 承运商

Customer 在每个上下文中含义不同:

  • 订单上下文:姓名、邮箱、配送偏好
  • 支付上下文:账单信息、支付方式
  • 支持上下文:工单历史、满意度评分

上下文映射图

[订单] ←→ [支付]     # 合作关系
[订单] → [物流]     # 客户-供应商
[订单] → [遗留CRM]   # 防损层

战术设计

实体

具有标识的对象。两个属性相同但ID不同的实体被视为不同实体。

class User {
  readonly id: UserId;
  name: string;
  email: Email;  // 值对象
}

值对象

由其属性定义而非标识的对象。不可变。

class Email {
  constructor(readonly value: string) {
    if (!isValidEmail(value)) throw new InvalidEmailError(value);
  }
  equals(other: Email): boolean {
    return this.value === other.value;
  }
}

聚合

由单个根实体(聚合根)统领的实体和值对象集群。所有访问都通过根进行。

class Order {  // 聚合根
  private items: OrderItem[] = [];
  
  addItem(product: ProductRef, quantity: number): void {
    // 业务逻辑在这里,不在服务中
    if (quantity <= 0) throw new InvalidQuantityError();
    this.items.push(new OrderItem(product, quantity));
  }
  
  get total(): Money {
    return this.items.reduce((sum, item) => sum.add(item.subtotal), Money.zero());
  }
}

聚合规则:

  1. 仅通过ID引用其他聚合
  2. 每个事务一个聚合
  3. 聚合之间采用最终一致性

领域事件

领域中发生的、领域专家关心的事件。

class OrderPlaced implements DomainEvent {
  constructor(
    readonly orderId: OrderId,
    readonly customerId: CustomerId,
    readonly total: Money,
    readonly occurredAt: Date
  ) {}
}

领域服务

不属于实体或值对象的业务逻辑。

class PricingService {
  calculatePrice(order: Order, customer: Customer, promotions: Promotion[]): Money {
    // 涉及多个聚合的复杂定价逻辑
  }
}

仓储

数据访问的抽象。每个聚合根对应一个仓储。

interface OrderRepository {
  findById(id: OrderId): Promise<Order | null>;
  save(order: Order): Promise<void>;
  delete(id: OrderId): Promise<void>;
}

目录结构 (DDD)

src/
├── modules/
│   └── orders/                    # 限界上下文
│       ├── domain/
│       │   ├── entities/
│       │   │   └── order.ts       # 聚合根
│       │   ├── value-objects/
│       │   │   └── money.ts
│       │   ├── events/
│       │   │   └── order-placed.ts
│       │   ├── services/
│       │   │   └── pricing.ts
│       │   └── repositories/
│       │       └── order.repository.ts  # 接口
│       ├── application/
│       │   ├── commands/
│       │   │   └── place-order.ts
│       │   ├── queries/
│       │   │   └── get-order.ts
│       │   └── handlers/
│       │       └── place-order.handler.ts
│       └── infrastructure/
│           ├── persistence/
│           │   └── order.repository.impl.ts  # 实现
│           └── api/
│               └── orders.controller.ts

整洁架构依赖规则

在DDD中,依赖关系必须严格向内指向:

[ 框架与驱动 (Web, DB, UI) ]
      └──▶ [ 接口适配器 (Controllers, Gateways) ]
            └──▶ [ 应用层 (Use Cases, CQRS Handlers) ]
                  └──▶ [ 领域层 (Entities, Value Objects) ]
  • 领域层对ORM(如Prisma、TypeORM)、HTTP框架(如Express、NestJS)或外部SDK 零依赖。
  • 仓储在领域层/应用层定义为接口,在基础设施层实现。

领域事件 vs 集成事件

  1. 领域事件:表示单个限界上下文内部的状态变更。
    • 直接在聚合根内部引发(如 order.addItem(...) 引发 OrderItemAdded)。
    • 在事务提交前进程内分发。
  2. 集成事件:跨限界上下文边界发布,用于与其他服务通信。
    • 通过事务性发件箱模式分发给消息代理。
    • 必须使用带有版本控制的向后兼容模式。

防损层 (ACL)

当消费来自外部限界上下文或第三方供应商API(如Stripe、Salesforce)的数据时:

  • 绝对不要将外部领域模型直接导入你的领域。
  • 在基础设施层创建一个 ACL转换器/适配器,将外部DTO转换为你自己的值对象和实体。

反模式

  • [失败] 贫血领域模型 —— 实体只有getter/setter,所有逻辑在服务中
  • [失败] 大聚合 —— 聚合应该小,专注于不变量
  • [失败] 跨聚合事务 —— 使用最终一致性
  • [失败] 处处DDD —— 仅在复杂性足以证明合理的地方使用DDD
  • [失败] ORM实体泄漏到领域 —— 领域实体不得依赖 @Entity() 或ORM装饰器

代码示例

详细代码示例请参见 EXAMPLES.md。

验证清单

在完成任务前的审查阶段需要验证的内容。

常见错误

需要明确避免的反模式和事项。请参见 TROUBLESHOOTING.md。

集成说明

此技能如何与其他技能交互。

相关技能