Development
代码简化
简化代码以提升清晰度。适用于在不改变行为的前提下重构代码以提高可读性。
通过降低复杂性来简化代码,同时保持完全一致的行为。目标是让代码更易于阅读、理解、修改和调试。
使用场景
- 功能已实现且测试通过,但实现显得过于复杂时
- 代码审查中标记了可读性或复杂性问题时
- 遇到深层嵌套逻辑、过长函数或命名不清时
- 在时间压力下编写的代码需要重构时
五项原则
1. 精确保持行为
不要改变代码的功能——只改变表达方式。
每次修改前都要确认:
→ 对每个输入是否产生相同输出?
→ 是否保持相同的错误行为?
→ 是否保持相同的副作用和执行顺序?
→ 所有现有测试是否不需修改即可通过?
2. 遵循项目约定
简化意味着让代码与代码库更加一致,而不是强加外部偏好。
3. 清晰优先于技巧
// 不清晰:密集的三元表达式链
const label = isNew ? 'New' : isUpdated ? 'Updated' : isArchived ? 'Archived' : 'Active';
// 清晰:可读的映射
function getStatusLabel(item: Item): string {
if (item.isNew) return 'New';
if (item.isUpdated) return 'Updated';
if (item.isArchived) return 'Archived';
return 'Active';
}
4. 保持平衡
警惕过度简化的陷阱:
- 过度内联
- 合并不相关逻辑
- 移除"不必要"的抽象
- 为减少行数而优化
5. 限定在变更范围内
默认只简化最近修改的代码。避免顺手重构不相关的代码。
简化流程
第 1 步:修改前先理解(Chesterton's Fence)
在修改任何代码之前,先理解它存在的原因:
简化前先回答:
- 这段代码的职责是什么?
- 谁调用它?它调用谁?
- 边界情况和错误路径有哪些?
- 是否有定义预期行为的测试?
- 为什么它被写成这样?
第 2 步:识别简化机会
结构复杂性:
| 模式 | 信号 | 简化方式 |
|---|---|---|
| 深层嵌套(3+层) | 控制流难以跟随 | 提取为卫语句 |
| 长函数(50+行) | 多个职责 | 拆分为专注的函数 |
| 嵌套三元表达式 | 需要心理栈 | 替换为 if/else 链 |
| 布尔参数标志 | doThing(true, false, true) |
替换为选项对象 |
| 重复条件判断 | 相同的 if 检查出现在多处 |
提取为谓词函数 |
命名和可读性:
| 模式 | 信号 | 简化方式 |
|---|---|---|
| 通用名称 | data、result、temp |
重命名以描述内容 |
| 误导性名称 | 名为 get 的函数实际在修改数据 |
重命名以反映行为 |
| 解释"做什么"的注释 | // increment counter |
删除注释 |
| 解释"为什么"的注释 | // Retry because API is flaky |
保留——它们传达意图 |
冗余:
| 模式 | 信号 | 简化方式 |
|---|---|---|
| 重复逻辑 | 相同的 5+ 行代码出现在多处 | 提取为共享函数 |
| 死代码 | 不可达分支、未使用变量 | 移除 |
| 不必要的抽象 | 无价值的包装器 | 内联 |
| 过度工程化的模式 | 工厂的工厂 | 替换为简单方案 |
第 3 步:逐步应用变更
一次进行一项简化。每次变更后运行测试。
第 4 步:验证结果
对比修改前后:
- 简化后的版本是否确实更易理解?
- 是否引入了与代码库不一致的新模式?
- diff 是否干净且可审查?
- 团队成员是否会批准这个变更?
语言特定指导
TypeScript / JavaScript
// 简化:不必要的 async 包装
// 修改前
async function getUser(id: string): Promise<User> {
return await userService.findById(id);
}
// 修改后
function getUser(id: string): Promise<User> {
return userService.findById(id);
}
// 简化:冗长的条件赋值
// 修改前
let displayName: string;
if (user.nickname) {
displayName = user.nickname;
} else {
displayName = user.fullName;
}
// 修改后
const displayName = user.nickname || user.fullName;
// 简化:手动构建数组
// 修改前
const activeUsers: User[] = [];
for (const user of users) {
if (user.isActive) {
activeUsers.push(user);
}
}
// 修改后
const activeUsers = users.filter((user) => user.isActive);
验证
完成简化后:
- 所有现有测试不需修改即可通过
- 构建成功且无新警告
- 每项简化都是可审查的增量变更
- 简化后的代码遵循项目约定
- 未移除或削弱任何错误处理
- 未留下死代码
- 团队成员会认为这是净改进