名称: m15-反模式 description: “在审查代码时用于识别反模式。关键词:反模式,常见错误,陷阱,代码异味,不良实践,代码审查,这是反模式吗,更好的做法,应避免的常见错误,为什么这不好,地道写法,初学者错误,与借用检查器斗争,到处克隆,生产环境使用unwrap,是否应该重构” 用户可调用: false
反模式
第二层:设计选择
核心问题
这个模式是否掩盖了设计问题?
审查代码时:
- 这是在解决症状还是原因?
- 是否有更地道的做法?
- 这是在与Rust对抗还是顺应Rust?
反模式 → 更好的模式
| 反模式 | 为什么不好 | 更好的做法 |
|---|---|---|
到处使用 .clone() |
掩盖所有权问题 | 正确的引用或所有权 |
生产环境使用 .unwrap() |
运行时恐慌 | ?、expect 或错误处理 |
单一所有者时使用 Rc |
不必要的开销 | 简单的所有权 |
为方便使用 unsafe |
UB风险 | 寻找安全模式 |
通过 Deref 实现OOP |
误导性API | 组合、特征 |
| 巨大的match分支 | 难以维护 | 提取到方法中 |
到处使用 String |
分配浪费 | &str、Cow<str> |
忽略 #[must_use] |
丢失错误 | 处理或 let _ = |
思考提示
看到可疑代码时:
-
这是症状还是原因?
- 克隆以避免借用? → 所有权设计问题
- 解包“因为它不会失败”? → 未处理的情况
-
地道的代码应该是什么样子?
- 使用引用而不是克隆
- 使用迭代器而不是索引循环
- 使用模式匹配而不是标志
-
这是在与Rust对抗吗?
- 与借用检查器斗争 → 重构结构
- 过度使用unsafe → 寻找安全模式
向上追溯 ↑
为了理解设计:
“为什么我的代码有这么多克隆?”
↑ 问:所有权模型正确吗?
↑ 检查:m09-领域(数据流设计)
↑ 检查:m01-所有权(引用模式)
| 反模式 | 追溯至 | 问题 |
|---|---|---|
| 到处克隆 | m01-所有权 | 谁应该拥有这些数据? |
| 到处解包 | m06-错误处理 | 错误策略是什么? |
| 到处使用Rc | m09-领域 | 所有权清晰吗? |
| 与生命周期斗争 | m09-领域 | 数据结构应该改变吗? |
向下追溯 ↓
到实现(第一层):
“用正确的所有权替换克隆”
↓ m01-所有权:引用模式
↓ m02-资源:如果需要,使用智能指针
“用正确的处理替换解包”
↓ m06-错误处理:? 运算符
↓ m06-错误处理:带消息的expect
前5个初学者错误
| 排名 | 错误 | 修复 |
|---|---|---|
| 1 | 克隆以逃避借用检查器 | 使用引用 |
| 2 | 生产环境使用unwrap | 使用 ? 传播 |
| 3 | 到处使用String | 使用 &str |
| 4 | 索引循环 | 使用迭代器 |
| 5 | 与生命周期斗争 | 重构以拥有数据 |
代码异味 → 重构
| 异味 | 表明 | 重构 |
|---|---|---|
大量 .clone() |
所有权不清晰 | 澄清数据流 |
大量 .unwrap() |
缺少错误处理 | 添加正确的处理 |
大量 pub 字段 |
封装被破坏 | 私有化 + 访问器 |
| 深度嵌套 | 复杂逻辑 | 提取方法 |
| 长函数 | 多重职责 | 拆分 |
| 巨大枚举 | 缺少抽象 | 特征 + 类型 |
常见错误模式
| 错误 | 反模式原因 | 修复 |
|---|---|---|
| E0382 移动后使用 | 克隆 vs 所有权 | 正确的引用 |
| 生产环境恐慌 | 到处解包 | ?、匹配 |
| 性能缓慢 | 所有文本都用String | &str、Cow |
| 借用检查器斗争 | 错误的结构 | 重构结构 |
| 内存膨胀 | 到处使用Rc/Arc | 简单所有权 |
已弃用 → 更好
| 已弃用 | 更好 |
|---|---|
| 基于索引的循环 | .iter()、.enumerate() |
collect::<Vec<_>>() 然后迭代 |
链式迭代器 |
| 手动不安全单元格 | Cell、RefCell |
用于转换的 mem::transmute |
as 或 TryFrom |
| 自定义链表 | Vec、VecDeque |
lazy_static! |
std::sync::OnceLock |
快速审查清单
- [ ] 没有未经论证的
.clone() - [ ] 库代码中没有
.unwrap() - [ ] 没有违反不变量的
pub字段 - [ ] 迭代器可用时没有索引循环
- [ ]
&str足够时没有String - [ ] 没有忽略
#[must_use]警告 - [ ] 没有不带SAFETY注释的
unsafe - [ ] 没有巨大函数(>50行)
相关技能
| 何时 | 参见 |
|---|---|
| 所有权模式 | m01-所有权 |
| 错误处理 | m06-错误处理 |
| 心智模型 | m14-心智模型 |
| 性能 | m10-性能 |