SuperAPI AI Directory

ddd

Coding & development

View repository

Updated 10-15 22:39

About this skill

DDD Skill - Domain-Driven Design Modeling

Overview

DDD Skill provides comprehensive guidance on Domain-Driven Design, helping developers and architects perform domain modeling, bounded context decomposition, and tactical pattern implementation.

When to Use

When users need to:

  • Analyze complex business domains and perform domain modeling
  • Decompose bounded contexts and subdomains
  • Design aggregate roots, entities, and value objects
  • Implement domain services and domain events
  • Perform microservice boundary decomposition
  • Apply CQRS/event sourcing patterns
  • Design hexagonal architecture/onion architecture

Quick Start

1. Strategic Design

Determine the boundaries of the business domain and the relationships between contexts:

核心域(Core Domain)→ 竞争优势所在
支撑域(Supporting Domain)→ 支持核心业务
通用域(Generic Domain)→ 可外购/复用

2. Tactical Design

Perform detailed modeling within bounded contexts:

聚合根(Aggregate Root)
├── 实体(Entity)- 有唯一标识
├── 值对象(Value Object)- 无标识,不可变
└── 领域事件(Domain Event)- 记录业务变化

Core Concepts

Bounded Context

A bounded context is a core concept of DDD that defines the boundaries of a domain model:

┌─────────────────────────────────────────────────────┐
│                    订单上下文                         │
│  ┌─────────┐  ┌─────────┐  ┌─────────┐              │
│  │  订单   │  │ 订单项  │  │ 支付    │              │
│  │ 聚合根  │  │  实体   │  │ 值对象  │              │
│  └─────────┘  └─────────┘  └─────────┘              │
└─────────────────────────────────────────────────────┘
                    │
                    │ 上下文映射
                    ▼
┌─────────────────────────────────────────────────────┐
│                    库存上下文                         │
│  ┌─────────┐  ┌─────────┐                           │
│  │  库存   │  │ 库存项  │                           │
│  │ 聚合根  │  │  实体   │                           │
│  └─────────┘  └─────────┘                           │
└─────────────────────────────────────────────────────┘

Aggregate Design Rules

  1. Protect business invariants - Data consistency within the aggregate boundary is protected by the aggregate root
  2. Small aggregate principle - Aggregates should be as small as possible and contain only essential elements
  3. Reference by ID - Aggregates reference each other by ID, not by directly holding object references
  4. One aggregate per transaction - Modify only one aggregate per transaction
  5. Eventual consistency - Achieve eventual consistency between aggregates through domain events

Modeling Workflow

Step 1: Event Storming

Identify key events in the domain:

橙色便签:领域事件(发生了什么)
蓝色便签:命令(触发事件的动作)
黄色便签:聚合(处理命令、产生事件)
紫色便签:策略(响应事件的规则)
粉色便签:外部系统

Step 2: Identify Bounded Contexts

Divide context boundaries based on the results of event storming:

  • Group related events and aggregates into the same context
  • Use Ubiquitous Language
  • Determine the relationships between contexts

Step 3: Context Mapping

Define the integration relationships between contexts:

Pattern Description Applicable Scenarios
Shared Kernel Share part of the model Closely collaborating teams
Customer-Supplier Upstream-downstream dependency Clear service dependencies
Anticorruption Layer Isolate external models Integrate legacy systems
Open Host Service Provide a standard API Multi-consumer scenarios
Published Language Shared data format Event-driven integration

Step 4: Tactical Modeling

Perform detailed design within each context:

# 聚合根示例
class Order(AggregateRoot):
    def __init__(self, order_id: OrderId, customer_id: CustomerId):
        self.id = order_id
        self.customer_id = customer_id
        self.items: List[OrderItem] = []
        self.status = OrderStatus.DRAFT
    
    def add_item(self, product_id: ProductId, quantity: int, price: Money):
        """添加订单项 - 业务逻辑封装在聚合内"""
        if self.status != OrderStatus.DRAFT:
            raise DomainException("只能向草稿订单添加商品")
        item = OrderItem(product_id, quantity, price)
        self.items.append(item)
        self.add_event(OrderItemAdded(self.id, item))
    
    def submit(self):
        """提交订单 - 触发领域事件"""
        if not self.items:
            raise DomainException("订单不能为空")
        self.status = OrderStatus.SUBMITTED
        self.add_event(OrderSubmitted(self.id, self.total_amount))
# 值对象示例 - 不可变,无标识
@dataclass(frozen=True)
class Money:
    amount: Decimal
    currency: str
    
    def add(self, other: 'Money') -> 'Money':
        if self.currency != other.currency:
            raise ValueError("货币类型不匹配")
        return Money(self.amount + other.amount, self.currency)
# 领域事件示例
@dataclass(frozen=True)
class OrderSubmitted(DomainEvent):
    order_id: OrderId
    total_amount: Money
    occurred_at: datetime = field(default_factory=datetime.utcnow)

Architecture Patterns

Hexagonal Architecture (Ports and Adapters)

                    ┌─────────────────────────────────┐
                    │         应用层(Application)    │
    ┌───────────┐   │  ┌─────────────────────────┐   │   ┌───────────┐
    │   REST    │◄──┼──│      端口(Ports)       │──┼──►│  数据库   │
    │   API     │   │  └─────────────────────────┘   │   │ 适配器    │
    └───────────┘   │              │                  │   └───────────┘
                    │              ▼                  │
    ┌───────────┐   │  ┌─────────────────────────┐   │   ┌───────────┐
    │  消息     │◄──┼──│      领域层(Domain)    │──┼──►│  消息     │
    │  队列     │   │  │    聚合、实体、值对象     │   │   │ 适配器    │
    └───────────┘   │  └─────────────────────────┘   │   └───────────┘
                    └─────────────────────────────────┘

CQRS Pattern

命令端(Command Side)          查询端(Query Side)
      │                              │
      ▼                              ▼
┌──────────────┐              ┌──────────────┐
│ Command Bus  │              │  Query Bus   │
└──────────────┘              └──────────────┘
      │                              │
      ▼                              ▼
┌──────────────┐              ┌──────────────┐
│   聚合根     │──事件──►     │   读模型     │
│(写模型)    │              │(优化查询)  │
└──────────────┘              └──────────────┘
      │                              │
      ▼                              ▼
┌──────────────┐              ┌──────────────┐
│  事件存储    │              │  查询数据库  │
└──────────────┘              └──────────────┘

Resource Files

Detailed Reference Documentation:

  • references/strategic-design.md - Strategic Design Explained
  • references/tactical-design.md - Tactical Design Patterns
  • references/patterns.md - DDD Architecture Patterns
  • assets/ddd-model-template.drawio - Domain Model Templates

Frequently Asked Questions

Q: How do you determine aggregate boundaries?

  1. Identify business invariants (rules that must always be true)
  2. Entities involved in an invariant should be within the same aggregate
  3. Prefer small aggregates, and achieve cross-aggregate consistency through domain events

Q: When should domain services be used?

  • When business logic does not naturally belong to any entity or value object
  • When operations need to coordinate multiple aggregates
  • For example: a transfer service (coordinating two account aggregates)

Q: How do you handle cross-aggregate transactions?

  • Use the Saga pattern to orchestrate long-running transactions
  • Achieve eventual consistency through domain events
  • Avoid distributed transactions and embrace compensation mechanisms

Related Links