一个 invoice 生成函数,6层嵌套 if,变量命名像密码。马丁·福勒花了 60 分钟把它拆成 12 个独立函数,测试通过率从 73% 跳到 100%。
这不是魔术。这是《重构》第 2 版开篇的第一个例子,福勒用 40 页纸把一次完整的代码手术摊开给你看。
从"能跑就行"到"敢改敢动"
福勒选了一个真实到扎心的场景:计算戏剧演出账单。原始代码 40 多行,混着格式化逻辑、金额计算、积分规则。你改一行,三个测试挂掉。
他的第一步让新手困惑——先写测试。不是先动手拆代码,而是先把现有行为锁进测试用例。这是他的铁律:重构不是重写,是"在不改变外在行为的前提下,改善内部结构"。没有测试网兜着,拆代码等于拆炸弹。
测试就位后,福勒开始动刀。Extract Function(提炼函数)用了 7 次,把"计算金额""计算积分""格式化账单"逐个剥离。每次提炼后立刻跑测试,绿了就下一步,红了就回滚。
有个细节很产品经理:他把"计算价格"和"格式化输出"彻底拆成两个阶段(Split Phase)。原因是——价格计算可能被复用到 API、报表、对账系统,而 HTML 格式化只给前端看。耦合度降低,复用度上升,这是架构层面的收益,不是代码洁癖。
"好代码"的四个刻度
福勒在书里没给"好代码"下定义,但他反复出现的判断标准可以总结成四把尺子。
第一,命名即文档。他把变量 `perf` 改成 `performance`,`thisAmount` 改成 `amountFor(performance)`。函数名取代注释,读代码像读需求文档。
第二,消除重复。原始代码里"悲剧""喜剧"的定价逻辑写了两遍,福勒把它抽到 `playFor(performance)` 里。重复是万恶之源——改一处漏一处,迟早埋雷。
第三,函数要短,且只做一件事。他提炼后的函数平均 5 行,最长的不超过 10 行。短函数不是炫技,是降低认知负荷。你打开一个文件,扫一眼函数名就知道它在哪层抽象。
第四,数据与行为绑定。他把"喜剧""悲剧"的差异从 if-else 里抽出来,变成多态对象。新增剧种?加一行配置,不用改核心逻辑。开闭原则(Open/Closed Principle)落地了。
重构的节奏感:小步快跑,频繁提交
福勒的操作粒度细到让人不适。Extract Function 后马上跑测试,Inline Variable(内联变量)后马上跑测试,Move Function(搬移函数)后马上跑测试。每次变更控制在 5 分钟内可回滚。
这和创业公司的"敏捷"不是一回事。很多团队把重构当项目,排期两周,"这次彻底重写"。福勒的做法是:重构是日常,不是事件。看见坏味道(code smell)就动手,像看到桌上咖啡渍就擦。
他列了 20 多种"坏味道":过长函数、过大的类、发散式变化、霰弹式修改……每种味道对应一组重构手法。这不是教条,是经验压缩——他 30 年代码生涯踩过的坑,打包成检查清单给你。
有个类比很妙:重构就像整理衣柜。你不会等衣柜塌了才动手,而是每次拿衣服时顺手归位。代码库同理——每次提交都比上次干净一点,复利效应惊人。
为什么现在重读这本书
《重构》初版 1999 年,Java 还是主流。第 2 版 2019 年更新,示例换成 JavaScript,但核心没变:代码是负债,也是资产。维护成本随复杂度指数上升,而重构是唯一的对冲手段。
福勒在序言里写了一句被低估的话:"任何傻瓜都能写出计算机可以执行的代码,好的程序员写出人类可以理解的代码"。
AI 写代码的时代,这句话更刺耳。Copilot 能生成能跑的代码,但看不懂的代码就是技术债。福勒的 72 种重构手法,本质上是教人类如何保持对代码的掌控权——不是对抗 AI,而是让 AI 生成的输出也能被人类理解和迭代。
书里有个数据:未经重构的代码库,添加新功能的耗时每年增长 20-30%。重构过的代码库,增速稳定在 5% 以内。这不是估算,是福勒在 ThoughtWorks 多个项目跟踪的结果。
你上一次说"这段代码不敢动"是什么时候?
特别声明:以上内容(如有图片或视频亦包括在内)为自媒体平台“网易号”用户上传并发布,本平台仅提供信息存储服务。
Notice: The content above (including the pictures and videos if any) is uploaded and posted by a user of NetEase Hao, which is a social media platform and only provides information storage services.