重构改善既有代码的设计
1.Duplicated Code
代码重复往往来自于copy-and-paste编程风格,重复的代码使得代码难以理解和维护,如果系统中充斥了大量的重复代码,对系统维护者来说,每次很小的改动,他都要保证几分copy都同时修改掉。测试回归点也非常多。解决这个问题的方法就是靠重构代码,发现重复代码时,将重复代码抽离出来,然后所有调用点全部复用这段代码。当然,避免编写重复代码是最好的,一旦发现自己在编写重复代码,
就立刻进行代码重构。
2.Long method
方法如果过长,最主要的问题是难以理解,不容易理解导致的是调试和修改代码会非常麻烦,进而使得代码质量变差。方法做的事情太多,
不符合职责单一,很难进行复用,使得此时会编写很多重复代码。此时应该将密切相关代码抽离到单独的方法,原方法会立刻变得清晰。
3.Large Class
类似于方法过长,类提供功能太多,使得这个类不容易复用,别人很难理解设计这个类的意图,职责不单一,也会引起重复代码问题。
4.Divergent Change
一个类里面的属性值变化率不同。某些状态一个小时变一次,某些则几个月一年才变一次;某些状态因为这方面的原因发生变化,而另一些则因为其他方面的原因变一次。面向对象的抽象就是把相对不变的和相对变化相隔离。这使得这些相对不变的可以重用。问题变化的每个方面都可以单独重用。这种相异变化的共存使得重用非常困难。
5.Shotgun Surgery
这正好和上面相反。对系统一个地方的改变涉及到其他许多地方的相关改变。这些变化率和变化内容相似的状态和行为通常应当放在同一个类中。
6.Feature Envy
对象的目的就是封装状态以及与这些状态紧密相关的行为。如果一个类的方法频繁用get、set方法存取其他类的状态进行计算,那么你要考虑把行为移到涉及状态数目最多的那个类。
7.Data Clumps
某些数据通常会一起出现在很多类的成员变量中,一起出现在许多方法的参数中,这些数据应该自己独立形成对象。
8.Primitive Obsession(基本类型迷恋)
有些人习惯使用几个原始类型的数据来表示一个概念。例如对于坐标,他们会使用两个数字(10,20);对于Money,他们会用一个浮点数来表示。这使得代码变的难以理解,解决问题的难度大大增加。
9.Switch Statement
基于常量的开关语句是OO的大敌,你应当把他变为子类、state或strategy。
10. Parallel Inheritance Hierarchies
并行的继承层次是shotgun surgery 的特殊情况。因为当你改变一个层次中的某一个类时,你必须同时改变另外一个层次的并行子类。
11. Lazy Class
一个干活不多的类。类的维护需要额外的开销,如果一个类承担了太少的责任,应当消除它。
12. Speculative Generality
一个类实现了从未用到的功能和通用性。通常这样的类或方法唯一的用户是testcase。不要犹豫,删除它。
13. Temporary Field
一个对象的属性可能只在某些情况下才有意义。这样的代码将难以理解。专门建立一个对象来持有这样的孤儿属性,把只和他相关的行为移到该类。最常见的是一个特定的算法需要某些只有该算法才有用的变量。
14. Message Chain
消息链发生于当一个客户向一个对象要求另一个对象,然后客户又向这另一对象要求另一个对象,再向这另一个对象要求另一个对象,如此如此。这时,你需要隐藏分派。
15. Middle Man
对象的基本特性之一就是封装,而你经常会通过分派去实现封装。但是这一步不能走得太远,如果你发现一个类接口的一大半方法都在做分派,你可能需要移去这个中间人。
16. Inappropriate Intimacy
某些类相互之间太亲密,它们花费了太多的时间去砖研别人的私有部分。
17. Alternative Classes with Different Interfaces
做相同事情的方法有不同的函数signature,一致把它们往类层次上移,直至协议一致。
18. Incomplete Library Class
要建立一个好的类库非常困难。我们大量的程序工作都基于类库实现。然而,如此广泛而又相异的目标对库构建者提出了苛刻的要求。库构建者也不是万能的。有时候我们会发现库类无法实现我们需要的功能。而直接对库类的修改有非常困难。此时我们可以对类库进行扩展。
19. Data Class
对象包括状态和行为。如果一个类只有状态没有行为,那么肯定有什么地方出问题了。
20. Refused Bequest
超类传下来很多行为和状态,而子类只是用了其中的很小一部分。这通常意味着你的类层次有问题。
21. Comments(太多注释)
经常觉得要写很多注释表示你的代码难以理解。可以通过定义有意义变量名、方法名的方式提高代码的可读性,减少注释。