『重构--改善既有代码的设计』读书笔记----代码坏味道【4】

    转眼之间已经出到坏味道【4】了,有朋友跟我说很喜欢前面出的坏味道系列,感觉很有用,因为重构本身就是可以立即进行。他们不像设计模式那样需要有一个准备和改变的过程,重构本身和开发就是可以做到同步的。作者也提到,设计模式是重构的目标。重构就是一个将代码改优雅让你后期添加行为或者重新理解更加方便的过程。所以你应该将重构放到工作的各个位置,而不是当设计模式一样,当成工具书去查看。下面进入正题:

    【13】Speculative Generality(夸夸其谈未来性)

    Brain Foote介绍了这个坏味道。其实我的理解就是4个字过度设计,很多时候当我们要着手进行开发的时候都会去考虑未来性,这里需不需要一个抽象类或者这个函数需要不需要设置为虚,这里要不要放一个钩子来为以后使用。总之你会使用各种各样的防卫手段来过度开发,想减少以后程序本身应对变化的改变。但你要知道,需求永远是下一秒,你想都想不到。这种过度开发的设计往往让系统变得难以理解和维护。当然,如果你确定这些以后都用的到,那你大胆放心去做。如果你不能确定用不用的到,那就不值得,所以,删掉它吧。

    如果你的某个抽象类没有太多实际的作用,那么可以运用Collapse Hierarchy来打破这层继承关系。如果类和类之间的委托你觉得没有必要,你可以用Inline Class来将类内联。如果函数的参数有部分没有用到,请运用Remove Parameter把参数删掉。如果你本身函数名称在起名字的时候就带有抽象含义,那么你可以运用Rename Method把他的语义层含义表达的更具体点。如果你发现只有测试用例用到了这个函数或者类,除非他们是用来帮助测试用例检查正当功能,不然,你就应该把测试用类和它们一起删掉。

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

    有时候你会看到某个类中的某些变量并不被类时时刻刻使用,只有当某个具体算法或者具体函数的特殊情况下才会去用到这个变量。往往这种不被一直使用的变量会让代码阅读者产生疑惑,因为通常对象应该在所有时候都需要它的所有变量。我们很难在变量未被使用的情况下,去猜测它设置的目的。这个时候你需要用Extract Class将这个变量和和这个变量相关的函数都移到这个新类当中去。如果你发现会有判断变量合不合法的情况,你可能需要运用Introduce Null Object来进行重构从而避免写出条件式代码。

    如果类中有一个复杂的算法,实现者在实现这个算法的时候不希望这个算法的参数列表过于冗长,所以他会把这些特殊变量都放到类的字段当中去从而产生坏味道。这个时候你应该运用Extract Class将这些变量和相关函数移到一个新类中,这个类就是我们一直提到的“函数对象”。

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

    有些时候我们在调用某个函数的时候往往会形成A->B->C->D.test(),这个时候如果你在A端,你就产生了Message Chains的坏味道。这种状态使的你客户代码在A中变成getB()->getC()->getD()->test(),这会使得客户代码在以后这些类关系发生变化的时候变得极易修改与相当不稳定。这个时候你应该运用Hide Delegate来打破这消息链,理论上你可以重构消息链上的任一对象。但这样做往往会让这些小对象都变成Middle Man(中间人),通常更好的做法是:查看消息链最终对象是用来干什么的,看看是否能用Extract Method把他提炼到一个独立的函数中去,再运用Move Method把这个函数推入消息链,然后查看是否有多个客户访问某个对象以此来航行余下部分的,然后增加函数来做这件事。当然,并不是说消息链就是坏东西,任何事情都有两面性,我们需要自己做出判断。

    【16】Middle Man(中间人)

    对象的基本特征之一就是封装,就是对外部隐藏其实现的细节。比如我们问服务员,这道菜做好没,我们只需要去询问服务员,服务员具体去问厨师还是去问别的伙计这一点我们不用在意。但是很多时候我们可能会过度委托,有些时候某个类的接口有一半的函数都委托给其他类。这样就是过度使用Middle Man,这个时候你应该使用Remove Middle Man来进行重构,如果这种委托函数只有少数几个,你可以简简单单用Inline Method来处理原来函数。如果Middle Man除了委托还有其他行为,你可以运用Replace Delegation with Inheritance把它变成调用类的子类,这样你可以少写委托动作的同时,又可以扩展原对象的行为。

    【17】Inappropriate Intimacy(狎昵关系)

    在面向对象的时间里,两个类之间不能出现“情人”关系。也就是彼此的private部分一直互相去探究去查看,要记住在对象时间里,互相依赖是噩梦。你可以运用Move Mothed和Move Field帮他们划清界限。你也可以看看是否可以用Change Bidirectional Association to Uniderctional让其中一个类斩断对另一个类的情丝。如果这两个类实在情投意合,你可以尝试使用Extract Class把两者共同点提炼到一个独立类中,然后让这两个类去访问他,从而改变从双向依赖A->B,B->A变成A->C,B->C。或者你也可以尝试用Hide Delegate让另一个类来为他们传递相思情。

    很多时候,委托要比继承来的实用。因为后者往往造成过度亲密过度依赖。如果你觉得可以让这个类独立生活,你可以使用Replace Inheritance widh Delegation来让他离开继承体系。

posted @ 2014-12-01 10:42  Ricky.K  阅读(1126)  评论(0编辑  收藏  举报