浅谈代码重构

2019/10/29      2220 文章来源:优百 丨 作者:史禹哲

什么是代码重构?

在Martin Fowler的名著《重构:改善既有代码的设计》中对重构做了如下定义:
重构(名词):对软件内部结构的一种调整,目的是在不改变软件可观察行为的前提下,提高其可理解性,降低其修改成本。
重构(动词):使用一系列重构手法,在不改变软件可观察行为的前提下,调整其结构。

由此可见,代码重构的根本意义在于提高代码的可理解性以及降低修改成本,也就是说代码重构前后,功能保持不变,性能有可能提升也有可能降低。

为什么要代码重构?

那么一定有人会问我们又为什要去做这种既不能提升性能又没有提供新功能的事情呢?
结合公司现有的项目情况以及实际工作遇见的问题,代码重构所带来的的好处不是短期的,而是要从长远的角度去考虑。一般情况下一个软件从最初开发的时候开始就不是一个人能够完成,而且通常需要很多程序员进行后续的维护,那么代码是否通俗易懂就显得尤为重要。
在软件在制造之初,我们会对其进行精心的设计,讨论技术方案,制定命名规则以及代码规范,然后程序员根据产品设计的需求进行开发。此时的代码架构是良好的,并且代码也具备很好的可扩展性。开发完成之后软件就要经受真正的挑战了,交付给客户,此时客户会提出大量的需求,也有可能会发现一些潜在的BUG。尤其是项目周期较短的项目,此时就需要程序员在短时间内修改尽量多的BUG完成尽量多的需求开发,通常这时候的程序员是在没有完全理解软件的整体架构及设计情况下,就着手去做的。于是,就会出现越来越多的随意的对象命名,混乱的排版布局,没有一行注释的功能模块。那么当新人来维护这套代码的时候,会发现源码晦涩难懂,架构混乱不清,也因此越来越难通过阅读源码来理解最初的设计意图。此时维护软件的难度及时间都会大幅度提升,而定期的代码重构可以在一定程度上避免这种情况的发生,从而降低运维的成本。

何时进行代码重构以及如何重构?

当我们发现阅读源码已经比较困难的时候,再准备大刀阔斧的开始重构代码吗?严格来说这个时候已经有些晚了,重构应该是在工作中每时每刻都在做的。以下的几个时间节点是我认为的比较合适做代码重构的时机

添加新功能时

在拿到新需求时,可以不必急于动手,先想一下整个系统中是否有相似的功能模块,结合公司现有的主数据项目,物料分类是一个树形结构的主数据,物料模板以及物料代码都需要通过物料分类这个树形结构来进行查询以及快速定位,那么我们可以在物料模板跟物料代码页面上增加物料分类的树形结构,此时如果模板先前已经将分类加在了页面中,我们在对代码页面进行优化的时候,可以直接将模板中的方法复制过来稍加修改就使用,但这意味着如果将来某一个新的主数据也需要关联物料分类的类别树时,你只能再一次的复制修改。同时,如果这块功能需要完善并进行修改时,你也需要找到所有曾经复制的地方,并进行多次修改。而此时如果将先前的模板里已经写好的代码抽成函数,并稍加修改,此时的工作量可能会比直接复制要多,但是却大大节省了后续维护的成本,此时如果再有别的地方需要用的这个功能,那么我们就只需要调用这个函数并传参

修改BUG时
主数据系统多个主数据功能模块间业务层面上功能差距较大,但实际底层代码上,很多地方的逻辑都大同小异。这也就导致有的时候业务人员发现了某个BUG,开发人员改完之后,业务人员又在另一个主数据模块发现了同样的BUG。此时我们可以审视一下系统,将相似的功能模块进行测试,在排除BUG的同时,我们可以将所有相似的功能模块进行重构,毕竟修改一处总是要比修改多处省时的多

有时我们修改的BUG可能一开始并不是我们自己所写的,那么此时我们要先通过阅读源码来理解这段代码,如果在阅读的过程中发现代码结构十分糟糕,对象及变量命名一塌糊涂,那么此时我们也可以参照命名规则及代码规范对代码进行重构

性能优化时
首先我们要明确代码重构并不能带来性能的提升,相反有可能会导致性能下降。但是这并不影响我们在性能优化时进行不影响性能的代码重构

记得某一个项目客户反映主数据系统页面查询太慢,我们调查代码发现,此类主数据在查询时,有大量的外键关联,上一任开发人员写了过多的循环嵌套,导致页面上仅仅只显示20条数据,后台却查了100多次数据库。此时发现,除了通过在数据库中增加索引以提升性能外,我们还应该对代码进行重构,减少嵌套,优化逻辑,提高代码的可读性

代码检查时

在做主数据开发的时候,因为功能模块较多,工作量较大,所以整套程序必然是由多个开发人员共同完成,那么此时代码检查就显得尤为重要。通常我们可以通过代码检查来确保系统是完全按照开发规范以及命名规则来开发的,同时我们也可以在代码审核中发现一些冗余代码。每一个人拿到的需求都是自己那一个模块的需求,然而通常都会存在跨模块间有相同或相似的功能,那么当代码检查时发现这种情况时,我们可以对这部分功能进行代码重构

是否所有的代码都要重构?

那么有没有什么时候是不应该重构的?答案是肯定的。毕竟我们在一开始就提到了代码重构的意义是提高代码的可理解性以及降低修改成本,所以当你发现某一块代码重构的代价已经比重写还要大了,那么当然就没必要重构了。如果某一块代码你不需要使用,而且也不存在BUG需要修改,那么也没必要重构,毕竟世界上没有什么是绝对完美的