mcpField
M
m05-type-driven

m05-type-driven

github.com/actionbook开发1.6k3.4k 次安装9 周前更新
代码仓库

关于 m05-type-driven

面向 Rust 设计的技能,讲解如何用类型表达不变量并避免无效状态。内容涵盖从 newtype 到 Builder 和类型状态模式的选择。

主要功能

  1. 01用类型表达约束
  2. 02选择常见类型模式
  3. 03应用类型状态设计
  4. 04识别类型设计反模式

适用场景

  1. 01用 newtype 表示语义值
  2. 02建模编译期状态转换
  3. 03选择已验证构造模式

安装

复制下面的命令,在终端中运行。

$npx skills add https://github.com/actionbook/rust-skills --skill m05-type-driven

安装后在 Claude Code 中输入/m05-type-driven确认已加载。

详细介绍

类型驱动设计

第 1 层:语言机制

核心问题

类型系统如何防止无效状态?

在使用运行时检查之前:

  • 编译器能否捕获此错误?
  • 能否让无效状态无法表示?
  • 类型能否编码这一不变量?

错误 → 设计问题

模式不要只说转而询问
基本类型痴迷“这只是一个字符串”这个值代表什么?
布尔标志“添加一个 is_valid 标志”能否将状态表示为类型?
到处使用可选值“检查是否为 None”真的可能缺失吗?
运行时验证“无效时返回 Err”能否在构造时验证?

思考提示

在添加运行时验证之前:

  1. 类型能否编码约束?

    • 数值范围 → 有界类型或 newtype
    • 有效状态 → 类型状态模式
    • 语义含义 → newtype
  2. 何时可以进行验证?

    • 构造时 → 已验证的 newtype
    • 状态转换时 → 类型状态
    • 只能在运行时 → 返回明确错误的 Result
  3. 谁需要了解这个不变量?

    • 编译器 → 类型级编码
    • API 用户 → 清晰的类型签名
    • 仅运行时 → 文档

向上追溯 ↑

类型设计不明确时:

"Need to validate email format"
    ↑ Ask: Is this a domain value object?
    ↑ Check: m09-domain (Email as Value Object)
    ↑ Check: domain-* (validation requirements)
情况追溯到问题
要创建哪些类型m09-domain领域模型是什么?
状态机设计m09-domain有哪些有效转换?
标记 trait 的使用m04-zero-cost静态还是动态分派?

向下追溯 ↓

从设计到实现:

"Need type-safe wrapper for primitives"
    ↓ Newtype: struct UserId(u64);

"Need compile-time state validation"
    ↓ Type State: Connection<Connected>

"Need to track phantom type parameters"
    ↓ PhantomData: PhantomData<T>

"Need capability markers"
    ↓ Marker Trait: trait Validated {}

"Need gradual construction"
    ↓ Builder: Builder::new().field(x).build()

快速参考

模式用途示例
Newtype类型安全struct UserId(u64);
类型状态状态机Connection<Connected>
PhantomData方差/生命周期PhantomData<&'a T>
标记 Trait能力标志trait Validated {}
Builder渐进式构造Builder::new().name("x").build()
密封 Trait阻止外部实现mod private { pub trait Sealed {} }

模式示例

Newtype
struct Email(String);  // Not just any string

impl Email {
    pub fn new(s: &str) -> Result<Self, ValidationError> {
        // Validate once, trust forever
        validate_email(s)?;
        Ok(Self(s.to_string()))
    }
}
类型状态
struct Connection<State>(TcpStream, PhantomData<State>);

struct Disconnected;
struct Connected;
struct Authenticated;

impl Connection<Disconnected> {
    fn connect(self) -> Connection<Connected> { ... }
}

impl Connection<Connected> {
    fn authenticate(self) -> Connection<Authenticated> { ... }
}

决策指南

需求模式
基本类型的类型安全Newtype
编译时状态验证类型状态
生命周期/方差标记PhantomData
能力标志标记 Trait
渐进式构造Builder
封闭的实现集合密封 Trait
零大小类型标记ZST struct

反模式

反模式问题更好的做法
用布尔标志表示状态运行时错误类型状态
用字符串表示语义类型没有类型安全Newtype
用 Option 表示未初始化不变量不明确Builder
带不变量的公开字段违反不变量私有字段 + 经验证的 new()

相关技能

适用场景查看
领域建模m09-domain
Trait 设计m04-zero-cost
构造函数中的错误处理m06-error-handling
反模式m15-anti-pattern

评论

支持 Markdown