关于代码重构
公司开发的项目中随着客户的需求逐渐增加,项目版本迭代,加之参与编码人员较多,编码风格不统一,编码之前的设计缺少前瞻性难以符合新需求等问题的增加,代码会不停地堆砌,逐渐出现冗余和bug风险,如果没有人为代码质量负责,代码就会往越来越混乱的方向演化,当混乱到达一定程度,量变会引起质变,项目维护成本会主键增加,甚至已经高过开发一套新代码的成本,此时想要去重构代码已经相当艰难。因为在项目开发阶段,需要有效的代码质量监管机制,随着需求和代码量的增加,持续不断的发现代码中的 “坏味道”并及时修正,对旧有系统的不合理之处进行代码的重构,才能保证代码质量的持续达标,项目持续运行。
1、什么是重构
根据《重构——改善既有代码的设计》一书作者的定义,重构是对软件内部结构的一种调整,目的是在不改变软件可观察行为的前提下,提高其可理解性,降低其修改成本。根据重构的规模可以大致分为大型重构和小型重构:
2、大型重构
大型重构是对顶层设计的重构,包括:系统、模块、代码结构、类与类之间关系等的重构,重构的手段有:分层、模块化、解耦、抽象可复用组件等。这类重构的工具主要包括软件设计思想,设计原则和设计模式。这类重构涉及的代码改动会比较多,影响面积比较大,所以难度较大,耗时比较长,引入bug的风险也大。
3、小型重构
小型重构是对代码细节的重构,主要是针对类、方法、变量等代码级别的重构,比如规范命名和注释,消除超大类或方法,提高代码的重用性等。小型重构更多的是使用统一的编码规范,这类重构要修改的地方比较集中,比较简单,可操作性强,耗时会比较短,引入bug的风险相对来说较小 。新功能开发、修bug或者代码review中出现“坏味道”,就应该及时进行重构,持续在日常开发中记进行小重构,能够降低重构和测试成本,及时发现问题及时解决,避免大型重构的风险。
4、代码的坏味道
项目代码中的“坏味道”就是指不符合设计思想、模式和规范的代码,代码的“坏味道”增加会导致项目健壮性减弱,系统关联性过多,很难分离代码的可重复部分;由于相互依赖关系复杂,一处改变会导致其他部分的修改,不利于系统的稳定性;不同编码人员参与的编码如果没有统一的编程规范和风格,会造成代码命名杂乱,结构复杂,难于理解和阅读;代码量的增加会造成分支依赖较多,测试难度增加,无法覆盖全面。代码的“坏味道”有很多种表现形式,这里列举开发中比较常见的几种:
代码重复
在项目开发过程中,由于系统较为复杂,继承体系比较复杂,编码过程中没有对重复逻辑进行抽取,造成具有相同的实现逻辑和执行流程的方法在同一个类、不同子类或者父子类中出现,造成代码重复冗余,不利于阅读理解和管理。
方法过长
随着需求的逐渐增加,项目中方法尤其是实现主要能够的关键逻辑和方法中的代码会逐渐累积,导致方法中的语句不在同一个抽象层级,逻辑复杂混乱难以理解,需要大量注释,面向过程编程而非面向对象编程。
逻辑分散
分散式变化:某个类经常因为不同的原因在不同的方向上发生变化
散弹式修改:系统发生某种变化时,需要在多个类上进行修改
不合理的继承体系
继承打破了封装性,子类依赖其父类中特定的功能的实现细节,子类必须跟着其父类的更新而演变,除非父类专门是为了扩展而设计,并且有很好的说明文档,否则会造成系统混乱,修改难度大,代码可扩展性差。
5、代码重构技巧
代码的重构技巧有很多种,这里列举开发中比较常见的几种:
提炼方法
多个方法代码重复、方法中代码过长或者方法中的语句不在同一个抽象层级上,方法是代码服用的最小粒度,方法过长不利于复用,可读性低,提炼方法往往是重构工作的第一步。在提炼方法过程中需要把处理某件事的流程和具体做事的实现方式分开,把一个问题分解为一系列功能步骤,并假定这些功能步骤已经实现,我们只需要把各个方法组织在一起即可解决问题,在组织好整个功能后,再去分别实现各个方法。
以方法对象取代方法
将方法放进一个单独的对象中,如此一来局部变量就变成了对象内的字段,然后我们可以在同一个对象中将这个大型方法分解为多个小型方法。
使用多态代替条件判断
当存在方法中存在一条表达式时,它会根据对象类型的不同选择不同的行为,可以将这话总表达式的每个分支放进一个子类内的复写方法中,然后将原始方法声明为抽象方法。
提炼类
根据单一职责原则,一个类应该有明确的责任边界。但在实际工作中,类会不断的扩展。当某个类添加一项新任务时,会觉得不值得分离出一个单独的类,但是随着类的责任不断增加,这类类就包含了大量的数据和方法,逻辑复杂不易理解。此时需要考虑将哪些部分分离到一个单独的类中,可以依据高内聚低耦合的原则,如果某些数据和方法总在一起出现,或者某些数据经常同时变化,这就表明他们应该放在一个类中,另一种信号是类的子类化方式:如果发现子类化只影响类的部分特性,或者类的特性需要以不同的方式来子类化,这就意味着需要分解原来的类。