SuperAPI AI 工具集

refactoring

编程与开发

查看项目

更新于 10-16 04:24

技能介绍

用途

本技能用于在保持外部行为不变的前提下,改善代码结构与质量。它强调通过测试和增量改动来保证安全,适用于需要重构代码、消除代码坏味道、提升可读性与可维护性的场景。

核心原则

测试是安全网。没有测试就不要重构。

重构循环

  1. 确保测试存在且通过
  2. 做一次小改动
  3. 运行测试(必须仍然通过)
  4. 提交(保持改动隔离)
  5. 重复

每一步都必须可回退。如果测试失败,回退并尝试更小的改动。

重构前检查清单

如果以下任何一项为假,就停止:

  • 被重构的代码存在测试
  • 所有测试当前通过
  • 理解代码做什么
  • 外部行为将保持不变
  • 有足够时间认真做(不赶工)

如果没有测试:先添加测试,验证测试通过,然后再重构。

何时重构

提示重构的代码坏味道:

可读性问题:

  • 长函数(超过 50 行)
  • 深层嵌套(超过 3 层)
  • 命名不清晰
  • 魔法数字
  • 复杂条件

可维护性问题:

  • 重复(同一代码出现在多处)
  • 上帝类(职责过多)
  • 特性依恋(方法使用另一个类多于自身)
  • 数据泥团(同一组参数被反复传递)

复杂性问题:

  • 圈复杂度大于 10
  • 依赖过多
  • 紧耦合代码
  • 难以测试

何时不应重构

  • 没有测试(先添加测试)
  • 处于截止日期压力下(推迟到以后)
  • 代码能工作且可读(不要过度设计)
  • 改变外部行为(那不是重构,而是功能或修复)
  • 发布前(风险太大)

经典重构手法

提取函数

问题:函数做太多事情。

重构前:一个长函数同时做校验、计算和保存。

重构后:拆分为 validateOrder、calculateTotals、saveOrder 等聚焦函数。

好处:每个函数单一职责,更易测试,更易理解。

提取变量

问题:复杂表达式难以理解。

重构前:if (user.age >= 18 && user.country === 'US' && !user.banned && user.verified)

重构后:拆为 isAdult、isUSResident、hasGoodStanding、canPurchase 等变量。

好处:自文档化,更易调试,更易修改。

内联函数/变量

问题:不必要的间接层,没有增加清晰度。

重构前:getTotal 只是调用 calculateTotalAmount。

重构后:直接内联计算。

何时内联:抽象没有增加价值,反而让代码更难跟随时。

重命名

问题:命名不清晰或误导。

重构前:function proc(d: any)

重构后:function calculateArea(dimensions: Dimensions)

好处:代码自文档化,无需猜测变量含义。

用命名常量替换魔法数字

问题:代码中出现无法解释的数字。

重构前:const tax = subtotal * 0.08

重构后:定义 TAX_RATE、FREE_SHIPPING_THRESHOLD、STANDARD_SHIPPING_COST 等常量。

消除重复

问题:同一代码出现在多处。

重构前:formatUserName、formatAdminName、formatAuthorName 各自重复相同逻辑。

重构后:统一为 formatFullName。

简化条件

问题:复杂的嵌套 if/else。

重构后:使用提前返回、扁平结构,或查找表。

用多态替换条件

问题:类型检查散布在代码各处。

重构后:定义接口,由各类型实现 calculatePrice。

拆分函数

问题:函数试图做太多事情。

重构后:将校验、计算、持久化、通知分离为独立函数。

重构工作流

逐步过程:

# 1. 确保测试通过
npm test
# ✅ 所有测试通过

# 2. 做一次重构改动
# 例如:提取函数

# 3. 立即运行测试
npm test
# ✅ 仍然通过

# 4. 用描述性消息提交
git add .
git commit -m "refactor: extract validateOrder function"

# 5. 重复下一次重构

如果重构后测试失败:

# 选项 1:回退并尝试更小的改动
git reset --hard HEAD
# 做更小、更安全的改动

# 选项 2:调试并修复
# 找到问题
# 修复它
# 再次运行测试

重构策略

童子军规则:“让代码比你发现时更好。” 触碰代码时修复明显问题、改进命名、提取复杂表达式、补充缺失测试、删除注释掉的代码。小改进会累积。

预备性重构:在添加功能前先重构,使功能更容易添加。引用:“让改动变容易,然后做容易的改动。”

机会性重构:工作时顺手修复注意到的问题。修 bug 时清理周边代码,加功能时改进结构,读代码时修正令人困惑的命名。

计划性重构:专门安排时间改善代码健康,如技术债工单、重构冲刺、清理会议。

重构安全清单

每次改动前:

  • 测试存在
  • 测试通过
  • 理解代码做什么

每次改动后:

  • 测试仍然通过
  • 功能没有改变
  • 代码更清晰
  • 可以提交

如果测试失败:

  • 理解原因
  • 修复或回退
  • 绝不提交失败的测试

与其他技能集成

重构期间可应用:boy-scout-rule、simplicity-principles、solid-principles、structural-design-principles、test-driven-development、proof-of-work、code-reviewer。

常见重构陷阱

  • 没有测试就重构:风险是未察觉地改变行为。解决方案:先添加测试,再重构。
  • 一次改动太多:风险是出问题时难以调试。解决方案:一次一个重构,频繁提交。
  • 改变行为:风险是行为改变就不是重构。解决方案:测试必须仍然通过,功能不变。
  • 过度工程:风险是“重构”后更复杂。解决方案:更简单更好,不要添加不必要的抽象。
  • 压力下重构:风险是赶工导致错误。解决方案:推迟到有时间做对时。

衡量重构成功

好的重构结果是:更易理解、更易修改、更易测试、代码行数通常更少、复杂度更低、性能相同或更好、所有测试仍然通过。如果任何测试失败,就不是成功的重构。

工具

自动化重构工具:IDE 重构命令(安全)、重命名变量/函数(安全)、提取方法(安全)、移动文件(安全)。

手动重构:做小改动、频繁测试、每次改动后提交、用版本控制作为安全网。

记住

  • 测试优先——没有测试就不重构
  • 小步前进——一次一个改动
  • 每步之后测试——必须保持绿色
  • 频繁提交——每个安全改动都提交
  • 行为不变——如果行为改变,就不是重构

重构是在不改变代码做什么的前提下改善结构。