一、重构入门:什么是重构、为什么需要重构、重构与重写的区别、重构的时机与原则
1.1 什么是重构?说白了就是「整理代码」
我经常跟团队里的年轻人说,重构不是什么高大上的魔法。它其实就是——在不改变代码外部行为的前提下,调整内部结构。
你想想看,我们写代码就像写文章。第一稿能跑通就不错了,但读起来可能逻辑混乱、变量命名随意、函数又长又臭。重构就是把这些「烂文章」改得清晰、易读、好维护。
举个例子,我接手过一个老项目,里面有个函数长达 800 行。我花了三天时间,把它拆成 12 个小函数,每个函数只做一件事。测试用例全部通过,业务逻辑没变,但后来新同事接手时,只花了一天就理解了全部逻辑。这就是重构的价值。
1.2 为什么需要重构?
说实话,很多团队不重构也能活。但活得累不累,只有自己知道。
我个人习惯把重构的必要性归纳为三点:
- 降低维护成本:烂代码每改一次 bug,可能引入两个新 bug。重构后,逻辑清晰了,改起来心里有底。
- 提升扩展性:我在项目中遇到过,一个模块加了新需求,结果改了 5 个文件,因为代码耦合太严重。重构后,加功能只需要改 1 个文件。
- 减少技术债务:技术债务就像信用卡,不还就会利滚利。重构就是还债。
嗯,这里要注意一点:不是所有代码都值得重构。有些代码写完就扔,比如一次性脚本,重构就是浪费时间。但如果是核心业务模块,不重构就是在给自己挖坑。
1.3 重构 vs 重写:别搞混了
我见过不少团队,把「重构」和「重写」混为一谈。结果呢?重构搞成了重写,项目延期三个月,老板气得拍桌子。
它们的区别其实很简单:
| 维度 | 重构 | 重写 |
|---|---|---|
| 外部行为 | 不变 | 可能改变 |
| 风险 | 低(小步快跑) | 高(推倒重来) |
| 时间成本 | 几天到几周 | 几周到几个月 |
| 适用场景 | 代码结构差但逻辑正确 | 原有架构完全无法满足需求 |
我曾经犯过一个错:一个老项目代码很乱,我脑子一热说「重写吧」。结果写了两个月,业务方催得紧,最后不得不把老代码又捡回来。那次之后我学乖了——能重构就别重写。
1.4 重构的时机:什么时候该动手?
这个问题没有标准答案。但我总结了几条「信号」:
- 添加新功能很痛苦:改一行代码要翻 5 个文件,说明该重构了。
- 代码审查总吵架:团队里每次 review 都在争论「这段逻辑写在哪」,说明结构有问题。
- 测试覆盖率低:没有测试,你不敢改代码。不敢改,代码就越烂。这是个死循环。
- 新人上手慢:一个新人花了两周还看不懂核心模块,说明代码可读性太差。
我个人习惯是:每次修改代码时,顺手做一点重构。比如改一个 bug,顺便把附近 3 行烂代码清理一下。这叫「童子军规则」——让营地比你发现时更干净。
1.5 重构的原则:别乱来
重构不是随心所欲地改代码。我总结了四条铁律:
- 先有测试,再动手:没有测试的重构,就是裸奔。我每次重构前,先确保核心逻辑有单元测试覆盖。
- 小步提交,频繁验证:每次只改一小块,改完就跑测试。不要攒一个大 patch 再提交,那样出了问题根本不知道是哪一步引起的。
- 不要同时重构和加功能:这是最常见的坑。重构时加新功能,出了问题你分不清是重构引入的还是新功能引入的。
- 保持代码可读性:重构后的代码,应该让一个普通水平的同事能一眼看懂。如果看不懂,说明你重构得还不够好。
1.6 本章知识体系
下面这张图,是我自己画的知识结构。你看一眼,就能把本章内容串起来:
这张图把本章的核心知识点都串起来了。你记住这五个分支,重构的基本功就算打牢了。
1.7 一个小例子:感受一下重构
光说不练假把式。我写个简单的例子,你感受一下:
重构前:
function calc(a, b, c) {
let x = a * 0.1;
let y = b * 0.2;
let z = c * 0.15;
return x + y + z;
}
这段代码有什么问题?变量名毫无意义,魔法数字满天飞。你根本不知道 0.1、0.2、0.15 是什么。
重构后:
const TAX_RATE_BASIC = 0.1;
const TAX_RATE_MEDIUM = 0.2;
const TAX_RATE_HIGH = 0.15;
function calculateTotalTax(incomeBasic, incomeMedium, incomeHigh) {
const basicTax = incomeBasic * TAX_RATE_BASIC;
const mediumTax = incomeMedium * TAX_RATE_MEDIUM;
const highTax = incomeHigh * TAX_RATE_HIGH;
return basicTax + mediumTax + highTax;
}
你看,行为完全没变——输入输出一样。但代码的可读性、可维护性提升了不止一个档次。这就是重构的魅力。