返回博客

重构不是追求完美,是管理变更成本

重构这个词很容易被滥用。有人把它当成「趁机把所有不顺眼的地方都改一遍」,有人把它当成「先把需求堆上去,等有空再说」。这两种极端都不对。

我在代码评审流程里把重构单独拎出来作为第三阶段——先找 bug,再看安全/质量,最后才看结构——原因是:结构问题和行为问题的修复节奏完全不同,混在一起只会让 PR 又大又难审

三条硬约束,比任何框架都重要

安全第一:只做不改变行为的变更。如果你的「重构」需要加测试来验证它没改出 bug,那它不是重构,是功能变更。把这两件事拆开提交。

3 次规则:代码重复 2 次,忍着。重复 3 次,再抽象。这条规则看起来很机械,但背后有实用的逻辑——两份重复代码往往是「巧合相似」,过早抽象会把两个本来无关的概念强行耦合。等到第三次出现时,你才真的看清楚它们共同的本质。

最小变更:每次重构只解决一个结构问题。不要在一个 PR 里同时拆函数、改命名、引入新模式。叠加得越多,代码审查越难,出问题越难定位。

分级输出,让建议真的被执行

把重构建议分成三档:

  • 立即处理(当前 PR 内):重复代码超过 3 次、单函数超过 80 行、单文件超过 600 行、嵌套超过 4 层。这些是维护成本已经可见的信号,不处理会继续恶化。
  • 下次迭代:命名不清、参数过多(超过 4 个)、「特性羡慕」(函数大量操作另一个模块的数据)。这些有成本,但不紧急。
  • 低优先级:简化条件表达式、引入解释变量、用多态替代大量 if/switch。这些是锦上添花,有余力再做。

每条建议都要有 Before/After 对比,不然就是在给人出题,不是在给人帮助。

核心判断标准

每个重构建议都要能回答:「如果不做这件事,六个月后的变更成本会多多少?」答不上来的建议,先不做。

最容易踩的反模式

过早抽象比重复代码危害更大。三行相似的代码,理解成本接近零;一个抽象出来的基类或工具函数,每个读代码的人都要先理解它的边界和假设。如果这个抽象以后还需要被改掉,代价会比当初没抽象时高得多。

尊重现有架构。项目里已经有 Mixin 的用 Mixin,已经有 Service 层的往 Service 里放,不要在同一个代码库里混搭五种不同的抽象风格。重构建议要和项目的已有模式对齐,而不是把自己偏好的模式强行带进来。

区分变更代码和存量代码。代码评审时,重构建议应该聚焦在本次 PR 改动的范围内。存量代码里也许有更严重的问题,但那是另一个故事,不要在一个 PR 里把所有账都算。

一句话心法

重构的触发条件是「继续改动这段代码的成本变高了」,而不是「我看这段代码不顺眼」。