什么情况下要重构

1 重构的目的

1.1 重构的定义

软件设计大师 Martin Fowler 是这样定义重构的:“重构是一种对软件内部结构的改善,目的是在不改变软件的可见行为的情况下,使其更易理解,修改成本更低。”

在保持功能不变的前提下,利用设计思想、原则、模式、编程规范等理论来优化代码,修改设计上的不足,提高代码质量。

1.2 为什么要进行代码重构?

重构是时刻保证代码质量的一个极其有效的手段,不至于让代码腐化到无可救药的地步。

项目在演进,代码不停地在堆砌。如果没有人为代码的质量负责任,代码总是会往越来越混乱的方向演进。

其次,优秀的代码或架构不是一开始就能完全设计好的,就像优秀的公司和产品也都是迭代出来的。我们无法 100% 遇见未来的需求,也没有足够的精力、时间、资源为遥远的未来买单,所以,随着系统的演进,重构代码也是不可避免的。

最后,重构是避免过度设计的有效手段。在我们维护代码的过程中,真正遇到问题的时候,再对代码进行重构,能有效避免前期投入太多时间做过度的设计,做到有的放矢。

1.3 工程师技术的成长重要的意义

  • 重构实际上是对我们学习的经典设计思想、设计原则、设计模式、编程规范的一种应用。

  • 重构实际上就是将这些理论知识,应用到实践的一个很好的场景,能够锻炼我们熟练使用这些理论知识的能力。

  • 重构能力也是衡量一个工程师代码能力的有效手段。

2 重构的对象

根据重构的规模,我们可以笼统地分为大规模高层次重构(以下简称为“大型重构”)和小规模低层次的重构(以下简称为“小型重构”)。

  • 大型重构指的是对顶层代码设计的重构,包括:系统、模块、代码结构、类与类之间的关系等的重构
    重构的手段有:分层、模块化、解耦、抽象可复用组件等等。

这类重构涉及的代码改动会比较多,影响面会比较大,所以难度也较大,耗时会比较长,引入 bug 的风险也会相对比较大

  • 小型重构指的是对代码细节的重构,主要是针对类、函数、变量等代码级别的重构,比如规范命名、规范注释、消除超大类或函数、提取重复代码等等。

小型重构更多的是利用我们能后面要讲到的编码规范。这类重构要修改的地方比较集中,比较简单,可操作性较强,耗时会比较短,引入 bug 的风险相对来说也会比较小。

3 重构的时机

个人比较反对,平时不注重代码质量,堆砌烂代码,实在维护不了了就大刀阔斧地重构、甚至重写的行为。

寄希望于在代码烂到一定程度之后,集中重构解决所有问题是不现实的,我们必须探索一条可持续、可演进的方式。

我特别提倡的重构策略是持续重构。

平时没有事情的时候,你可以看看项目中有哪些写得不够好的、可以优化的代码,主动去重构一下。或者,在修改、添加某个功能代码的时候,你也可以顺手把不符合编码规范、不好的设计重构一下。

Code Review 作为开发的一部分

重构能力很重要,但持续重构意识更重要。

4 重构的方法

按照重构的规模,重构可以笼统地分为大型重构和小型重构。对于这两种不同规模的重构,我们要区别对待。

对于大型重构来说,因为涉及的模块、代码会比较多,如果项目代码质量又比较差,耦合比较严重,往往会牵一发而动全身,本来觉得一天就能完成的重构,你会发现越改越多、越改越乱,没一两个礼拜都搞不定。

而新的业务开发又与重构相冲突,最后只能半途而废,revert 掉所有的改动,很失落地又去堆砌烂代码了。

在进行大型重构的时候,我们要提前做好完善的重构计划,有条不紊地分阶段来进行

每个阶段完成一小部分代码的重构,然后提交、测试、运行,发现没有问题之后,再继续进行下一阶段的重构,保证代码仓库中的代码一直处于可运行、逻辑正确的状态。
每个阶段,我们都要控制好重构影响到的代码范围,考虑好如何兼容老的代码逻辑,必要的时候还需要写一些兼容过渡代码

只有这样,我们才能让每一阶段的重构都不至于耗时太长(最好一天就能完成),不至于与新的功能开发相冲突。

大规模高层次的重构一定是有组织、有计划,并且非常谨慎的,需要有经验、熟悉业务的资深同事来主导。

小规模低层次的重构,因为影响范围小,改动耗时短,所以,只要你愿意并且有时间,随时都可以去做。

实际上,除了人工去发现低层次的质量问题,我们还可以借助很多成熟的静态代码分析工具(比如 CheckStyle、FindBugs、PMD),来自动发现代码中的问题,然后针对性地进行重构优化。

对于重构这件事情,资深的工程师、项目 leader 要负起责任来,没事就重构一下代码,时刻保证代码质量处在一个良好的状态。否则,一旦出现“破窗效应”,一个人往里堆了一些烂代码,之后就会有更多的人往里堆更烂的代码。

毕竟往项目里堆砌烂代码的成本太低了。

参考

27 | 理论一:什么情况下要重构?到底重构什么?又该如何重构?

你可能感兴趣的:(什么情况下要重构)