在每个程序员的生活中,都会有这样的时刻,他们的任务是在项目发布前为其添加最后一项功能。通常情况下,没有时间去适当地、以与代码库其他部分一致的方式来完成它。出现马虎的代码几乎是不可避免的,但这并不意味着你必须容忍它。
尽可能地重构你的代码是一种有价值的做法,它将在短期和长期内帮助你工作的任何项目。这是我们在Sunscrapers的项目中经常做的一种做法。在这篇文章中,我提供了一个来自我们的CTO--Przemek Lewandowski的真实世界的例子。
什么是代码重构?
代码重构是软件开发中的一种方法,它涉及清理和重组现有的代码,而不改变其功能。代码重构带来很多好处,包括增加可读性和降低复杂性。因此,我们可以提高代码的可维护性,使其更加简单和干净。
根据《重构,改善现有代码的设计》一书的作者Martin Fowler的说法
尽管重构的主要目标不是为了消除错误,但从长远来看,它确实有助于防止错误。重构还有助于消除和减少技术债务。如果不进行代码重构,开发人员很容易被代码拖累。
什么时候不应该重构?
当我们在做长期的软件时,重构是非常有帮助的。它可以帮助软件具有更强的适应性。然而,你应该避免执行重构,如果它:
- 超出了你的预算
- 超出了你的时间
- 代码正在生产中
- 代码符合所有要求的标准
- 代码中没有与安全相关的问题存在
- 没有考虑到风险和收益。
什么时候应该考虑软件重构?
至少有几种不同的方法应该进行重构。在一个理想的世界里,重构应该是软件开发的一个组成部分,而不是一个单独的过程:
- 对于许多开发者来说,重构的最佳时机是在开发新版本的软件之前,或者在添加新功能之前。在添加新功能之前清理代码,可以提高产品本身的质量,并使其他开发者的工作更容易。
- 另一种重构的方法是在产品发布后立即进行。这样软件程序员就有更多的时间来清理和重组代码。
- 修复错误是进行代码重构的一个完美机会。你可能会在最脏的几块代码中发现bug。通过做重构,你不仅是在清理代码,而且你可能会发现一些bug几乎可以自行修复。
- 代码审查是编程周期中一个极其重要的阶段。它有助于发现代码的缺陷,知识的转移,也可以提高代码的质量。它也是在代码发布之前对其进行重构和修复的最后机会。

如何进行代码重构:主要技术
在我们开始重构过程之前,最好先想清楚我们要改变什么和如何改变。这个过程有助于防止不受控制的代码扩展。还要记住以下提示:
- 最后期限--如果你没有足够的时间,而发布期就在眼前,最好把注意力放在调试等事情上,而不是重构。
- 大块的代码--处理这些代码需要整个团队的良好管理和计划。你应该知道,重构大段的代码可能会阻碍其他开发者的任务。
- 沟通--如果事情失控了,不要犹豫,与团队和项目经理沟通。与他们沟通可能会让你更有效地解决这个问题,而不是自己一个人去解决。
- 测试和审查 - 在进行重构工作时,为你的代码写一个测试,并请其他开发人员审查代码设计。前者可以帮助你控制过程中发生的变化,后者则有助于在实施之前对流程和建议的变化进行验证。这也是程序员之间知识传递的一个好方法。
有各种重构技术。其中一些可能只适用于某些语言或语言类型。涵盖所有的技术将需要一个以上的帖子。下面你可以找到最流行的方法。
红-绿-重构
红-绿-反应器是一种采用测试驱动开发(TDD)方法的敏捷工程模式:
- 红色--思考必须要开发的东西。
第一阶段的目的是写一个测试。测试是要失败的,因为在写的时候,被测试功能的代码并不存在。只有在满足预期的情况下,测试才会通过:
- 绿色--思考如何通过测试。
在绿色阶段,你应该写足够的代码来通过测试。在这个阶段,代码不一定要非常优雅。让我们把它留到下一个阶段:
- 重构 - 思考如何改进现有的实现。
最后也是最重要的阶段。在这一点上,你必须对代码和测试进行重构。在做这件事的时候,你应该专注于内容,并寻找方法来改善它。
要考虑到以下事项:
- 代码是否遵循正确的风格?
- 是否有重复的地方?
- 该类是否有单一的责任?
通过抽象重构进行分支
抽象重构是一种技术,通常用于以渐进的方式对一个软件系统进行大规模的改变。其主要概念是创建一个抽象层,包裹一部分将被重构的代码和最终取代它的对应代码。这种技术允许开发人员在变化仍在进行时定期发布变化。
Pull-Up/Push-Down方法是抽象重构的一个好例子。这些是与类的重构相反的类型。为了避免代码的重复,Pull-Up方法将代码部分拉到超类中。使用Push-Down方法将代码从超类向下推入子类。
组成方法
组成方法是一个基本的重构模式,应该放在每个人的工具箱里。较长的代码更难理解和实现。
组合方法有助于减少重复,精简代码。这可以通过几种方式实现,包括通过提取和内联技术。

简化方法
代码越老,它就越零散,越难读。因此,进入并简化大量的逻辑是有意义的。我们的目标是简化方法调用和类之间的交互。这可以通过多种方式实现,包括合并条件件和表达式,以及用多态性代替条件性。
简化可能包括添加、删除和引入新的参数,以及用明确的方法和方法调用代替参数。
在对象之间移动特征
在对象之间移动特征的目的是为了处理不同类之间的分布式功能。这种方法涉及到新类的创建,以及新旧类之间的功能转移。
当一个类变得过载时,是时候将一些代码分配给另一个类了。另外,如果一个类做得不多,它的功能可以转移到另一个类中,而这个类可以被删除。
重构遗留代码
有时需要重构别人创建的现有代码。可能没有足够的回归测试来确保我们最终不会破坏任何东西。
面对遗留代码,值得应用前面提到的TDD方法。然而,在这种情况下,我们通常需要在现有的代码中增加一些回归测试,并确保它们在不触及原始代码的情况下通过。事实上,这种做法在实际工作之前就已经展开了安全网。
这里有一个简短的检查表,可能是上述技术的一个好的起点:
- 检查将要被重构的代码是否被测试所覆盖。寻找测试的边缘案例,而不仅仅是一个快乐的路径。注意集成和/或e2e测试。在重构过程中,所有的用户功能应该是完全一样的。实施细节可能不同,所以一些单元测试可能需要在重构后更新。
- 如果代码没有足够的测试覆盖,那么在开始重构过程之前先写测试。
- 进行实际的重构。它通常会改善代码结构、数据流、性能、内聚力或解耦。
- 改进代码,直到所有的回归测试通过,特别是集成和e2e。
- 如果代码仍然需要重构,就去做第3点。
自动化工具可能有帮助
许多代码编辑器和集成开发环境(IDE)可以很容易地实现重构的自动化。开发人员可以通过在需要时应用重构来清理代码,这是实现测试和代码的正常部分。该功能对于需要更快地安排重构的敏捷开发者来说是非常有帮助的。这包括提取代码到一个新的函数、方法甚至是类,只需敲几下键盘。
下面是一些所谓重构浏览器的例子:
- PyDev
- PyCharm
- Visual Studio
总结
代码重构可以帮助你保持你的代码干净和到位。一个组织良好和重构的代码给你带来更少的压力--更容易找到东西和操作它。对于接手项目的人来说,它也让事情变得更容易。重构可以帮助程序员更好地理解代码,做出更好的设计决定。
定期检查和清理代码会给你带来回报,创造一个健康、更有成效的工作场所和工作程序。