代码重构安全清单:别把重构做成重写
wxk1991 Lv5

代码重构安全清单:别把重构做成重写

重构最容易失控的地方,是你以为自己在整理代码。

结果改着改着变成:

1
2
3
4
5
顺手改业务
顺手换结构
顺手改命名
顺手修 bug
顺手重写一半系统

最后没人知道这次改动到底想解决什么。

重构不是重写。

真正好的重构,应该让外部行为基本不变,只让内部结构更清楚。


一、先说清楚为什么要重构

不要用一句:

1
代码太乱了。

作为重构理由。

这句话太大,最后会导致无限范围。

更好的目标是具体的:

1
2
3
4
5
把订单创建逻辑从 controller 挪到 service
拆出支付状态判断函数
减少重复的参数校验代码
把 600 行文件拆成 3 个模块
为后续接入优惠券预留扩展点

重构前先写一句目标。

如果一句话说不清楚,说明范围还没收住。


二、重构前先建立验证方式

没有验证方式的重构,本质上是靠感觉。

至少要有一种:

  • 单元测试
  • 集成测试
  • API 回归测试
  • 页面截图对比
  • 核心流程手动验证清单
  • 日志和监控观察项

比如重构登录流程前,先列清楚:

1
2
3
4
5
正确账号可以登录
错误密码不能登录
禁用用户不能登录
登录后能拿到 token
token 过期后会被拒绝

有测试最好。

没有自动化测试,也要有手动验证清单。

不要等改完才想“我应该怎么知道没坏”。


三、先补测试,再动结构

如果你要重构的是核心逻辑,最好先补测试。

比如价格计算:

1
2
3
4
5
6
原价
折扣
优惠券
会员价
税费
运费

这种逻辑很容易改坏。

先写几个典型用例:

1
2
3
4
5
普通用户无优惠
会员用户有折扣
优惠券超过订单金额
运费满减
税费四舍五入

等测试能覆盖当前行为,再开始改内部结构。

重构时测试失败,才知道自己动到了行为。

这会让你心里稳很多。


四、一次只改一种东西

重构最怕混合改动。

比如一次提交里同时做:

1
2
3
4
5
改目录结构
改函数命名
改业务逻辑
改数据库字段
改接口返回格式

代码 review 会非常痛苦。

更好的方式是拆开:

1
2
3
4
第 1 次:纯移动文件,不改逻辑
第 2 次:纯重命名,不改逻辑
第 3 次:抽函数,不改行为
第 4 次:调整业务逻辑

每一步都小一点。

小步提交的好处是:一旦出问题,容易定位,也容易回滚。


五、先做机械改动,再做设计改动

机械改动指的是:

  • 重命名
  • 移动文件
  • 调整 import
  • 格式化
  • 抽取函数

这些最好先单独完成。

设计改动指的是:

  • 改职责边界
  • 改数据流
  • 改状态机
  • 改错误处理方式
  • 改模块依赖关系

如果机械改动和设计改动混在一起,diff 会非常难看。

review 的人很难判断:

1
2
这是只是挪位置?
还是业务行为变了?

所以先把机械部分做干净,再处理真正需要思考的部分。


六、抽函数不是越多越好

很多人重构时喜欢疯狂抽函数。

但函数太碎,也会降低可读性。

判断一个函数是否值得抽,可以看:

  • 是否有明确业务含义
  • 是否能减少重复
  • 是否能降低当前函数复杂度
  • 是否方便单独测试
  • 名字是否比代码本身更清楚

不要为了“短”而抽函数。

比如:

1
2
3
4
check()
handle()
process()
doWork()

这种名字没有信息量。

抽出来也不一定更好。

好的函数名应该解释意图:

1
2
3
4
validateOrderStock
calculatePayableAmount
buildUserSession
markInvoiceAsPaid

七、保持接口边界稳定

如果这次目标是内部重构,尽量不要同时改外部接口。

外部接口包括:

  • HTTP API
  • CLI 参数
  • 配置文件字段
  • 数据库表结构
  • 消息格式
  • 对外 SDK

内部代码你可以调整。

但外部契约一变,影响面立刻扩大。

如果必须改接口,最好单独做兼容:

1
2
3
先支持新旧字段
灰度切换调用方
观察稳定后删除旧字段

重构的理想状态是:

1
调用方不知道你重构过。

八、删除代码要比新增代码更谨慎

删除代码很爽。

但要确认它真的没人用。

可以检查:

  • 全局搜索引用
  • 路由注册
  • 定时任务
  • 消息消费者
  • 配置开关
  • 外部调用方
  • 线上日志

有些代码看起来没人调用,但可能通过反射、配置、脚本、任务调度入口使用。

特别是后台任务、Webhook、CLI 子命令,不能只靠 IDE 引用判断。

删除前先确认入口。


九、重构后要看 diff

改完代码后,不要直接提交。

先自己看一遍 diff。

重点看:

  • 有没有混入无关格式化
  • 有没有意外改业务判断
  • 有没有多余日志
  • 有没有调试代码
  • 有没有改到不该改的文件
  • 有没有让错误信息变差
  • 有没有把简单逻辑抽得更绕

很多问题在自查 diff 时就能发现。

这一步很朴素,但非常有效。


十、写清楚提交说明

重构提交不要只写:

1
refactor

更好的写法:

1
重构订单创建流程,拆分参数校验和库存检查

或者:

1
调整用户模块目录结构,保持接口行为不变

提交说明要让未来的人知道:

1
2
这次改动的意图是什么
有没有行为变化

如果有行为变化,就不要假装只是重构。

那应该叫功能修改或 bug fix。


十一、一个实用重构清单

每次重构前,可以快速过一遍:

1
2
3
4
5
6
7
8
9
10
1. 这次重构目标能否一句话说清楚?
2. 外部行为是否应该保持不变?
3. 有没有测试或验证清单?
4. 是否需要先补测试?
5. 是否能拆成多个小提交?
6. 机械改动和设计改动是否分开?
7. 是否改动了外部接口?
8. 删除代码是否确认没人用?
9. 是否自查过 diff?
10. 提交说明是否写清楚意图?

这个清单不复杂。

但它能挡住很多“越改越大”的重构。


十二、我的建议

好的重构应该像整理房间。

你知道要整理哪一块。

你不会顺手把墙拆了。

你整理完之后,东西更容易找,房间还能正常住。

写代码也一样。

重构的目标不是证明自己能写更高级的结构。

而是让下一次修改更简单、更安全、更不容易出错。