m09-domain
Compare original and translation side by side
🇺🇸
Original
English🇨🇳
Translation
ChineseDomain 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 Concept | Rust Pattern | Ownership Implication |
|---|---|---|
| Entity | struct + Id | Owned, unique identity |
| Value Object | struct + Clone/Copy | Shareable, immutable |
| Aggregate Root | struct owns children | Clear ownership tree |
| Repository | trait | Abstracts persistence |
| Domain Event | enum | Captures state changes |
| Service | impl block / free fn | Stateless operations |
| 领域概念 | Rust模式 | 所有权说明 |
|---|---|---|
| Entity | struct + Id | 自有、唯一标识 |
| Value Object | struct + Clone/Copy | 可共享、不可变 |
| Aggregate Root | struct owns children | 清晰的所有权树 |
| Repository | trait | 抽象持久化 |
| Domain Event | enum | 捕获状态变更 |
| Service | impl block / free fn | 无状态操作 |
Thinking Prompt
思考提示
Before creating a domain type:
-
What's the concept's identity?
- Needs unique identity → Entity (Id field)
- Interchangeable by value → Value Object (Clone/Copy)
-
What invariants must hold?
- Always valid → private fields + validated constructor
- Transition rules → type state pattern
-
Who owns this data?
- Single owner (parent) → owned field
- Shared reference → Arc/Rc
- Weak reference → Weak
在创建领域类型前:
-
该概念的标识是什么?
- 需要唯一标识 → Entity(含Id字段)
- 可按值互换 → Value Object(实现Clone/Copy)
-
必须保持哪些不变量?
- 始终有效 → 私有字段 + 已验证的构造函数
- 转换规则 → 类型状态模式
-
谁拥有该数据?
- 单一所有者(父级) → 自有字段
- 共享引用 → 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 Question | Trace To | Ask |
|---|---|---|
| Entity vs Value Object | domain-* | What makes two instances "the same"? |
| Aggregate boundaries | domain-* | What must be consistent together? |
| Validation rules | domain-* | What business rules apply? |
到领域约束(第3层):
"我应该如何建模Transaction?"
↑ 提问:哪些领域规则管控交易?
↑ 检查:domain-fintech(审计、精度要求)
↑ 检查:业务相关人员(有哪些不变量?)| 设计问题 | 追溯至 | 提问 |
|---|---|---|
| Entity vs Value Object | domain-* | 什么让两个实例“相同”? |
| 聚合边界 | 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 Concept | Rust Pattern | Example |
|---|---|---|
| Value Object | Newtype | |
| Entity | Struct + ID | |
| Aggregate | Module boundary | |
| Repository | Trait | |
| Domain Event | Enum | |
| DDD概念 | Rust模式 | 示例 |
|---|---|---|
| Value Object | Newtype | |
| Entity | Struct + ID | |
| Aggregate | 模块边界 | |
| Repository | Trait | |
| Domain Event | Enum | |
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
常见错误
| Mistake | Why Wrong | Better |
|---|---|---|
| Primitive obsession | No type safety | Newtype wrappers |
| Public fields with invariants | Invariants violated | Private + accessor |
| Leaked aggregate internals | Broken encapsulation | Methods on root |
| String for semantic types | No validation | Validated newtype |
| 错误 | 原因 | 优化方案 |
|---|---|---|
| 原始类型滥用 | 无类型安全性 | 使用Newtype包装器 |
| 带不变量的公共字段 | 不变量可能被破坏 | 私有字段 + 访问器 |
| 暴露聚合内部细节 | 破坏封装性 | 在根实体上实现方法 |
| 用字符串表示语义类型 | 无验证 | 已验证的Newtype |
Related Skills
相关技能
| When | See |
|---|---|
| Type-driven implementation | m05-type-driven |
| Ownership for aggregates | m01-ownership |
| Domain error handling | m13-domain-error |
| Specific domain rules | domain-* |
| 场景 | 参考 |
|---|---|
| 类型驱动实现 | m05-type-driven |
| 聚合的所有权 | m01-ownership |
| 领域错误处理 | m13-domain-error |
| 特定领域规则 | domain-* |