所谓重构,是指在维持代码功能不变的前提下,重新建立其结构,以提高效率,降低风险。
重构可以从以下几方面着手:
调整格式,改善外观
当代码符合组织的编码规范,其格式在项目里面保持一致,与整个团队所采用的风格相符,就可以帮助我们更容易发现语句和表达式中某些微妙的错误。比如,当代码缩进得比较整齐,可以使得其控制流就会显得更加清晰;可以令我们比较容易看出那些复杂的表达式及函数调用操作写得是否正确。又比如,添加空行和必要的注释,可以帮助阅读者更好地理解代码的结构和含义。
严格来说,格式/外观的变化不是结构的调整,但它通过规范格式/外观也能够使得隐藏的错误更加突出,同样起到了重构的效果。
去除重复的代码
重复的代码一旦出现bug,那么你很可能会在修复bug时遗漏其中的一处或几处。所以,重复的代码存在很大风险,我们在进行重构时应当尽力去除重复的代码。方法是把这些重复的代码全都放到一个常用的例程、类或模板里面,这样只需要修改一次这个例程、类或模板,就可以在整个程序中见效,不会有任何遗漏的风险。注意在把这个例程、类或模板提取好之后,要逐个删除原来每一处重复的代码。
如果重复的代码隐藏在switch语句里面,那么最好的重构方法是彻底消除switch语句。我们可以把每个case分支有关的行为,移入到各子类的对应方法中,并且对这个多态方法进行调用,以替换原来的switch语句。
打散数据泥团
数据泥团是指那些经常同时出现的数据对象。这些搅在一起的数据也容易引发bug。我们应该把这些数据放到某个类中,并改用那个类的对象来表示某些参数及返回值,这样不仅能够对原来众多的数据对象进行归类管理,而且还可以防止由于忘写某个数据对象所引发的bug。
比如,如果你用整数来表示货币值,那就有可能出现把两种不同的货币值直接相加的错误。为了避免这样的错误产生,我们可以建立一个“货币”类,并且用类的对象来表示不同的货币值。与之类似,基本类型的数组,也应该改成链表或大小可变的vector等容器;那些针对时间、质量、力、能和加速度等具体的物理概念都可以定制特别的类,而不采用原始的浮点数类型来表示它们的值。这样做令我们能够以适当的方法来表示这些类之间的结合关系(例如,力=质量×加速度),从而避免那种类型错乱的赋值行为。
规范类的接口
如果每个类都各自支持一套不同的方法,而这些方法的名称、参数顺序及参数类型也都各有区别,那么也会很容易造成混乱引发bug。面对这种情况,重构时应该通过重命名及调整顺序等做法来使这些类的方法名称及参数顺序彼此相似,并且通过删除和移动方法等手段来使各个类所拥有的方法也彼此相似。甚至在作出这些调整之后,使得这些类都具备类似的新接口,我们还能够发现新的重构机会。
避免过长的函数/例程
过长的函数或例程是很难阅读和调试的,重构时应该将其拆分为多个小块,并对复杂的条件进行分解,通过对其他例程的调用来表达这个复杂的逻辑。
削减代码段之间的依赖
如果代码段之间存在过于依赖的关系,那么就有可能把某些错误的交互行为掩盖起来。重构时应该通过移动方法及字段等办法来尽量打破这种依赖关系。如果有些类之间依赖关系难以去除,那也要尽量确保这种关系是单向而非双向的。
删掉那些永远执行不到的代码
删除无用的代码和参数、去掉无用的类、把仅有的调用的类进行内联,并给那些名称特别抽象的方法重新赋予反映其功能的更有意义的名字,这些举措都可以使bug无处藏身。
这正是:
重构具体怎着手,以上七方供参考
只要设计能用简,重构效果看得见
参考书目:软件和系统调试的66个有效方法,作者:Diomidis Spinellis,出版社:机械工业出版社
联系客服