一、重构入门:什么是重构、为什么需要重构、重构与重写的区别、重构的时机与原则

1.1 什么是重构?说白了就是「整理代码」

我经常跟团队里的年轻人说,重构不是什么高大上的魔法。它其实就是——在不改变代码外部行为的前提下,调整内部结构。

你想想看,我们写代码就像写文章。第一稿能跑通就不错了,但读起来可能逻辑混乱、变量命名随意、函数又长又臭。重构就是把这些「烂文章」改得清晰、易读、好维护。

举个例子,我接手过一个老项目,里面有个函数长达 800 行。我花了三天时间,把它拆成 12 个小函数,每个函数只做一件事。测试用例全部通过,业务逻辑没变,但后来新同事接手时,只花了一天就理解了全部逻辑。这就是重构的价值。

重构的核心定义: 行为不变,结构优化。

1.2 为什么需要重构?

说实话,很多团队不重构也能活。但活得累不累,只有自己知道。

我个人习惯把重构的必要性归纳为三点:

  • 降低维护成本:烂代码每改一次 bug,可能引入两个新 bug。重构后,逻辑清晰了,改起来心里有底。
  • 提升扩展性:我在项目中遇到过,一个模块加了新需求,结果改了 5 个文件,因为代码耦合太严重。重构后,加功能只需要改 1 个文件。
  • 减少技术债务:技术债务就像信用卡,不还就会利滚利。重构就是还债。

嗯,这里要注意一点:不是所有代码都值得重构。有些代码写完就扔,比如一次性脚本,重构就是浪费时间。但如果是核心业务模块,不重构就是在给自己挖坑。

1.3 重构 vs 重写:别搞混了

我见过不少团队,把「重构」和「重写」混为一谈。结果呢?重构搞成了重写,项目延期三个月,老板气得拍桌子。

它们的区别其实很简单:

维度 重构 重写
外部行为 不变 可能改变
风险 低(小步快跑) 高(推倒重来)
时间成本 几天到几周 几周到几个月
适用场景 代码结构差但逻辑正确 原有架构完全无法满足需求

我曾经犯过一个错:一个老项目代码很乱,我脑子一热说「重写吧」。结果写了两个月,业务方催得紧,最后不得不把老代码又捡回来。那次之后我学乖了——能重构就别重写。

避坑指南: 我曾经见过一个团队,把重构当重写,结果上线后出了 20 多个 bug。记住:重构是手术,重写是换器官。能微创就别开刀。

1.4 重构的时机:什么时候该动手?

这个问题没有标准答案。但我总结了几条「信号」:

  • 添加新功能很痛苦:改一行代码要翻 5 个文件,说明该重构了。
  • 代码审查总吵架:团队里每次 review 都在争论「这段逻辑写在哪」,说明结构有问题。
  • 测试覆盖率低:没有测试,你不敢改代码。不敢改,代码就越烂。这是个死循环。
  • 新人上手慢:一个新人花了两周还看不懂核心模块,说明代码可读性太差。

我个人习惯是:每次修改代码时,顺手做一点重构。比如改一个 bug,顺便把附近 3 行烂代码清理一下。这叫「童子军规则」——让营地比你发现时更干净。

1.5 重构的原则:别乱来

重构不是随心所欲地改代码。我总结了四条铁律:

  1. 先有测试,再动手:没有测试的重构,就是裸奔。我每次重构前,先确保核心逻辑有单元测试覆盖。
  2. 小步提交,频繁验证:每次只改一小块,改完就跑测试。不要攒一个大 patch 再提交,那样出了问题根本不知道是哪一步引起的。
  3. 不要同时重构和加功能:这是最常见的坑。重构时加新功能,出了问题你分不清是重构引入的还是新功能引入的。
  4. 保持代码可读性:重构后的代码,应该让一个普通水平的同事能一眼看懂。如果看不懂,说明你重构得还不够好。
小技巧: 我习惯用「代码坏味道」来指导重构。比如过长函数、过大的类、重复代码、过度耦合。闻到这些味道,就该动手了。

1.6 本章知识体系

下面这张图,是我自己画的知识结构。你看一眼,就能把本章内容串起来:

重构入门 什么是重构 行为不变,结构优化 为什么需要重构 降低维护成本 提升扩展性 减少技术债务 重构 vs 重写 重构:小步快跑 重写:推倒重来 重构时机 加功能痛苦时 代码审查总吵架 重构原则 先有测试 小步提交 不混加功能 代码坏味道 过长函数 重复代码 过度耦合

这张图把本章的核心知识点都串起来了。你记住这五个分支,重构的基本功就算打牢了。

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;
}

你看,行为完全没变——输入输出一样。但代码的可读性、可维护性提升了不止一个档次。这就是重构的魅力。

记住: 重构不是炫技,而是让代码更「像人话」。好的代码,应该像一篇清晰的文章,而不是天书。
可可精品资料库