我第一次接触重构,是在毕业后的第一个项目。那时我刚入职,一堆凌乱的代码让我头疼不已。
我尝试着将函数拆分、变量重命名,结果不仅自己心情愉悦,也让团队 review 时少了很多疑问。那次经历让我第一次体会到重构的价值。

程序员都喜欢重构代码。
让乱糟糟的东西变得整洁,能给我们带来极大的愉悦感。
重构这种做法,也是程序员圈子里公认的好习惯。
在学校里,老师会推崇。
在职场里,前辈会推荐。
在各种软件开发理念、各种编程思维里,重构也经常被提及。
但嘴上说得好听是一回事。
经验丰富的老油条会发现,项目真正开始之后,重构的机会少之又少。
最多是在提交 PR 时,顺便做一下变量重命名、拆分函数之类的小修小补。
正儿八经地把重构当成一个有分量的任务都很少见,更别说把重构当做是某个开发周期的主要工作。
程序员很重视,但是项目组不重视。
是什么造成了这种割裂的状态呢?
故事得从最开始说起。
作为 90 年代软件开发理念的墓志铭三部曲中的最后一部,重构是唯一一个源自于学术界的理论。
1990 年,来自伊利诺伊大学的在读博士生 William,发表了论文《balabalabala……》,首次提到了重构(refactoring)这个词。
一年后,华盛顿大学的另一个博士生发表博士学位论文,首次全面系统地构建了重构的理论。
它针对的是主流的 functional programming 和 procedural programming 的代码。
又过了一年,William 自己也发表博士学位论文,构建了面向 OOP 代码的重构理论。
因为他的导师就是 OOP 圣经《Design Patterns》的四个作者之一。

但重构这个做法,从实验室里的理论,走进项目组里的实践,多多少少得归功于上一期墓志铭的主角 TDD。
作为 Agile 体系的基石,extreme programming 模式中,TDD 是最深入日常工作的指导方针。
而 TDD 的三个主要步骤:写测试、写代码、重构代码,则是环环相扣,缺一不可。
因为在 TDD 的写法里,如果代码不重构,屎山会呈指数级上升,很快就会举步维艰。
所以在 Agile 体系全盘接管开发的年代,重构毋庸置疑是不可或缺的一环。
但成也 TDD,败也 TDD。
随着 Agile 开发被大家做成“Agile 风味”的开发,捆绑销售的 TDD 也不再受宠。
脱离了 TDD 的重构,也开始变得可有可无。

对于这个成本不小、价值不明的工序,负责管理项目的人们开始提出问题:“我们为什么要重构来着?”
这个问题最标准的回答来自于重构圣经,Martin Fowler 的名著《Refactoring》。
根据这本书的解释,重构是为了让代码“easier to understand and cheaper to modify”。
这里的主语是程序员。
让程序员更容易看懂代码,让程序员可以更轻松地改动代码。
从头到尾,重构都是一个以程序员的身心健康为主要考量的理念。
而这,也是让重构在业界寸步难行的根本原因。
我在一个创业项目中,团队为了尽快上线产品,几乎没有时间重构。随着功能叠加,代码越来越复杂。那段经历让我深刻理解为什么早期的 MVP 阶段,速度比重构更重要,也体会到技术债带来的压力。

在业界,我们可以用价值和成本来衡量一切行为。
那么一个新产品在开发时,就有两种选择:
1.
在开发初期投入精力进行重构,时刻保持代码高质量。这会在早期影响产品商业价值的爬坡速度,因为每花 1 分钟在重构上,就少 1 分钟在业务需求开发上。但随着产品成熟,高质量代码会减少技术债,加快新功能开发,降低维护成本,提升商业价值。
2.
在开发初期埋头猛干,不去管代码质量。这样能让产品更快发布、更快获得用户、更早占领市场。但进入后期,会面临技术债、过期技术栈、频繁出 bug,开发团队需要投入更多维护成本,新功能开发风险增加。
现实中,软件开发往往选择第二条路。
根据鸿沟理论,任何产品都需要先验证市场。
早期阶段就是 MVP,最重要的是速度。
路线二会比路线一更早达到 MVP,这是从风险和收益角度的最优解。
即使成功发布 MVP,并获得早期认可,也不能立刻重构。

因为此时的目标是跨越鸿沟,进入主流市场。
主流市场是赢家通吃的零和游戏。在这个阶段投入精力重构,就是主动让出领先地位。
假设已经跨越鸿沟,站稳主流市场。
此时积累的技术债已经很多,重构成本远高于 MVP 时期。
重构成为一个短期成本和长期价值的组合。
在现实商业环境下,很少有人愿意为此承担风险。
从商业角度来看,在软件工程里,很难为重构留出空间。
前段时间,我在一个使用 AI 编程辅助的项目中,看到生成的代码重复造轮子、范式混乱。我花了一天时间重构了一小部分,虽然用户无感,但团队开发效率明显提升。这让我重新相信,重构不只为了程序员的愉悦,也能在团队层面体现价值。

至于狭义重构,AI 编程可能带来转机。
随着大量代码由 AI 生成,中庸化、重复造轮子、范式混乱的问题逐渐显现。
当代码复杂度再次失控,人类程序员可能会被重新需要。
而那,或许就是重构的重生时刻。