一、重构初探:什么是代码重构?

先说说我自己的经历吧。刚入行那会儿,我总觉得代码能跑就行。直到有一次,一个客户需求变更,我花了整整三天才改完一个模块。改完之后,又冒出来三个新bug。当时我就想,这代码是不是哪里不对劲?

后来我才明白,问题出在代码结构上。那堆代码就像一团乱麻,牵一发而动全身。这时候需要的,就是重构。

1.1 重构的定义

重构,说白了就是在不改变代码外部行为的前提下,改善其内部结构。注意关键词——「不改变外部行为」。也就是说,功能不能变,测试用例得全过。

重构的核心:让代码更容易理解、更容易维护、更容易扩展。

举个例子,你有一段这样的代码:

// 重构前
int calc(int a, int b, int c) {
    int x = a * b;
    int y = x + c;
    int z = y / 2;
    return z;
}

这段代码能跑,但变量名毫无意义。重构一下:

// 重构后
int calculateAverage(int price, int quantity, int discount) {
    int subtotal = price * quantity;
    int totalAfterDiscount = subtotal - discount;
    int average = totalAfterDiscount / 2;
    return average;
}

功能完全一样,但可读性天差地别。这就是重构的威力。

1.2 重构 vs 重写

很多人分不清重构和重写。我见过一个团队,明明只需要重构,结果一激动把整个模块重写了,工期翻了三倍。

维度 重构 重写
范围 局部调整 整体推翻
风险 低,逐步进行 高,一次性替换
时间 数小时到数天 数周到数月
外部行为 不变 可能变化
适用场景 代码结构差但逻辑正确 架构彻底腐烂

我曾经踩过的坑:有一次我试图重构一个3000行的函数,改到一半发现根本理不清逻辑。最后不得不全部重写。所以,重构也要看情况——如果代码已经烂到无法理解,重写可能是更务实的选择。

二、重构的时机

什么时候该重构?这个问题我思考了很久。后来总结出三个信号:

2.1 三次法则

我第一次写某个功能时,直接写。第二次遇到类似需求,我复制粘贴改一改。第三次再遇到,我就知道——该重构了。

为什么是三次?因为前两次你还不确定这个模式会不会重复。第三次基本可以确认,这是个通用逻辑。

2.2 添加新功能时

你想想看,每次加新功能都要在旧代码上打补丁,代码会越来越臃肿。我个人的习惯是:在添加新功能之前,先把相关的老代码重构好。这样新功能加进去,代码反而更清爽。

2.3 修复bug时

bug往往藏在混乱的代码里。如果你发现一个bug很难定位,或者修完一个又冒出来三个,那说明代码结构有问题。这时候别急着修bug,先重构。

我的经验:修bug时如果花了超过30分钟还没找到根因,我就会停下来,先把那段代码重构一遍。通常重构完,bug自己就暴露了。

三、重构的原则

重构不是乱改。我总结了几条铁律:

3.1 小步提交

每次只改一点点。改完就编译、测试、提交。不要想着一次改完所有问题。

// 错误示范:一次改了10个函数
// 正确做法:每次只重构1个函数,确保测试通过

3.2 测试先行

没有测试的重构,就是耍流氓。我见过太多人重构完发现功能全崩了。所以,重构之前,先把测试用例写好。

核心原则:没有测试覆盖的代码,不要重构。先写测试,再重构。

3.3 保持功能不变

重构过程中,如果发现需要修改功能,立刻停下来。那叫「重写」,不叫「重构」。把功能变更和结构改善分开做。

四、知识体系总览

下面这张图,是我对本章内容的总结。你可以把它当作一个思维导图来看:

代码重构 什么是重构? 不改变外部行为 改善内部结构 重构 vs 重写 重构:局部调整,低风险 重写:整体推翻,高风险 重构的时机 三次法则 添加新功能时 修复bug时 重构的原则 小步提交 测试先行 保持功能不变

五、避坑指南

最后,分享几个我亲身踩过的坑:

  • 不要边重构边加功能。我曾经同时做这两件事,结果代码改到一半,功能也乱了,两边都没做好。
  • 不要追求完美。重构的目标是「更好」,不是「完美」。够用就行,过度重构反而浪费时间。
  • 不要一个人偷偷重构。团队协作时,重构要通知大家。不然别人还在用旧接口,你这边已经改完了,冲突一堆。

一个小技巧:重构之前,先把当前代码的git版本号记下来。万一改砸了,还能快速回退。我吃过这个亏,现在每次重构前都先打个tag。

嗯,关于重构的基础知识,就先聊到这儿。记住一句话:重构不是炫技,而是为了让代码更健康。下次你看到一段代码觉得「不对劲」的时候,别忍着,动手重构吧。

公众号:蓝海资料掘金营,微信deep3321