您的位置:首页 > 编程语言

《重构--改善既有代码的设计》--代码的坏味道(3)

2015-06-23 16:25 274 查看
何时需要重构?

1、Duplicated Code(重复代码)

A、同一个类中的两个方法含有相同的表达式。采用Extract Method提炼出重复的代码。

B、两个互为兄弟的子类内含相同表达式。对两个类都使用Extract Method,然后Pull Up Method推入到超类。相同部分写入超类,差异部分写入派生类,这时可以运用Template Method设计模式。如果某些函数不同的算法做相同的事,可以使用Substitute Algorithm将其他函数的算法替换掉。

C、两个毫不相关的类出现相同的表达式。可以创建一个独立类,然后引用它。

2、Long Method(过长函数)

采用“间接层”—解释能力、共享能力、选择能力,都是由小函数支持。让小函数真正理解的关键是在于一个好名字。

遵循的原则:每当感觉需要以注释来说明的时候,我们就要把这些代码写入独立的函数中,并以用途来命名。

A、大量的参数与临时变量,可以运用Replace Temp With Query来消除临时变量。Introduce Parameter Object和Preserve Whole Object使参数变得简洁。如果仍然有太多参数与临时变量,使用Replace Method With Method Object。

B、条件表达式与循环是提炼的信号。使用Decompose Conditional处理条件表达式,循环提炼到独立的函数中。

3、Large Class(过大的类)

A、太多的实例变量。使用Extract SubClass提炼到某个子类中,

B、太多的方法。使用Extract Interface提炼一个接口为每个方法。

C、GUI(Graphical User Interface)类。数据与行为移到独立的领域对象,使用Duplicate Observed Data。

4、Long Parameter List(过长参数列)

A、向已有对象发出一条请求就可以取代一个参数。使用Replace Parameter With Method。

B、如果参数是来自类的字段,可以运用Preserve Whole Object将数据收集起来,并用该对象替换它们。

C、如果某此参数无对象归属,可使用Introduce Parameter Object为它们制造出一个“参数对象”。

如果“被调用对象”与“较大对象”间的不希望有依赖关系,我们可以从对象中拆解出来作为参数,如果参数太长或变化频繁,就考虑依赖结构了。

5、Divergent Change(发散式变化)

一个类受多种变化的影响, 当我们为软件添加一个功能,需要修改多个地方,就是紧耦合,这时,使用Extract Class将它们提炼到另一个类中。

6、Shotgun Surgery(霰弹式修改)

一个变化引起多个类的修改。这时使用Move Method和Move Field放在同一个类,也可以使用Inline Class放在同一个类中。但会造成少量的Divergent Change。

7、Feature Envy(依生恋情结)

当某个类中的方法需要的大部分数据不是来自本类,而是另一个类,即对另一个类产生依恋,使用Move Method和Extract Method搬移到另一个类中或创建一上独立的类。

8、Data Clumps(数据泥团)

当多个类中具有相同的字段、参数时,使用Extract Class提炼到一个独立的对象中。

9、Primitive Obsession(基本类型偏执)

把基本类型用对象的方式表示。可以运用Replace Data Value With Object,Replace Type Code With Class,Replace Type Code With SubClass或Replace Type Code With State/Strategy加以处理。

10、Switch Statements(switch 惊悚现身)

面向对象的特征是:少用switch,case语句。使用多态可以替换此语句。即运用Replace Conditional With Polymorphism。

11、Parallel Inheritance Hierarchies(平行继承体系)

是Shotgun Surgery的特例,即添加一个子类,也必须为另一个父类增加子类,可以运用Move Method和Move Field,将两个继承体系合并为一个或分开独立。

12、Lazy Class(冗赘类)

如果某些子类没有做足够的工作,试试Collapse Hierarchy,对于组件,试试Inline Class。

13、Speculative Generality(夸夸其谈未来性)

将来可能用到的函数,如果现阶段用不到,即移除。

14、Temporary Field(令人迷惑的暂时字段)

如果有两个以上的临时变量,可以使用Extract Class提炼到独立的类中。

15、Message Chains(过度耦合的消息链)

当用户A对象请求B对象,然后B对象请求C对象,再C对象请求D对象……这就是消息链,使用Hide Delegate。

16、Middle Man(中间人)

当一个类过半的函数都委托给其他类,这就是过度运用。可以使用Remove Middle Man。

17、Inappropriate Intimacy(狎昵关系)

如果两个类过于紧密,是紧耦合,或者超类与派生类过度紧密,可以使用Move Method和Move Field或Change Bidirectional Association To Unidirectional。

18、Alternative Classes With Different Interface(异曲同工的类)

如果两个函数使用不同名称却做同样的事,运用Rename Method或者Move Method还可以Extract Superlass。

19、Incomplete Library Class(不完美类库)

如果库类如果满足你的要求,可以运用Introduce Foreign Method和Introduce Local Extension。

20、Data Class(纯稚的数据类)

指那些只具有字段和属性的类,立刻运用Encapsulate Field,Encapsulate Collection,对那些不允许修改的字段运用Remove Setting Method。

21、Refused Bequest(被拒绝的遗赠)

子类继承父类的函数与数据,但是子类只想部分继承,这时为子类创建一个兄弟类,运用Push Down Method和Push Down Field,这时父类只有子类共享的东西了。

22、Comments(过多的注释)

过长和过多的注释是因为代码很糟糕。如果一段代码块需要解释做了什么,试试Extract Method,如果还需要解释其行为,试试Rename Method,需求注释某些系统的规格,试试Introduce Assertion。

当你感觉需要撰写注释时,请先尝试重构,试着让所有注释都变得多余。如果你不知道做什么,可以用注释。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: