所有小事(2014)
摘要
Sandy Metz 讨论了如何精简代码以及使用测试来指导重构,并通过 Gilded Rose kata 进行说明。
<p><a href="https://lobste.rs/s/gtarrm/all_little_things_2014">评论</a></p>
查看缓存全文
缓存时间: 2026/08/31 02:09
**概要:** 编写更优面向对象代码的关键在于保持小规模——小类、小方法——同时通过测试引导安全、渐进的重构。
## 核心问题:当代码变得难以维护时
Sandy Metz 首先指出,许多开发者在面向对象编程中挣扎。她观察到,即使初衷良好的代码也会随时间推移而令人沮丧。她的总体建议很简单:**保持小规模**。这意味着更小的类、更小的方法,以及尽可能减少组件间的相互依赖。
她近期关注的焦点是条件语句(if语句)。她探讨何时应将复杂条件替换为小型对象,以及这对代码库会产生何种影响。
## 《镀金玫瑰》练习:复杂性案例分析
Metz 以 **《镀金玫瑰》练习** 作为演讲框架。这是她通过 Jim Weirich 首次接触的知名编程练习。
该练习涉及一个包含 `name`、`quality` 和 `remaining_days` 属性的 `GildedRose` 类,以及单一的 `tick` 方法。她指出该 `tick` 方法是 **43行条件语句**。为客观衡量其复杂度,她使用了 **Flog** 工具——一种基于赋值、分支、条件的度量指标。`GildedRose` 类的 Flog 得分为50,其中仅 `tick` 方法就得了45分。
### 主观的“模糊测试”
Metz 描述了她评判代码复杂度的经验法则:“模糊测试”。通过模糊视线下观察代码,可以识别:
* **形状变化:** 表明存在嵌套条件,难以理解
* **颜色变化:** 表明存在不同抽象层级,导致逻辑难以追踪
`tick` 方法未通过该测试,其中包含 **16个if语句**、**魔法字符串**(“布里”、“硫磺”、“后台通行证”)和 **魔法数字**。
代码库虽有测试,但 **六个被跳过**。跳过的测试针对“被诅咒”物品类型。Metz 指出所有测试都遵循相同模式:给定具有特定属性的物品,执行 `tick()` 后,品质和剩余天数会按预期方式变化。
## 修改挑战与重构过程
Metz 的任务是添加对“被诅咒”物品的支持。她最初尝试修改复杂的 `tick` 方法但失败了,因为修改会破坏现有测试。这揭示了一个常见陷阱:当被要求修改代码时,开发者往往倾向于在最近的现有结构上添加内容,即使那是一个大型条件语句。这会导致代码变得臃肿难控。
她决定 **重构**——在不改变行为的前提下调整代码结构——并利用现有测试作为安全网。
### 分步重构
她对“普通”物品类型的处理步骤如下:
1. **创建接缝:** 她将大型条件替换为向自身发送消息(`send(self)`)的特定分支。这导致四个测试失败,确认她已捕获该执行路径。
2. **使测试通过(回归绿色状态):** 她编写最简代码使每个测试依次通过。她坦言最初会写不完全理解的代码,优先确保测试通过。初始代码很简单:若品质不为零,则品质减一且剩余天数减一。
3. **重构至绿色状态:** 当该分支所有测试通过后,她开始重构。她识别出恒定模式(剩余天数始终减一)并提取出来。同时发现 `quality > 0` 的条件可以包裹整个操作,从而简化逻辑。
4. **重复流程:** 她对“布里”物品重复此过程,为提高清晰度将其转换为 `case` 语句。
## 关键洞察:过早优化的代价(DRY原则)
实现“普通”和“布里”的独立分支后,她注意到两者逻辑惊人相似。立即应用 **DRY(不要重复自己)原则** 的诱惑随之而来。
Metz 认为在此时这样做是个错误。她指出:**“保留重复代码远比处理错误的抽象便宜得多”**。
她解释道,初学者被教导 DRY 是因为这是易于理解的规则。然而经验丰富的开发者应暂时容忍某些重复,以便在寻求正确抽象前收集更多关于问题本质的信息。过早行动可能导致拙劣、牵强的抽象。
## 结论:安全重构的模式
演讲勾勒出处理复杂代码的清晰、可重复模式:
1. **创建接缝**(例如通过消息发送)
2. **通过失败测试追踪执行路径**
3. **编写最简代码通过测试**(优先达到“绿色”状态)
4. **测试通过后进行重构**以提升清晰度和结构
这种方法允许开发者在测试引导下,将整体复杂的单体方法分解为更小、更易理解的单元,同时不改变外部行为。目标不仅是让代码工作,更要使其可维护、易理解。
**来源:** All the Little Things (2014) (https://www.youtube.com/watch?v=8bZh5LMaSmE)
相似文章
@SaitoWu: https://x.com/SaitoWu/status/2053101671035851216
The article summarizes a talk by Matt Pocock criticizing 'specs-to-code' approaches, arguing that solid software engineering fundamentals like TDD and modular design are more critical than ever for effectively using AI coding assistants like Claude Code.
@kentcdodds: 我使用Fable和Grok 4.5(在两个独立的聊天中)查找并清理了代码库中所有搞笑又糟糕的AI生成代码。
作者讲述了自己使用Fable和Grok 4.5识别并移除代码库中糟糕的AI生成代码的经历。
@rubenhassid: https://x.com/rubenhassid/status/2067125557024960922
一份面向非程序员的实用指南,介绍如何使用Claude Code通过用简单英语描述想法来构建可点击的原型和小型内部工具,并附有逐步设置说明。
正念编码:目的与意图
一篇鼓励开发者以清晰意图编写代码的文章,认为命名困难往往揭示了抽象设计的问题,并指出理解代码的“为什么”与“是什么”同样重要。
@garrytan: https://x.com/garrytan/status/2054064931515855118
Garry Tan 认为,Claude Code 和 Codex 等 AI 编程代理通过使高测试覆盖率变得经济可行,改变了软件工程领域。这创造了一种“复杂性棘轮效应”,确保代码质量在牺牲速度的前提下随时间推移而不断提升。