1. 重构初体验:什么是重构?为什么重构?重构 vs 重写

大家好,我是你们的老朋友。

今天咱们聊聊重构。说实话,这个词在圈子里被用烂了。很多人一听到「重构」,脑子里蹦出来的就是「把代码推倒重来」。嗯,这其实是个天大的误会。

我见过太多团队,打着重构的旗号,干着重写的活儿。结果呢?项目延期、Bug 满天飞、老板拍桌子。我自己也踩过这个坑,所以今天想跟你好好掰扯清楚——重构到底是什么,它跟重写有什么区别,以及为什么你值得拥有它。

从一个混乱的排序算法开始

先看一段代码。这是我早期项目里真实遇到过的,一个同事写的排序函数。你感受一下:

void sort_data(int* arr, int n) {
    int temp;
    for (int i = 0; i < n; i++) {
        for (int j = i + 1; j < n; j++) {
            if (arr[i] > arr[j]) {
                temp = arr[i];
                arr[i] = arr[j];
                arr[j] = temp;
            }
        }
    }
}

这段代码能跑吗?能。排序对吗?对。但问题在哪?

  • 变量名太随意:temp、arr、n,读起来费劲
  • 逻辑混在一起:排序、交换、循环全塞一块儿
  • 没有边界检查:万一 n 是负数呢?
  • 性能一般:冒泡排序的变种,O(n²) 复杂度

你想想看,如果这是你接手的一个模块,里面全是这种代码,你什么感觉?我当时的感觉就是——想骂人,但又得忍着,因为项目 deadline 就在下周。

什么是重构?

重构,说白了就是「在不改变外部行为的前提下,改善内部结构」。注意关键词:不改变外部行为。

什么意思?就是你的函数输入输出不变,接口不变,测试用例全部通过。你改的只是代码的写法、结构、可读性、可维护性。

核心原则:重构是手术,不是换器官。你动的是内部组织,不是外部功能。

我个人习惯把重构分成三个层次:

  1. 小重构:改变量名、提取函数、消除重复代码。几分钟搞定。
  2. 中重构:调整类结构、拆分模块、优化继承体系。可能需要半天到一天。
  3. 大重构:架构层面的调整,比如从单体拆成微服务。这通常需要团队协作,持续数周。

刚才那段排序代码,属于小重构的范畴。我们试试看:

void bubble_sort(int* array, int size) {
    if (array == nullptr || size <= 0) {
        return;  // 边界检查
    }

    for (int i = 0; i < size - 1; ++i) {
        bool swapped = false;
        for (int j = 0; j < size - i - 1; ++j) {
            if (array[j] > array[j + 1]) {
                std::swap(array[j], array[j + 1]);
                swapped = true;
            }
        }
        if (!swapped) {
            break;  // 优化:如果没发生交换,说明已经有序
        }
    }
}

看到了吗?我没改排序算法本身,但代码清晰多了:

  • 函数名从 sort_data 变成 bubble_sort,一目了然
  • 加了边界检查,防止空指针和非法长度
  • 用了 std::swap,不用自己写交换逻辑
  • 加了 swapped 标志位,提前终止循环——性能也提升了

小技巧:重构时,每改一步就编译一次、跑一次测试。别想着「改完再测」,那样你会死得很惨。我曾经一次性改了 10 个文件,结果编译都过不了,回退花了一整天。

为什么重构?

你可能会问:代码能跑不就行了?干嘛费劲重构?

嗯,这个问题我当年也问过。直到有一次,一个紧急需求下来,我需要在那个混乱的排序模块里加一个新功能。结果呢?我花了三天才看懂原来的逻辑,改完后又引入两个 Bug,线上出了事故。老板找我谈话,那滋味……

重构的价值,其实就三点:

维度 不重构的后果 重构后的收益
可读性 代码像天书,新人上手慢 一眼看懂逻辑,降低沟通成本
可维护性 改一处牵全身,Bug 频发 模块清晰,改动局部化
可扩展性 加功能像打补丁,越补越乱 预留扩展点,新功能轻松接入

说白了,重构是在为未来的自己省钱。你今天花 1 小时重构,可能省下未来 10 小时的调试时间。这笔账,你算算。

重构 vs 重写

这是最容易混淆的地方。我见过太多人把「重写」当「重构」用,结果项目翻车。

警告:重写是推倒重来,重构是逐步改善。两者有本质区别。

我列个对比表,你一看就明白:

维度 重构 重写
风险 低,逐步进行,随时可回退 高,一次性替换,失败代价大
时间 持续进行,融入日常开发 集中投入,通常需要专门项目
业务影响 几乎无影响,功能保持不变 可能中断业务,需要重新验证
适用场景 代码结构差但逻辑正确 技术栈过时、架构彻底不合理

举个例子。你有一栋老房子,墙皮脱落、水管老化。重构就是:今天刷个墙,明天换根水管,后天修个窗户。房子一直能住人。重写呢?把房子拆了,重新盖一栋。这期间你得住酒店,成本高、周期长。

我在项目中遇到过最惨的一次重写:一个团队花了 6 个月重写核心模块,结果上线第一天就崩了,因为新代码没考虑到老系统里的 200 多个边界情况。最后不得不回退,那 6 个月白干了。

重构的魅力在哪?

重构最大的魅力,在于它让你持续进步,而不是一步到位。

你不需要等到「有空了」再重构。重构可以融入日常:

  • 今天改个变量名
  • 明天提取个公共函数
  • 后天优化个循环

每次改动都很小,风险可控。但积累下来,代码质量会肉眼可见地提升。

我记得有一次,我接手一个遗留系统,代码里到处都是 int a, b, c 这种命名。我每天花 15 分钟重构一个函数,一个月后,整个模块的可读性提升了不止一个档次。新来的同事说:「这代码写得真清楚。」我心里暗爽——其实一个月前它还是一坨屎。

本章知识体系

下面这张图,帮你理清本章的核心逻辑:

重构初体验:知识体系 重构 (Refactoring) 什么是重构? 为什么重构? 重构 vs 重写 不改变外部行为 改善内部结构 提升可读性 降低维护成本 低风险、逐步改善 高风险、推倒重来 核心原则:不改变外部行为,持续改善内部质量

小结

这一章,我们从一段混乱的排序代码出发,聊了重构的本质。记住三个关键点:

  • 重构是改善内部结构,不改变外部行为
  • 重构的价值在于提升可读性、可维护性、可扩展性
  • 重构和重写是两码事,别混为一谈

下一章,我会带你深入重构的具体手法,从「改名字」开始,一步步把烂代码变成艺术品。咱们到时候见。

一句话总结:重构不是重写,是持续进步。别等代码烂透了再动手,每天改一点,积少成多。

可可精品资料库