m09-domain

Compare original and translation side by side

🇺🇸

Original

English
🇨🇳

Translation

Chinese

Domain Modeling

领域建模

Layer 2: Design Choices
第2层:设计选择

Core Question

核心问题

What is this concept's role in the domain?
Before modeling in code, understand:
  • Is it an Entity (identity matters) or Value Object (interchangeable)?
  • What invariants must be maintained?
  • Where are the aggregate boundaries?

该概念在领域中的角色是什么?
在进行代码建模前,需明确:
  • 它是Entity(标识至关重要)还是Value Object(可互换)?
  • 必须维护哪些不变量?
  • 聚合边界在哪里?

Domain Concept → Rust Pattern

领域概念 → Rust模式

Domain ConceptRust PatternOwnership Implication
Entitystruct + IdOwned, unique identity
Value Objectstruct + Clone/CopyShareable, immutable
Aggregate Rootstruct owns childrenClear ownership tree
RepositorytraitAbstracts persistence
Domain EventenumCaptures state changes
Serviceimpl block / free fnStateless operations

领域概念Rust模式所有权说明
Entitystruct + Id自有、唯一标识
Value Objectstruct + Clone/Copy可共享、不可变
Aggregate Rootstruct owns children清晰的所有权树
Repositorytrait抽象持久化
Domain Eventenum捕获状态变更
Serviceimpl block / free fn无状态操作

Thinking Prompt

思考提示

Before creating a domain type:
  1. What's the concept's identity?
    • Needs unique identity → Entity (Id field)
    • Interchangeable by value → Value Object (Clone/Copy)
  2. What invariants must hold?
    • Always valid → private fields + validated constructor
    • Transition rules → type state pattern
  3. Who owns this data?
    • Single owner (parent) → owned field
    • Shared reference → Arc/Rc
    • Weak reference → Weak

在创建领域类型前:
  1. 该概念的标识是什么?
    • 需要唯一标识 → Entity(含Id字段)
    • 可按值互换 → Value Object(实现Clone/Copy)
  2. 必须保持哪些不变量?
    • 始终有效 → 私有字段 + 已验证的构造函数
    • 转换规则 → 类型状态模式
  3. 谁拥有该数据?
    • 单一所有者(父级) → 自有字段
    • 共享引用 → Arc/Rc
    • 弱引用 → Weak

Trace Up ↑

向上追溯 ↑

To domain constraints (Layer 3):
"How should I model a Transaction?"
    ↑ Ask: What domain rules govern transactions?
    ↑ Check: domain-fintech (audit, precision requirements)
    ↑ Check: Business stakeholders (what invariants?)
Design QuestionTrace ToAsk
Entity vs Value Objectdomain-*What makes two instances "the same"?
Aggregate boundariesdomain-*What must be consistent together?
Validation rulesdomain-*What business rules apply?

到领域约束(第3层):
"我应该如何建模Transaction?"
    ↑ 提问:哪些领域规则管控交易?
    ↑ 检查:domain-fintech(审计、精度要求)
    ↑ 检查:业务相关人员(有哪些不变量?)
设计问题追溯至提问
Entity vs Value Objectdomain-*什么让两个实例“相同”?
聚合边界domain-*哪些内容必须保持一致?
验证规则domain-*适用哪些业务规则?

Trace Down ↓

向下追溯 ↓

To implementation (Layer 1):
"Model as Entity"
    ↓ m01-ownership: Owned, unique
    ↓ m05-type-driven: Newtype for Id

"Model as Value Object"
    ↓ m01-ownership: Clone/Copy OK
    ↓ m05-type-driven: Validate at construction

"Model as Aggregate"
    ↓ m01-ownership: Parent owns children
    ↓ m02-resource: Consider Rc for shared within aggregate

到实现(第1层):
"建模为Entity"
    ↓ m01-ownership: 自有、唯一
    ↓ m05-type-driven: 为Id使用Newtype

"建模为Value Object"
    ↓ m01-ownership: 可实现Clone/Copy
    ↓ m05-type-driven: 在构造时验证

"建模为Aggregate"
    ↓ m01-ownership: 父级拥有子级
    ↓ m02-resource: 考虑在聚合内使用Rc实现共享

Quick Reference

快速参考

DDD ConceptRust PatternExample
Value ObjectNewtype
struct Email(String);
EntityStruct + ID
struct User { id: UserId, ... }
AggregateModule boundary
mod order { ... }
RepositoryTrait
trait UserRepo { fn find(...) }
Domain EventEnum
enum OrderEvent { Created, ... }
DDD概念Rust模式示例
Value ObjectNewtype
struct Email(String);
EntityStruct + ID
struct User { id: UserId, ... }
Aggregate模块边界
mod order { ... }
RepositoryTrait
trait UserRepo { fn find(...) }
Domain EventEnum
enum OrderEvent { Created, ... }

Pattern Templates

模式模板

Value Object

Value Object

rust
struct Email(String);

impl Email {
    pub fn new(s: &str) -> Result<Self, ValidationError> {
        validate_email(s)?;
        Ok(Self(s.to_string()))
    }
}
rust
struct Email(String);

impl Email {
    pub fn new(s: &str) -> Result<Self, ValidationError> {
        validate_email(s)?;
        Ok(Self(s.to_string()))
    }
}

Entity

Entity

rust
struct UserId(Uuid);

struct User {
    id: UserId,
    email: Email,
    // ... other fields
}

impl PartialEq for User {
    fn eq(&self, other: &Self) -> bool {
        self.id == other.id  // Identity equality
    }
}
rust
struct UserId(Uuid);

struct User {
    id: UserId,
    email: Email,
    // ... 其他字段
}

impl PartialEq for User {
    fn eq(&self, other: &Self) -> bool {
        self.id == other.id  // 标识相等性
    }
}

Aggregate

Aggregate

rust
mod order {
    pub struct Order {
        id: OrderId,
        items: Vec<OrderItem>,  // Owned children
        // ...
    }

    impl Order {
        pub fn add_item(&mut self, item: OrderItem) {
            // Enforce aggregate invariants
        }
    }
}

rust
mod order {
    pub struct Order {
        id: OrderId,
        items: Vec<OrderItem>,  // 自有子级
        // ...
    }

    impl Order {
        pub fn add_item(&mut self, item: OrderItem) {
            // 强制执行聚合不变量
        }
    }
}

Common Mistakes

常见错误

MistakeWhy WrongBetter
Primitive obsessionNo type safetyNewtype wrappers
Public fields with invariantsInvariants violatedPrivate + accessor
Leaked aggregate internalsBroken encapsulationMethods on root
String for semantic typesNo validationValidated newtype

错误原因优化方案
原始类型滥用无类型安全性使用Newtype包装器
带不变量的公共字段不变量可能被破坏私有字段 + 访问器
暴露聚合内部细节破坏封装性在根实体上实现方法
用字符串表示语义类型无验证已验证的Newtype

Related Skills

相关技能

WhenSee
Type-driven implementationm05-type-driven
Ownership for aggregatesm01-ownership
Domain error handlingm13-domain-error
Specific domain rulesdomain-*
场景参考
类型驱动实现m05-type-driven
聚合的所有权m01-ownership
领域错误处理m13-domain-error
特定领域规则domain-*