domain-driven-design

Compare original and translation side by side

🇺🇸

Original

English
🇨🇳

Translation

Chinese

Domain-Driven Design

领域驱动设计

Overview

概述

This skill provides guidance for domain modeling based on Rich Hickey's data-oriented design principles and Scott Wlaschin's type-driven design approach. Focus on building systems that make illegal states unrepresentable, prioritize data and transformations over objects and methods, and establish a ubiquitous language that bridges technical implementation and business domain.
本技能基于Rich Hickey的面向数据设计原则和Scott Wlaschin的类型驱动设计方法,为领域建模提供指导。重点在于构建无法表示非法状态的系统,优先考虑数据与转换而非对象与方法,并建立连接技术实现与业务领域的通用语言。

Core Principles

核心原则

Rich Hickey's Data-Oriented Design

Rich Hickey的面向数据设计

Simplicity over Ease
  • Favor simple constructs that can be understood independently
  • Avoid complecting (intertwining) unrelated concerns
  • Separate policy from mechanism, data from behavior
Data is King
  • Model the domain using pure data structures, not objects with behavior
  • Prefer generic data structures (maps, sets, vectors) over custom classes when appropriate
  • Data should be self-describing and inspectable
  • Functions transform data; data does not execute behavior
Value of Values
  • Use immutable values to represent facts
  • Values enable local reasoning and simple equality
  • Values can be freely shared without coordination
  • Consider: what are the immutable facts in this domain?
Decomplecting
  • Identify what is truly essential to the domain vs. incidental complexity
  • Separate when-it-happens from what-happens
  • Separate mechanism from policy
  • Question: are these concerns actually separate, or have we tangled them?
简洁优于易用
  • 优先选择可独立理解的简单结构
  • 避免将无关关注点耦合(交织)在一起
  • 将策略与机制分离,数据与行为分离
数据为王
  • 使用纯数据结构而非带行为的对象来建模领域
  • 在合适的情况下,优先使用通用数据结构(映射、集合、向量)而非自定义类
  • 数据应具备自描述性且可被检查
  • 函数转换数据;数据不执行行为
值的价值
  • 使用不可变值来表示事实
  • 值支持本地推理和简单的相等性判断
  • 值无需协调即可自由共享
  • 思考:该领域中哪些是不可变的事实?
解耦
  • 识别领域中真正必要的部分与附带的复杂性
  • 将“何时发生”与“发生了什么”分离
  • 将机制与策略分离
  • 提问:这些关注点真的是独立的,还是我们把它们缠在一起了?

Scott Wlaschin's Type-Driven Design

Scott Wlaschin的类型驱动设计

Make Illegal States Unrepresentable
  • Use the type system to eliminate invalid states at compile time
  • Model optional values explicitly (Option/Maybe types)
  • Use sum types (discriminated unions) for states that are mutually exclusive
  • Avoid primitive obsession; create domain-specific types
Domain Modeling Made Functional
  • Model workflows as data transformations: Input → Process → Output
  • Explicitly model business rules as functions
  • Separate validation from business logic
  • Think in terms of: What can happen? What are the valid transitions?
Railway-Oriented Programming
  • Model success and failure paths explicitly (Result types)
  • Chain operations that can fail using bind/flatMap
  • Keep the happy path clear and linear
  • Handle errors at appropriate boundaries
Types as Documentation
  • Type signatures should communicate intent
  • Use newtype wrappers for semantic clarity (UserId, EmailAddress, Timestamp)
  • Constrain inputs to valid ranges using types
  • Let the type system guide API design
使非法状态无法被表示
  • 使用类型系统在编译时消除无效状态
  • 显式建模可选值(Option/Maybe类型)
  • 使用和类型(可区分联合)表示互斥状态
  • 避免原始类型痴迷;创建领域特定类型
函数式领域建模
  • 将工作流建模为数据转换:输入 → 处理 → 输出
  • 将业务规则显式建模为函数
  • 将验证与业务逻辑分离
  • 思考:可能发生什么?有效的状态转换有哪些?
面向铁路编程
  • 显式建模成功与失败路径(Result类型)
  • 使用bind/flatMap链式调用可能失败的操作
  • 保持正常路径清晰且线性
  • 在适当的边界处理错误
类型即文档
  • 类型签名应传达意图
  • 使用新类型包装器提升语义清晰度(UserId、EmailAddress、Timestamp)
  • 使用类型约束输入的有效范围
  • 让类型系统指导API设计

DDD Building Blocks

DDD构建块

Entities vs Value Objects

实体与值对象

Entities are defined by identity, not attributes:
  • Have a unique identifier (ID, account number, etc.)
  • Can change over time while maintaining identity
  • Two entities with same attributes but different IDs are distinct
  • Used when domain experts refer to things by name/ID
Value Objects are defined entirely by attributes:
  • No unique identifier
  • Immutable
  • Two value objects with same attributes are interchangeable
  • Used when only the value matters, not identity
Decision Guide:
  • Ask: Do domain experts refer to this by ID/name? → Entity
  • Ask: Can I replace it with an equivalent copy? → If yes: Value Object
实体由标识而非属性定义:
  • 拥有唯一标识符(ID、账号等)
  • 可随时间变化但保持标识不变
  • 属性相同但ID不同的两个实体是不同的
  • 当领域专家通过名称/ID指代事物时使用
值对象完全由属性定义:
  • 无唯一标识符
  • 不可变
  • 属性相同的两个值对象可互换
  • 当仅关注值而非标识时使用
决策指南:
  • 提问:领域专家是否通过ID/名称指代它?→ 实体
  • 提问:我能否用等效副本替换它?→ 如果是:值对象

Aggregates and Aggregate Roots

聚合与聚合根

Aggregate: A cluster of entities and value objects treated as a single unit for data changes.
Aggregate Root: The single entity through which all external access to the aggregate must pass.
Purpose:
  • Define transactional consistency boundaries
  • Enforce invariants that span multiple objects
  • Simplify the model by grouping related concepts
Rules:
  • External references go only to the aggregate root (use ID references)
  • Root enforces all invariants for the entire aggregate
  • Transactions don't cross aggregate boundaries (use eventual consistency)
  • Keep aggregates small for better performance and scalability
When NOT to create an aggregate:
  • Objects can be modified independently
  • No shared invariants requiring transactional consistency
  • Different objects have different lifecycles
聚合:一组被视为数据变更单一单元的实体和值对象集群。
聚合根:所有外部访问聚合必须通过的单一实体。
目的:
  • 定义事务一致性边界
  • 强制执行跨越多个对象的不变量
  • 通过分组相关概念简化模型
规则:
  • 外部引用仅指向聚合根(使用ID引用)
  • 根为整个聚合强制执行所有不变量
  • 事务不跨越聚合边界(使用最终一致性)
  • 保持聚合小型化以提升性能和可扩展性
不应创建聚合的场景:
  • 对象可独立修改
  • 无需要事务一致性的共享不变量
  • 不同对象有不同的生命周期

Bounded Contexts

限界上下文

Definition: An explicit boundary within which a domain model applies.
Purpose:
  • Divide large domains into manageable pieces
  • Allow same term to have different meanings in different contexts
  • Prevent model corruption from mixing incompatible concepts
Key Insight: Ubiquitous language is only ubiquitous within a context. "Customer" in Sales context may be different from "Customer" in Shipping context.
When modeling:
  • Identify which bounded context you're in
  • Make context boundaries explicit in code structure (separate modules/namespaces)
  • Use anti-corruption layers when integrating across contexts
  • Document relationships between contexts (context map)
定义:领域模型适用的明确边界。
目的:
  • 将大型领域划分为可管理的部分
  • 允许同一术语在不同上下文中有不同含义
  • 防止因混合不兼容概念而导致模型损坏
关键见解:通用语言仅在上下文中通用。销售上下文中的“客户”可能与物流上下文中的“客户”不同。
建模时:
  • 识别你所处的限界上下文
  • 在代码结构中明确上下文边界(独立模块/命名空间)
  • 在跨上下文集成时使用防腐层
  • 记录上下文之间的关系(上下文映射)

Domain Events

领域事件

Definition: Something important that happened in the domain.
Characteristics:
  • Named in past tense (OrderPlaced, PaymentProcessed, UserRegistered)
  • Immutable facts
  • Domain experts care about them
  • Can trigger reactions within or across bounded contexts
Uses:
  • Decouple domain logic
  • Enable eventual consistency between aggregates
  • Integration between bounded contexts
  • Event sourcing (store events as source of truth)
定义:领域中发生的重要事件。
特征:
  • 以过去式命名(OrderPlaced、PaymentProcessed、UserRegistered)
  • 不可变的事实
  • 领域专家关心这些事件
  • 可触发限界上下文内部或之间的响应
用途:
  • 解耦领域逻辑
  • 实现聚合之间的最终一致性
  • 限界上下文之间的集成
  • 事件溯源(将事件作为事实来源存储)

Repositories

仓库

Purpose: Provide illusion of an in-memory collection of aggregates, abstracting persistence.
Characteristics:
  • Operate at aggregate boundaries (load/save whole aggregates)
  • Provide lookup by ID
  • Hide database implementation details
  • Return domain entities, not database rows
Pattern: Application layer uses repository to get/save aggregates; domain layer remains pure.
目的:提供内存中聚合集合的假象,抽象持久化细节。
特征:
  • 在聚合边界操作(加载/保存整个聚合)
  • 提供按ID查找的功能
  • 隐藏数据库实现细节
  • 返回领域实体而非数据库行
模式:应用层使用仓库获取/保存聚合;领域层保持纯函数式。

Domain Modeling Workflow

领域建模工作流

1. Discover the Ubiquitous Language

1. 发现通用语言

Start by identifying the domain concepts, using terminology from domain experts:
Action Items:
  • List nouns (entities, value objects) and verbs (operations, events) from the domain
  • Document domain terms with precise definitions
  • Identify synonyms and resolve ambiguity
  • Ask: What does the business call this? What are the boundaries of this concept?
Output Format: Create a glossary section documenting each term:
markdown
**Term** (Type: Entity/ValueObject/Event/Command)
- Definition: [Clear, domain-expert-approved definition]
- Examples: [Concrete examples]
- Invariants: [Rules that must always hold]
从识别领域概念开始,使用领域专家的术语:
行动项:
  • 列出领域中的名词(实体、值对象)和动词(操作、事件)
  • 记录领域术语的精确定义
  • 识别同义词并解决歧义
  • 提问:业务中如何称呼这个概念?这个概念的边界是什么?
输出格式: 创建术语表部分记录每个术语:
markdown
**术语**(类型:Entity/ValueObject/Event/Command)
- 定义:[经领域专家认可的清晰定义]
- 示例:[具体示例]
- 不变量:[必须始终成立的规则]

2. Analyze the Existing Domain Model

2. 分析现有领域模型

Before making changes, understand the current state:
Exploration Steps:
  • Identify where domain concepts are currently modeled (types, schemas, tables)
  • Map out relationships between domain entities
  • Find where business logic lives (services, functions, stored procedures)
  • Document implicit rules and constraints
  • Note inconsistencies in naming or modeling
Questions to Answer:
  • What types/classes represent domain concepts?
  • What are the invariants? Where are they enforced?
  • Which concepts are tangled together that should be separate?
  • Are there phantom types or states that shouldn't exist?
在进行更改之前,了解当前状态:
探索步骤:
  • 识别当前领域概念的建模位置(类型、模式、表)
  • 绘制领域实体之间的关系图
  • 查找业务逻辑的存放位置(服务、函数、存储过程)
  • 记录隐式规则和约束
  • 注意命名或建模中的不一致性
需要回答的问题:
  • 哪些类型/类表示领域概念?
  • 不变量是什么?在哪里强制执行?
  • 哪些应该分离的概念被缠在一起了?
  • 是否存在不应存在的幽灵类型或状态?

3. Identify Inconsistencies and Smells

3. 识别不一致性与坏味道

Common problems to surface:
Naming Inconsistencies
  • Same concept with different names (User vs Account vs Customer)
  • Different concepts with same name (Order as entity vs Order as command)
  • Technical names bleeding into domain language (DTO, DAO suffixes)
Structural Problems
  • Illegal states being representable (e.g.,
    status: "approved" | "rejected"
    with separate
    approved_at
    and
    rejected_at
    fields that can both be set)
  • Primitive obsession (strings for email, numbers for money)
  • Optional fields that are actually required in certain states
  • Null/undefined used to represent multiple distinct states
Complected Concerns
  • Domain logic mixed with infrastructure (DB access in business logic)
  • Multiple responsibilities in one type/module
  • Temporal coupling (must call A before B or system breaks)
Missing Concepts
  • Domain concepts that exist in conversations but not in code
  • Implicit states that should be explicit
  • Business rules enforced through comments or conventions rather than types
需要发现的常见问题:
命名不一致
  • 同一概念有不同名称(User vs Account vs Customer)
  • 不同概念有相同名称(作为实体的Order vs 作为命令的Order)
  • 技术名称渗透到领域语言中(DTO、DAO后缀)
结构问题
  • 非法状态可被表示(例如,
    status: "approved" | "rejected"
    同时设置了
    approved_at
    rejected_at
    字段)
  • 原始类型痴迷(用字符串表示邮箱,用数字表示金额)
  • 在某些状态下实际必填的可选字段
  • 使用Null/undefined表示多个不同状态
耦合的关注点
  • 领域逻辑与基础设施混合(业务逻辑中包含数据库访问)
  • 单个类型/模块承担多个职责
  • 时间耦合(必须先调用A再调用B,否则系统崩溃)
缺失的概念
  • 存在于对话中但未在代码中建模的领域概念
  • 应显式化的隐式状态
  • 通过注释或约定而非类型强制执行的业务规则

4. Design the Domain Model

4. 设计领域模型

Apply type-driven and data-driven principles:
Data Modeling:
  • Start with the data shape; what are the facts?
  • Use immutable values for facts that don't change
  • Model state transitions explicitly
  • Separate identity from attributes
  • Consider: what varies together? What varies independently?
Type Design:
  • Create sum types for mutually exclusive states:
    type PaymentStatus =
      | Pending
      | Approved { approvedAt: Timestamp, approvedBy: UserId }
      | Rejected { rejectedAt: Timestamp, reason: string }
  • Use product types to ensure all required data is present
  • Create semantic wrappers for primitives:
    type EmailAddress = EmailAddress of string  // with validation
    type Money = { amount: Decimal, currency: Currency }
  • Make impossible states unrepresentable
Workflow Modeling:
  • Model each business workflow as a clear pipeline:
    ValidateInput → ExecuteBusinessLogic → HandleResult → Persist → Notify
  • Identify decision points and model them explicitly
  • Separate pure business logic from effects (IO, time, randomness)
  • Use clear function signatures that document intent
应用类型驱动和数据驱动原则:
数据建模:
  • 从数据形状开始;哪些是事实?
  • 对不变化的事实使用不可变值
  • 显式建模状态转换
  • 将标识与属性分离
  • 思考:哪些内容一起变化?哪些内容独立变化?
类型设计:
  • 为互斥状态创建和类型:
    type PaymentStatus =
      | Pending
      | Approved { approvedAt: Timestamp, approvedBy: UserId }
      | Rejected { rejectedAt: Timestamp, reason: string }
  • 使用积类型确保所有必填数据都存在
  • 为原始类型创建语义包装器:
    type EmailAddress = EmailAddress of string  // 带验证
    type Money = { amount: Decimal, currency: Currency }
  • 使不可能的状态无法被表示
工作流建模:
  • 将每个业务工作流建模为清晰的流水线:
    ValidateInput → ExecuteBusinessLogic → HandleResult → Persist → Notify
  • 识别决策点并显式建模
  • 将纯业务逻辑与副作用(IO、时间、随机性)分离
  • 使用清晰的函数签名传达意图

5. Build and Maintain Ubiquitous Language

5. 构建并维护通用语言

Consistency Rules:
  • Use identical terminology in code, documentation, conversations, and UI
  • When domain language changes, update all representations
  • Avoid technical jargon in domain code (no "factory", "manager", "handler" unless domain terms)
  • Resist the temptation to rename domain concepts for technical convenience
Code Conventions:
  • Domain types should mirror domain language exactly
  • Function names should use domain verbs
  • Module boundaries should follow domain boundaries
  • Comments should explain domain rules, not implementation details
Documentation:
  • Keep the glossary up to date
  • Document why decisions were made (especially constraints and invariants)
  • Link code to domain documentation
  • Make implicit domain rules explicit
一致性规则:
  • 在代码、文档、对话和UI中使用完全相同的术语
  • 当领域语言变化时,更新所有表示形式
  • 避免在领域代码中使用技术术语(除非是领域术语,否则不使用“factory”、“manager”、“handler”)
  • 抵制为了技术便利而重命名领域概念的诱惑
代码约定:
  • 领域类型应完全镜像领域语言
  • 函数名称应使用领域动词
  • 模块边界应遵循领域边界
  • 注释应解释领域规则而非实现细节
文档:
  • 保持术语表更新
  • 记录决策的原因(尤其是约束和不变量)
  • 将代码链接到领域文档
  • 使隐式领域规则显式化

6. Visualize the Domain Model

6. 可视化领域模型

Use diagrams to communicate domain structure and relationships:
Mermaid for Relationships:
mermaid
classDiagram
    Order --> Customer
    Order --> OrderLine
    OrderLine --> Product
    Order --> PaymentStatus

    class Order {
        +OrderId id
        +CustomerId customerId
        +List~OrderLine~ lines
        +PaymentStatus status
    }

    class PaymentStatus {
        <<enumeration>>
        Pending
        Approved
        Rejected
    }
Mermaid for Workflows:
mermaid
graph LR
    A[Receive Order] --> B{Valid?}
    B -->|Yes| C[Calculate Total]
    B -->|No| D[Return Validation Error]
    C --> E[Process Payment]
    E --> F{Payment Success?}
    F -->|Yes| G[Fulfill Order]
    F -->|No| H[Cancel Order]
Mermaid for State Transitions:
mermaid
stateDiagram-v2
    [*] --> Draft
    Draft --> Submitted: submit()
    Submitted --> Approved: approve()
    Submitted --> Rejected: reject()
    Approved --> Fulfilled: fulfill()
    Fulfilled --> [*]
    Rejected --> [*]
Graphviz/DOT for Complex Relationships:
dot
digraph domain {
    rankdir=LR;
    node [shape=box];

    Customer -> Order [label="places"];
    Order -> OrderLine [label="contains"];
    OrderLine -> Product [label="references"];
    Order -> Payment [label="requires"];
    Payment -> PaymentMethod [label="uses"];
}
ASCII for Quick Sketches:
Customer
  └─> Order (1:N)
       ├─> OrderLine (1:N)
       │    └─> Product
       └─> Payment (1:1)
            └─> PaymentMethod
When to Use Each:
  • Mermaid classDiagram: Entity relationships and type structures
  • Mermaid graph/flowchart: Business workflows and decision trees
  • Mermaid stateDiagram: State transitions and lifecycle
  • Graphviz/DOT: Complex dependency graphs, module boundaries
  • ASCII: Quick sketches during discussion, simple hierarchies
使用图表传达领域结构和关系:
用于关系的Mermaid:
mermaid
classDiagram
    Order --> Customer
    Order --> OrderLine
    OrderLine --> Product
    Order --> PaymentStatus

    class Order {
        +OrderId id
        +CustomerId customerId
        +List~OrderLine~ lines
        +PaymentStatus status
    }

    class PaymentStatus {
        <<enumeration>>
        Pending
        Approved
        Rejected
    }
用于工作流的Mermaid:
mermaid
graph LR
    A[Receive Order] --> B{Valid?}
    B -->|Yes| C[Calculate Total]
    B -->|No| D[Return Validation Error]
    C --> E[Process Payment]
    E --> F{Payment Success?}
    F -->|Yes| G[Fulfill Order]
    F -->|No| H[Cancel Order]
用于状态转换的Mermaid:
mermaid
stateDiagram-v2
    [*] --> Draft
    Draft --> Submitted: submit()
    Submitted --> Approved: approve()
    Submitted --> Rejected: reject()
    Approved --> Fulfilled: fulfill()
    Fulfilled --> [*]
    Rejected --> [*]
用于复杂关系的Graphviz/DOT:
dot
digraph domain {
    rankdir=LR;
    node [shape=box];

    Customer -> Order [label="places"];
    Order -> OrderLine [label="contains"];
    OrderLine -> Product [label="references"];
    Order -> Payment [label="requires"];
    Payment -> PaymentMethod [label="uses"];
}
用于快速草图的ASCII:
Customer
  └─> Order (1:N)
       ├─> OrderLine (1:N)
       │    └─> Product
       └─> Payment (1:1)
            └─> PaymentMethod
各图表的适用场景:
  • Mermaid classDiagram:实体关系和类型结构
  • Mermaid graph/flowchart:业务工作流和决策树
  • Mermaid stateDiagram:状态转换和生命周期
  • Graphviz/DOT:复杂依赖图、模块边界
  • ASCII:讨论中的快速草图、简单层次结构

Domain Modeling Anti-Patterns

领域建模反模式

Anemic Domain Model
  • Symptom: Data structures with getters/setters, all logic in separate services
  • Problem: Violates data-orientation by adding ceremony without encapsulation benefits
  • Solution: Keep data as data; put related transformations in same module but separate from data definition
Entity Services Anti-Pattern
  • Symptom: Classes like
    UserService
    ,
    OrderManager
    ,
    ProductFactory
  • Problem: Hides actual operations; lacks ubiquitous language
  • Solution: Name functions after domain operations:
    approveOrder
    ,
    cancelSubscription
    ,
    calculateDiscount
Primitive Obsession
  • Symptom: String for email, number for money, boolean flags for states
  • Problem: No type safety; invalid values representable
  • Solution: Create semantic types with validation
Accidental Complexity
  • Symptom: Complex abstractions, design patterns without clear domain benefit
  • Problem: Adds layers that obscure domain meaning
  • Solution: Simplify; prefer composition over inheritance; avoid premature abstraction
Hidden Temporal Coupling
  • Symptom: Must call methods in specific order or system breaks
  • Problem: Complects workflow with state management
  • Solution: Make workflow explicit; use types to enforce valid transitions
Boolean Blindness
  • Symptom: Boolean flags to represent states (isApproved, isActive, isDeleted)
  • Problem: Multiple booleans can represent impossible states
  • Solution: Use sum types for mutually exclusive states
贫血领域模型
  • 症状:带getter/setter的数据结构,所有逻辑在独立服务中
  • 问题:通过添加仪式化代码违反面向数据原则,却未获得封装收益
  • 解决方案:将数据保持为纯数据;将相关转换放在同一模块但与数据定义分离
实体服务反模式
  • 症状:如
    UserService
    OrderManager
    ProductFactory
    这类类
  • 问题:隐藏实际操作;缺乏通用语言
  • 解决方案:使用领域操作命名函数:
    approveOrder
    cancelSubscription
    calculateDiscount
原始类型痴迷
  • 症状:用字符串表示邮箱,用数字表示金额,用布尔值表示状态
  • 问题:无类型安全性;可表示无效值
  • 解决方案:创建带验证的语义类型
附带复杂性
  • 症状:无明确领域收益的复杂抽象、设计模式
  • 问题:添加的层级掩盖了领域含义
  • 解决方案:简化;优先组合而非继承;避免过早抽象
隐藏的时间耦合
  • 症状:必须按特定顺序调用方法否则系统崩溃
  • 问题:将工作流与状态管理耦合
  • 解决方案:显式建模工作流;使用类型强制执行有效转换
布尔盲
  • 症状:用布尔标志表示状态(isApproved、isActive、isDeleted)
  • 问题:多个布尔值可表示不可能的状态
  • 解决方案:对互斥状态使用和类型

Contextualizing Within Existing Models

在现有模型中融入新内容

When adding to or changing an existing domain model:
  1. Map Current State: Document existing types, relationships, and patterns
  2. Identify Affected Concepts: Which existing concepts does this change touch?
  3. Check Consistency: Does new design follow existing patterns? If not, why?
  4. Assess Impact: What breaks if we make this change?
  5. Migration Path: How do we evolve from current to desired state?
  6. Update Ubiquitous Language: Ensure all usage points are updated
  7. Visualize Before/After: Create diagrams showing current and proposed models
Key Questions:
  • Does this change align with existing domain boundaries?
  • Are we using consistent terminology?
  • Does this introduce new concepts or reuse existing ones?
  • Are we fixing an inconsistency or introducing a new one?
  • Can we make this change incrementally?
当添加或更改现有领域模型时:
  1. 映射当前状态:记录现有类型、关系和模式
  2. 识别受影响的概念:此更改会涉及哪些现有概念?
  3. 检查一致性:新设计是否遵循现有模式?如果不遵循,原因是什么?
  4. 评估影响:进行此更改会破坏什么?
  5. 迁移路径:如何从当前状态演进到目标状态?
  6. 更新通用语言:确保所有使用点都已更新
  7. 可视化前后对比:创建图表显示当前和提议的模型
关键问题:
  • 此更改是否与现有领域边界对齐?
  • 我们是否使用一致的术语?
  • 我们是引入新概念还是重用现有概念?
  • 我们是在修复不一致性还是引入新的不一致性?
  • 我们能否增量式进行此更改?

Checklist for Domain Modeling

领域建模检查清单

Before completing domain modeling work:
Language & Communication:
  • All domain concepts are named using ubiquitous language
  • Domain glossary is updated with new/changed terms
  • All code, docs, and conversations use identical terminology
  • Bounded context is clearly identified and documented
Type Design:
  • Types make illegal states unrepresentable
  • No primitive obsession; semantic types are used appropriately
  • Entities have clear identity; value objects are immutable
  • Sum types used for mutually exclusive states
Domain Logic:
  • Business rules are explicit and testable
  • Data and behavior are appropriately separated
  • Workflows are modeled as clear data transformations
  • Domain logic is pure (no side effects)
  • Temporal coupling is eliminated or made explicit
Aggregates & Boundaries:
  • Aggregate boundaries are explicit
  • Aggregates enforce their invariants
  • External references to aggregates use IDs only
  • Aggregates are kept small and focused
  • Transactional boundaries are appropriate
Consistency & Integration:
  • Inconsistencies with existing model are resolved or documented
  • Cross-aggregate consistency strategy is defined (transactional vs eventual)
  • Domain events are used for important occurrences
  • Integration between bounded contexts uses anti-corruption layers
Documentation:
  • Visualization diagrams clearly communicate the design
  • Key decisions and invariants are documented
  • Context map shows relationships between bounded contexts
完成领域建模工作前:
语言与沟通:
  • 所有领域概念都使用通用语言命名
  • 领域术语表已更新新增/更改的术语
  • 所有代码、文档和对话使用完全相同的术语
  • 限界上下文已明确识别并记录
类型设计:
  • 类型使非法状态无法被表示
  • 无原始类型痴迷;已适当使用语义类型
  • 实体有清晰的标识;值对象是不可变的
  • 对互斥状态使用了和类型
领域逻辑:
  • 业务规则显式且可测试
  • 数据与行为已适当分离
  • 工作流被建模为清晰的数据转换
  • 领域逻辑是纯函数式的(无副作用)
  • 时间耦合已消除或显式化
聚合与边界:
  • 聚合边界已明确
  • 聚合强制执行其不变量
  • 对聚合的外部引用仅使用ID
  • 聚合保持小型且聚焦
  • 事务边界适当
一致性与集成:
  • 与现有模型的不一致性已解决或记录
  • 跨聚合一致性策略已定义(事务性 vs 最终一致性)
  • 领域事件已用于重要事件
  • 限界上下文之间的集成使用了防腐层
文档:
  • 可视化图表清晰传达设计
  • 关键决策和不变量已记录
  • 上下文映射显示了限界上下文之间的关系

Resources

资源

references/

references/

This skill includes reference documentation for deeper exploration:
  • ddd_foundations_and_patterns.md: Eric Evans' foundational DDD concepts (entities, value objects, aggregates, bounded contexts, repositories, domain events), Martin Fowler's Ubiquitous Language guidance, and practical Clojure/functional patterns. Essential reading for understanding DDD building blocks and how to apply them.
  • rich_hickey_principles.md: Core concepts from Rich Hickey's talks including Simple Made Easy, Value of Values, and The Language of the System. Focus on data-oriented design, simplicity, decomplecting, and the power of immutable values.
  • wlaschin_patterns.md: Scott Wlaschin's type-driven design patterns, domain modeling recipes, functional architecture guidance, and railway-oriented programming. Emphasis on making illegal states unrepresentable and designing with types.
  • visualization_examples.md: Comprehensive examples of Mermaid, Graphviz, and ASCII diagram patterns for domain modeling. Includes entity relationships, workflows, state machines, aggregate boundaries, and bounded context maps.
Load these references when deeper context is needed on specific principles or patterns.
本技能包含用于深入探索的参考文档:
  • ddd_foundations_and_patterns.md:Eric Evans的基础DDD概念(实体、值对象、聚合、限界上下文、仓库、领域事件),Martin Fowler的通用语言指导,以及实用的Clojure/函数式模式。是理解DDD构建块及其应用的必读内容。
  • rich_hickey_principles.md:Rich Hickey演讲中的核心概念,包括《Simple Made Easy》、《Value of Values》和《The Language of the System》。重点是面向数据设计、简洁性、解耦和不可变值的力量。
  • wlaschin_patterns.md:Scott Wlaschin的类型驱动设计模式、领域建模方法、函数式架构指导和面向铁路编程。强调使非法状态无法被表示和用类型进行设计。
  • visualization_examples.md:用于领域建模的Mermaid、Graphviz和ASCII图表模式的综合示例。包括实体关系、工作流、状态机、聚合边界和限界上下文映射。
当需要特定原则或模式的更深入上下文时,加载这些参考文档。",