常见的不良编码习惯
什么样的代码需要被重构呢?《重构——改善既有代码的设计》一书中已经有了非常全面的论述,下面就是从该书中,总结出来的“代码的坏味道”。
-
Duplicated Code(重复的代码)
重复代码是最常见的异味,往往是由于Copy&Paste造成的,最单纯的重复的代码就是“同一个类(class)内的两个函数含有相同的表达式(expression)”. -
Long Method(过长的函数)
过长的函数是面向结构程序开发带来的后遗症,降低了程序的可读性。 -
Large Class (过大的类)
过大的类使得责任不清晰,使得代码复杂程度大大增加,难以维护。 -
Large Parameter List (过长的参数列表)
过程的参数列表难以理解,同时参数传递也容易出错 -
Divergent Change(发散式变化)
一个类,完成多个业务功能,需要修改时,将具有不同的原因和理由。比如,该类同时完成添加和删除功能,当我要修改添加功能时,有机会影响删除功能。 -
Shotgun Surgery(散弹式修改)
散弹式修改类似发散式变化,但恰恰相反。如果每遇到变化,你都必须在许多不同的classes内做出许多小修改来响应,你所面临的坏味道就是散弹式修改。如果需要修改的代码散布四处,你不但难以找到他们,也很容易忘记某个重要的修改。 -
Feature Envy (依恋情结)
函数对某个class的兴趣高过对自己所处类的兴趣,这种孺慕之情最通常的焦点便是数据。无数次经验里,我们看到某个函数为了计算某值,从另一个对象那调用几乎半打的取值函数(getting method)。 -
Data Clumps(数据泥团)
在很多地方看到相同的三或四笔数据项:两个类内的相同域(field)、许多函数签名式(signature)中的相同函数。 -
Primitive Obsession (基本型别偏执)
大多数编程环境都有两种数据:结构型别(record types)允许你将数据组织成有意义的形式;基本型别(Primitive type)则是构成结构型别的积木块。结构总是会带来一定的额外开销,它们有点想数据库中的表格,或是那些得不偿失的东西,如只为做一两件事而创建,却付出太大额外开销的东西。 -
Switch Statements(switch语句)
switch语句的问题在于重复,你常会发现同样的switch语句散步于不同地点。如果要为它添加一个新的子句,你必须找到所有switch语句并修改它们。 -
Parallel Inheritance Hierarchies(平行继承体系)
平行继承体系其实是shotgun surgery(散弹式修改)的特殊情况。在这种情况下,每当你为某个类增加一个子类,必须也为另一个类相应的增加一个类。如果你发现某个继承体系的名称前缀和另一个继承体系的名称前缀完全相同,便是闻到了这种坏味道。 -
Lazy Class (冗赘类)
如果一个类的所得不值其身价,它就应该消失,不要出现冗余代码。 -
Speculative Generally(夸夸其谈未来性)
现在用不到,觉得未来可以用到的代码,要警惕。当有人说“噢,我想我们总有一天需要做这事”,并因而企图以各式各样的挂钩(hooks)和特殊情况来处理一些非必要的事情,这种坏味道就出现了。 -
Temporary Field(令人迷惑的临时变量)
-
其内某个实例变量仅为某种特定情势而设。这样的代码让人不易理解,因为你通常认为对象在所有时候都是需要它的所有变量。在变量未被使用的情况下猜测当初其设置目的,会让你发疯。
-
Message Chains (过度耦合的消息链)
-
如果你看到用户向一个对象所求(request)另一个对象,然后再向后者索求另一个对象,然后再索求另一个对象。。。。这就是 过度耦合的消息链。
-
Middle Man(中间转手人)
-
对象的基本特征之一就是封装——对外部世界隐藏其内部细节。封装往往伴随delegation(委托)。但是人们可能过度运用委托。你也许会看到某个类接口有一半的函数都委托其他类,这样就是过度运用。
-
Inappropriate Intimacy (狎昵关系)
-
有时你会看到两个类过于亲密,花费太多时间去探究彼此的私有成分。如果这发生再两个“人”之间,我们不必做卫道之士;但对于类,我们希望它们严守清规。
-
Alternative Classes with Different Interfaces(异曲同工的类)
-
如果两个函数做同一件事,却有着不同的签名式(signatures),这就是异曲同工的类。
-
Incomplete Library Class(不完美的程序库类)
-
复用常被视为对象的终极目的。我们认为这实在是过度估计了,我们只是使用而已。
-
Data Class(数据类)
-
所谓数据类是指:它们拥有一些值域,以及用于访问(读写)这些值域的函数,除此之外一无长物。将数据类中数据以公共方式公布,没对数据访问进行防护。
-
Refused Bequest(被拒绝的遗赠)
-
子类不想继承子类的数据或方法,在真正该继承的时候才能选择继承,不然就会出现代码坏的味道。
-
Comments(过多的注释)
-
代码有着长长的注释,但注释之所以多是因为代码很糟糕。