Skip to content
On this page

重构的关键是:运用大量微小的、保持软件行为的步骤,一步步达成大规模的修改。

  • 重构可能会带来什么?

    • 改变代码调用栈,程序性能有所比变化
    • 改变接口声明,改变模块接口
    • ...
  • 重构和性能优化的区别:

    • 都改变了代码
    • 重构是为了代码更好理解
    • 性能优化是为了代码运行更快,但最终代码可能更难维护。
  • 开发时的两顶帽子🎩(两个阶段,反复横跳)

    • 添加新功能时,只关注添加新功能,不修改既有代码。添加测试并让测试完成。
    • 重构时,只关注调整代码结构,(非不要时)不添加和修改测试。
  • 设计耐久性假说

image.png

何时重构

  • 事不过三,三则重构

  • 预备性重构:重构最好的时机是添加新功能之前

    • 对于某个函数提供了我需要的大部分功能,只需要修改几个地方即可重复使用,此时应该复制粘贴,而是进行函数参数化,进行重构。
    • 重构之后的代码出现相同bug的概率会很低,如果通过负责粘贴,我们可能还需要反复修复同样的bug。
  • 捡垃圾式重构

    • 对于简单的重构,可以立即去执行
    • 对于比较复杂的重构,需要记下来,后续再进行重构

重构时的权衡

  • 写代码时,会做出很多权衡取舍

    • 参数化需要做到什么程度?
    • 函数之间的边界应该划在哪里?
    • 对于昨天的功能完全合理的权衡,在今天要添加新功能时可能就不再合理。
  • 需要不断的权衡现实情况的变化,简洁的代码重构起来会更加容易。

  • 添加新功能最快的方法往往是先修改现有的代码,使新功能更容易被加入。

  • 何时不重构

    • 在不理解其工作原理时,不重构,因为此时重构没有价值
    • 当重写比重构更加容易时,进行重写,此需要具备一定的判断。

重构代码的目的是,添加新功能更快,修bug更快,程序代码更好理解。重构总是由经济利益驱动的。意义不在与把代码库打磨的光鲜亮丽(误区)。

  • 对重构采取不同的策略

    • 简单设计,增量式设计。
    • 思考“以后重构有多困难”,判断此时是否需要进行重构,添加代码灵活性。
  • 重构与性能的权衡

    • 重构可能使软件运行更慢,但它也使软件的性能优化更容易。
    • (除了对性能严格要求的实时系统),其他情况下,编写快速软件的秘密就是:先写出课调优的软件,再调优到足够的速度。
    • 有时候,我们大部分时间都花在了优化一小部分代码上,但往往这部分代码大多很少被执行,可能花费的功夫是白费的。
    • 需要对程度有清晰的认识,使用工具测试程序的真实情况,找到问题的真实原因。

重构场景下的代码方案

重构代码导致的分支问题

  • 合并和集成是两回事:
    • 如果从主线合并到某个分支,只是单向的代码移动,主线没有改变。
    • 如果是集成,则是双向的。
  • 假设我重构了代码,修改了源函数名称,a此时提交了代码到主线,而我使用集成,把主线的代码进行集成,此时代码可能就会出现问题,因为a的代码可能存在旧函数的引用,而此时我的重构代码也集成到了主线中,导致代码被破坏。

引入测试

  • 想要重构之前,需要有可以自测的代码。
  • 消除“重构风险太大,可能引入bug”的担忧。
  • 一开始就写能自测试的代码

对数据库的重构

  • 最好是分散到多次生产发布来完成。这样子如果造成问题,比较容易回滚。
  • 运用“并行修改”:
    • 比如要改名一个字段。
    • 在第一次提交会新增一个字段,但暂时不使用它。之后修改数据写入的逻辑,使其同时写入新旧两个字段,随后修改读取数据的地方,逐个修改为新字段。
    • 暂停一下,看看有没有bug冒出来,确定没有bug后,再删除旧字段。

程序优化的流程

  • 先用工具监控程序的运行,找到消耗时间和空间的地方。
  • 小幅度进行修改,每一步都需要编译、测试,如果没有提高性能,则撤销修改,重复执行这个流程,直到获得满意的性能为止。
  • 前期编写好的代码,可以让我们带入到范围较小的代码快,性能的调整也会更容易些;代码清晰,可以更好的理解自己的选择,清楚哪种调整起关键的作用。

MIT Licensed | Copyright © 2021 - 2022