代码坏味道 重构: 改善有效代码的设计--阅读笔记

来源:互联网 发布:淘宝清关无法提交信息 编辑:程序博客网 时间:2024/04/30 06:31

重构: 改善有效代码的设计 阅读笔记

 

(1) 重复代码(Duplicated code)

           1 一个类两个函数有相同表达式                          extract method

           2 两个互为兄弟的子类含有相同的表达式          extract method

           3 两个毫不相关的类出现重读代码                      Extract class

(2) 过长函数(Long method)

          标准:每当你需要以注释来说明点什么的时候,就可以把需要说明的东西写到一个独立的函数中进行。

          1 如果函数中存在大量的参数和临时变量。       Extract method可读性不会有提升,Replace with Query。 Introduce Parameter Object和Preserve whole Object及杀手锏 Replace methoid with method Object.

         2条件表达式和循环可以使用                                 Decompose Conditional处理条件表达式

(3)过大类(Large class)

         1 一个类中有太多变量,可以讲几个彼此相关的变量提炼到一个新类内。可以多次使用

         2 一个类中有太多代码,可以使用Extract class和extract subclass。也可使用extract Interface为每一种方式提炼出一个接口。

         3 如果Large class是一个GUI类,可以讲数据和行为移到一个独立的领域对象中去。 

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

         1 可以使用另一个对象的东西

         2 如果向已有的对象发出一条请求就可以去带一个参数,那么你就应该激活重构手法Replace parameter with method。

         3 可以使用preserve whole object将来自同一个对象的一堆数据收集起来,并以该对象替换它们。如果对象缺乏合理归属,可以使用Introduce Parameter Object为它们制造一个“参数对象”。

(5)发散式变化 (Divergent change)

         1 针对某一外界变化所有的相应修改,都只应该发生在单一类中。找出某种原因产生的变化,运用extract class将之提炼到另外一个类中。

(6)散弹式修改 ( Shotgun Surgery)

        1 如果遇到某种变化,需要在许多不同的类中做出许多小的修改。可以使用Move method和Move field将所有需要修改的代码放进同一个类中。

(7)依恋情结 ( Feature Envy)

        1 函数对某个类的兴趣高于对自己所在的类的兴趣,例如函数使用了另外对象中的很多函数。先使用 extract method将这些部分提炼到独立函数中,再使用

(8)数据泥团 (Data Clumps)

       1 两个类中的相同字段、许多函数签名中相同的参数。这些忠实绑定在一起出现的数据应该拥有自己的对象。首先找出这些数据以字段出现的地方,运用extract class将他们提炼到一个独立的对象中。然后注意力转移到函数签名上,运用introduce parameter object或preserve whole object减肥。

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

       结构类型允许你将数据组织成有意义的形式;基本类型则是构成结构类型的积木块。结构总是带来一定的额外开销,他们可能代表着数据库中的表,如果只为一两件事而创建结构类型也可能显得太麻烦。

(10)switch惊悚现身(switch statements)

     先用extract method将switch语句提炼到一个独立的函数中,再以move method将它搬移到需要多态性的那个类里。此时决定是否使用replace thpy code with subclasses或replace type code with state/strategy,一旦完成以后就可以运用replace conditional with polymorphism了。

(11)平行继承体系(Parallel inheritance Hierarchies)

    如果每增加一个子类,必须为另一个类相应增加子类。 让一个继承体系实例引用另一个继承体系的实例。也可继续使用move method和move field。

(12)冗赘类(lazy class)

    如果某些子类没有足够的工作,试试collapse herarchy,对于几乎没有用的组件,应该以inline class对付。

(13)夸夸其谈未来性(Speculative generality)

      如果运用collapse hierarchy,不必要委托就可以运用inline class除掉。如果函数的某些参数并未用上,可以实施remove parameter。如果函数名称有多余抽象意味,应该试试remove method。

     如果函数或者类的唯一用户是测试用例,也同上。

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

    某个实例变量仅为某种特定情况而设,通常认为对象在所有时候都需要它所在的变量。使用extract class或者使用introduce Null object在变量不合法的情况下创建一个null对象。

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

    如果一个对象请求另外一个对象,然后再向后者请求另一个对象。。。。一旦对象关系发生变化,客户端就需要做出相应的修改。

    使用hide delegate,可以在消息链不同位置进行这种重构手法,可以重构消息链上任意一个对象,但这么做往往会把一系列对象intermediate object变成middle man。更好的选择是先观察消息链最终获得到得对象时干什么的,看看能否以extract method把使用该对象的代码提炼到一个独立的函数中,再运用move method把这个消息推入消息链。

(16)中间人(Middle man)

    如果一个类接口有一半函数都委托给其他的类,这样就是过度运用。这时应该使用remove middle man,直接和真正负责的对象打交道。如果不敢试试的函数只有少数几个,可以运用inlinemethod将它们放到调用端。如果这些middle man还有其他的行为,可以运用replace delegation with inheritance 把它们变成负责对象的子类。

(17)狎昵关系(Inappropriate INtimacy)

   如果两个类探究彼此private成分,应该拆散。采用move method和move field帮助划清界限,也可以看看能否运用change bidrectional association to unidirectional让其中一个类对另一个斩断。也可以使用hide delegate让另一个类来为它们传递。如果子类对超类的了解重视超过后者的愿望,可以使用repace inheritance with delegation让它离开。

(18)异曲同工的类(Alternative classes with different interfaces)

   Rename method根据用途重新命名,和反复运用move method将某些行为移入类中。如果重复移入代码,也可extract superclass。

(19)不完美的库类(incomplete Library class)

    如果你只想修改库类的一两个函数,可以运用introduce foreign method,如果想添加一大堆额外的行为,就得运用introduce local exetnsion。

(20)纯稚的数据类(data class)

   它拥有一些字段,以及用于访问这些字段的函数,除此之外无它。他们可能被其他类访问public,使用encapuslate collection把他们封装起来。对于那些不该被其他类修改的字段,请运用remove setting method修改。

    然后找出这些取值/设置函数被其他类运用的地点尝试以Move method将这些调用行为搬移到data class中来。然后使用hidden method将这些取值/设置函数隐藏起来。

(21)被拒绝的馈赠(Refused bequest)

    如果子类弗雷德全部函数和数据,意味着体系设计错误。尝试为这个子类新建一个兄弟,再运用push down method和push down field 把所有用不到的函数下推给兄弟。

    如果子类服用了超累的行为,却又不愿意支持超类的接口,refused bequest就会很明显。如果拒绝实现超累的接口,并不以为然。即使你不愿意集成接口,也不要胡乱修改集成体系,应该运用 replace inheritance with delegation来达到修改的目的。

(22)过多的注释(comments)

    comment可以帮助找到本章中线前提道德各种坏味道,如果找到后就会发现注释已经多余了。如果需要注释来说明一块代码做了什么,试试extract method;如果函数已经提炼出来,但是还是需要解释行为,试试rename method;如果需要注释来说明某些系统的需求规格。试试introduce assertion。