码迷,mamicode.com
首页 > 其他好文 > 详细

《重构:改善既有代码的设计》 笔记 2

时间:2015-07-08 14:24:00      阅读:123      评论:0      收藏:0      [点我收藏+]

标签:

 

代码的坏味道:

1、Duplicated Method(重复代码)

  (1)同一个类的两个函数含有相同的表达式  用  Extract Method(110)

  (2)两个互为兄弟的子类内含相同表达式  两个类都用 Extract Method,然后对用Pull Up Method(332)推入超类

    两个互为兄弟的子类内含类似表达式  两个类都用 Extract Method 将相似和差异部分隔开。

            运用Form Template Method(345) 获得一个Template Method设计模式。

    不同的算法作相同的事,选择较清晰的一个,Substitute Algorithm(139) 将其他替换掉

  (3)不相关的类方法重复。其中一个类使用Extract Class,重复代码提炼到一个独立类中,在另一个类中使用这个新类。

    或者这个代码本就应在在两者之一的类中,而不是新的类,需要判断。

 

2、Long Method(过长函数)

  “间接层”所能带来的全部利益:解释能力、共享能力、选择能力——都是由小型函数支持的。

   程序愈长愈难理解。过短函数让代码阅读者必须经常转换上下文去看看子程序做了什么,然短函数容易理解的真正关键在于一个好名字。如果你能给函数起个好名字,读者就可以通过名字了解函数的作用,根本不必去看其中写了些什么。

  可遵循的一条原则:每当感觉需要以注释来说明点什么的时候,我们就把需要说明的东西写进一个独立函数中,并以其用途(而非其实现手法)命名。

哪怕替换后的函数调用比函数自身还长,只要函数名称能够解释其用途,就要做——关键在函数“做什么”和“如何做“之间的语义距离。

  函数内如果有大量的参数和临时变量,会传递给新函数的形参,对你的函数提炼形成阻碍,导致可读性几乎没有任何提升 ——可以使用Replace Temp with Query(120) 来消除临时元素。Introduce Parameter Object(295) 和 Preserve Whole Object(288) 则可以将过长的参数列变的更简洁些。
 
  如果仍然有太多临时变量和参数,那就应该 Replace Method With Method Object(135) “用方法对象替换方法”。
 
  如何确定该提炼哪一段代码?
    寻找注释
    寻找条件式:Decompose Conditional (238) 分解条件  
    寻找循环:将循环和其内代码提炼到一个函数中

3、Large Class(过大的类)

  如果想利用单个类做太多事情,其内往往就会出现太多实例变量。

  可以将几个变量一起提炼至新类内。提炼时应该选择类内彼此相关的变量,将它们放在一起。例如depositAmount和depositCurrency可能应该隶属同一个类。

  通常如果类内的数个变量有着相同的前缀或字尾,这就意味着有机会把它们提炼到某个组件内。如果这个组件适合作为一个子类,你会发现Extract Subclass往往比较简单。

  如果类内有太多代码,最简单的解决方案是把东西消弭于类内部,比如有五个“百行函数”,它们之中很多代码都相同,那么或许你可以把它们变成五个“十行函数”和十个提炼出的“双行函数”。

  和"拥有太多实例变量"一样,一个类如果拥有太多代码,往往也适合使用 Extract Class和Extract Subclass. 这里有个技巧:先确定客户端如何使用它们 ,然后运用为每一种使用方式提炼出一个接口。这或许可以帮助你看清楚如何分解这个类。

  如果你的Large Class是一个GUI类,你可能需要把数据和行为移到一个独立的领域对象去。你可能需要两边各保留一些重复数据,并保持两边同步。Duplicate

Observed Data(189)

 

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

  因为太长的参数列难以理解,太多参数会造成前后不一致、不易使用,而且一旦你需要更多数据,就不得不修改它。如果将对象传递给函数,大多数修改都将没有必要,因为你很可能只需在传入对象内增加一两个字段,就能得到更多数据。

  如果向已有的对象发出一条请求就可以取代一个参数,那么你应该激活重构手法Replace Parameter with Method(292)。在这里,"已有的对象"可能是函数所属类内的一个字段,也可能是另一个参数。你还可以运用Preserve Whole Object(288)将来自同一对象的一堆数据收集起来,并以该对象替换它们。如果某些数据缺乏合理的对象归属,可使用Introduce Parameter Object(295)为它们制造出一个"参数对象"。

 

5、Divergent Change(发散式变化)

如果某个类经常因为不同的原因在不同的方向上发生变化,Divergent Change就出现了。

6、Shotgun Surgery(霰弹式修改)

如果每遇到某种变化,你都必须在许多不同的类内做出许多小修改,你所面临的坏味道就是Shotgun Surgery。

7、Feature Envy(依恋情结)

有一种经典的气味是:函数对某个类的兴趣高过对自已所处类的兴趣。

8、Data Clumps(数据泥团)

你常常可以在很多地方看到相同的三四项数据:两个类中相同的字段、许多函数签名中相同的参数。这些总是绑在一起出现的数据真应该拥有属于它们自已的对象。

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

10、Switch Statements(switch惊悚现身)

面向对象程序的一个最明显特征就是:少用switch语句。从本质上主,switch语句的问题在于重复。你常会发现同样的switch语句散布于不同地点。

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

每当你为某个类增加一个子类,必须也为另一个类相应增加一个子类,便是这种坏味道。

12、Lazy Class(冗赘类)

如果一个类的所得不值其身价,它就应该消失。

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

用不上的装置只会挡你的路,所以,把它搬开吧。

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

有时你会看到这样的对象:其内某个实例变量仅为某种特定情况而设。这样的代码让人不易理解,因为你通常认为对象在所有时候都需要它的所有变量。

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

如果你看到用户向一个对象请求另一个对象,然后再向后者请求另一个对象,然后再请求另一个对象.....这就是消息链。

16、Middle Man(中间人)

人们可能过度运用委托,也许你会看到某个类接口有一半的函数都委托给其他类,这就是过度委托。

17、Inappropriate Intimacy(狎昵关系)

一个类过多访问另一个类的私有成员

18、Alternative Classes with Different Interfaces(异曲同工的类)

如果两个函数做同一件事,却有不同的函数名,请运用rename method方法根据它们的用途重命名。

19、incomplete library class(不完美的库类)

库类构筑者没有未卜先知的能力,因此,库往往构造得不够好,而且往往不可能让我们修改其中的类使它完成我们希望的工作。这时有两个重构方法可采用:(1)如果你只想修改库类的一两个函数,可以运用introduce foreign method;(2)如果想要添加一大堆额外行为,就得运用introduce local extension。

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

所谓Data Class是指:它们拥有一些字段,以及用于访问(读写)这么字段的函数,除此之外一无长物。Data Class就像小孩子,作为一个起点很好,但若要让它们像成熟的对象那样参与整个系统的工作,它们就必须承担一定责任。

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

Refused Bequest是指子类继承了父类的函数和数据,但子类只从中挑选几样来玩,不需要接受父类这么多的东西。按传统做法:你需要为这个子类新建一个兄弟类,再运用Push Down Method和Push Down Field把所有用不到的函数和变量下推给那个兄弟。这样一来,超类就只持有所有子类共享的东西。但是作者不建议你每次都这么做,这种坏味道十之八九很淡,不值得理睬。

22、Comments(过多的注释)

Comments可以带我们找到上面提到的各种坏味道。找到坏味道后,我们首先应该以各种重构手法把坏味道去除。完成之后我们常常会发现:注释已经变得多余了,因为代码已经清楚说明了一切。

如果你不知道该做什么,这才是注释的良好运用时机。除了用来记述将来的打算之外,注释还可以用来标记你并无十足把握的区域。你可以在注释里写下自已“为什么做某某事”。这类信息可以帮助将来的修改者,尤其是那些健忘的家伙。

 

 

 

 

Extract Method(110)

Pull Up Method(332)

Form Template Method(345) 

Substitute Algorithm(139) 

Replace Temp with Query(120)
 
Introduce Parameter Object(295)
 
 
Preserve Whole Object(288) 
 
Replace Method With Method Object(135) “用方法对象替换方法”
 
Decompose Conditional (238) 分解条件

Extract Interface(341)

Duplicate Observed Data(189)

《重构:改善既有代码的设计》 笔记 2

标签:

原文地址:http://www.cnblogs.com/maxiaodoubao/p/4629816.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!