m09-domain by zhanghandong/rust-skills
npx skills add https://github.com/zhanghandong/rust-skills --skill m09-domain第 2 层:设计选择
这个概念在领域中的角色是什么?
在代码中建模之前,需要理解:
| 领域概念 | Rust 模式 | 所有权含义 |
|---|---|---|
| 实体 | struct + Id | 拥有,唯一身份 |
| 值对象 | struct + Clone/Copy | 可共享,不可变 |
| 聚合根 | struct 拥有子项 | 清晰的所有权树 |
| 仓储 | trait | 抽象持久化 |
| 领域事件 | enum | 捕获状态变化 |
| 服务 | impl 块 / 自由函数 |
广告位招租
在这里展示您的产品或服务
触达数万 AI 开发者,精准高效
| 无状态操作 |
在创建领域类型之前:
* 需要唯一身份 → 实体(Id 字段)
* 按值可互换 → 值对象(Clone/Copy)
2. 必须保持哪些不变条件?
* 始终有效 → 私有字段 + 验证过的构造函数
* 转换规则 → 类型状态模式
3. 谁拥有这些数据?
* 单一所有者(父级) → 拥有的字段
* 共享引用 → Arc/Rc
* 弱引用 → Weak
到领域约束(第 3 层):
"我应该如何建模一个交易?"
↑ 问:哪些领域规则管理交易?
↑ 检查:domain-fintech(审计、精度要求)
↑ 检查:业务相关方(哪些不变条件?)
| 设计问题 | 追溯至 | 提问 |
|---|---|---|
| 实体 vs 值对象 | domain-* | 什么使两个实例"相同"? |
| 聚合边界 | domain-* | 什么必须保持一致? |
| 验证规则 | domain-* | 适用哪些业务规则? |
到实现(第 1 层):
"建模为实体"
↓ m01-ownership: 拥有,唯一
↓ m05-type-driven: Id 使用新类型
"建模为值对象"
↓ m01-ownership: Clone/Copy 可行
↓ m05-type-driven: 在构造时验证
"建模为聚合"
↓ m01-ownership: 父级拥有子项
↓ m02-resource: 考虑在聚合内共享时使用 Rc
| DDD 概念 | Rust 模式 | 示例 |
|---|---|---|
| 值对象 | 新类型 | struct Email(String); |
| 实体 | 结构体 + ID | struct User { id: UserId, ... } |
| 聚合 | 模块边界 | mod order { ... } |
| 仓储 | 特征 | trait UserRepo { fn find(...) } |
| 领域事件 | 枚举 | enum OrderEvent { Created, ... } |
struct Email(String);
impl Email {
pub fn new(s: &str) -> Result<Self, ValidationError> {
validate_email(s)?;
Ok(Self(s.to_string()))
}
}
struct UserId(Uuid);
struct User {
id: UserId,
email: Email,
// ... 其他字段
}
impl PartialEq for User {
fn eq(&self, other: &Self) -> bool {
self.id == other.id // 身份相等性
}
}
mod order {
pub struct Order {
id: OrderId,
items: Vec<OrderItem>, // 拥有的子项
// ...
}
impl Order {
pub fn add_item(&mut self, item: OrderItem) {
// 强制执行聚合不变条件
}
}
}
| 错误 | 为何错误 | 更好的做法 |
|---|---|---|
| 原始类型偏执 | 没有类型安全 | 新类型包装器 |
| 带有不变条件的公共字段 | 不变条件被破坏 | 私有字段 + 访问器 |
| 泄露聚合内部结构 | 封装被破坏 | 根上的方法 |
| 使用字符串表示语义类型 | 没有验证 | 经过验证的新类型 |
| 何时 | 参见 |
|---|---|
| 类型驱动实现 | m05-type-driven |
| 聚合的所有权 | m01-ownership |
| 领域错误处理 | m13-domain-error |
| 特定领域规则 | domain-* |
每周安装量
597
代码仓库
GitHub 星标数
920
首次出现
2026年1月20日
安全审计
安装于
opencode549
codex534
gemini-cli525
github-copilot512
amp467
kimi-cli462
Layer 2: Design Choices
What is this concept's role in the domain?
Before modeling in code, understand:
| 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 |
Before creating a domain type:
What's the concept's identity?
What invariants must hold?
Who owns this data?
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? |
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
| DDD Concept | Rust Pattern | Example |
|---|---|---|
| Value Object | Newtype | struct Email(String); |
| Entity | Struct + ID | struct User { id: UserId, ... } |
| Aggregate | Module boundary | mod order { ... } |
| Repository | Trait | trait UserRepo { fn find(...) } |
| Domain Event | Enum | enum OrderEvent { Created, ... } |
struct Email(String);
impl Email {
pub fn new(s: &str) -> Result<Self, ValidationError> {
validate_email(s)?;
Ok(Self(s.to_string()))
}
}
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
}
}
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
}
}
}
| 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 |
| When | See |
|---|---|
| Type-driven implementation | m05-type-driven |
| Ownership for aggregates | m01-ownership |
| Domain error handling | m13-domain-error |
| Specific domain rules | domain-* |
Weekly Installs
597
Repository
GitHub Stars
920
First Seen
Jan 20, 2026
Security Audits
Gen Agent Trust HubPassSocketPassSnykPass
Installed on
opencode549
codex534
gemini-cli525
github-copilot512
amp467
kimi-cli462
React 组合模式指南:Vercel 组件架构最佳实践,提升代码可维护性
103,800 周安装
OpenAPI 转 TypeScript 工具 - 自动生成 API 接口与类型守卫
563 周安装
数据库模式设计器 - 内置最佳实践,自动生成生产级SQL/NoSQL数据库架构
564 周安装
Rust Unsafe代码检查器 - 安全使用Unsafe Rust的完整指南与最佳实践
564 周安装
.NET并发编程模式指南:async/await、Channels、Akka.NET选择决策树
565 周安装
韩语语法检查器 - 基于国立国语院标准的拼写、空格、语法、标点错误检测与纠正
565 周安装
技能安全扫描器 - 检测Claude技能安全漏洞,防范提示注入与恶意代码
565 周安装