ivaneeo's blog

自由的力量,自由的生活。

  BlogJava :: 首页 :: 联系 :: 聚合  :: 管理
  669 Posts :: 0 Stories :: 64 Comments :: 0 Trackbacks

#

如果两个函数做同一件事,却有着不同的签名式(signature),请运用Rename Method(273)根据它们的用途重新命名。但往往不够,请反复运用Move Method(142)将某些行为移入classes,直到两者的协议(protocols)一致为止。如果你必须重复而赘余地移入代码才能完成这些,或许可运用Extract Superclass(336)为自己赎点罪。
posted @ 2005-08-19 16:44 ivaneeo 阅读(248) | 评论 (0)编辑 收藏

有时你会看到两个classes过于亲密,花费太多时间去探究彼此的private成分。如果这发生在两个[人]之间,我们不必做卫道之士;但对于classes,我们希望它们严守清规。

就像古代恋人一样,过分狎昵的classes必须拆散。你可以采用Move Method(142)和Move Field(146)
帮它们划清界线,从而减少狎昵行经。你可以看看是否运用Change Bidirectional Association to Unidirectional(200)让其中一个class对另一个斩断情丝。如果两个classes实在是情投意合,可以运用Extract Class(149)把两者共同点提炼到一个安全地点,让它们坦荡地使用这个新class。或者也可以尝试运用Hide Delegate(157)让另一个class来为它们传递相思情。

继承(inheritance)往往造成过度亲密,因为subclass对superclass的了解总是超过superclass的主管愿望。如果你觉得该让这个孩子独自生活了,请运用Replace Inheritance with Delegation(352)让它离开继承体系。
posted @ 2005-08-19 16:28 ivaneeo 阅读(513) | 评论 (0)编辑 收藏

对象的基本特性之一就是封装(encapsulation)-对外部世界隐藏其内部细节。封装往往伴随delegation(委托)。比如说你问主管是否 有时间参加一个会议,他就把这个消息委托给他的记事薄,然后才能回答你。很好,你没必要知道这位主管到底使用传统记事薄或电子记事薄抑或秘书来记录自己的 约会。

但是人们可能过度运用delegation。你也许会看到某个class接口有一半的函数都委托给其他class,这样就是过度运用。这时你应该使用Remove Middle Man(160),直接和实责对象打交道。如果这样[不干实事]的函数只有少数几个,可以运用Inline Method(117)把它们“inlining”,放进调用端。如果这些Middle Man还有其他行为,你可以运用Replace Delegation with Inheritance(335)把它变成实责对象的subclass,这样你既可以扩展原对象的行为,又不必负担那么多的委托动作。
posted @ 2005-08-19 15:59 ivaneeo 阅读(282) | 评论 (0)编辑 收藏

如果你看到用户向一个对象索求(request)另一个对象,然后再向后者索求另一个对象,然后再索求另一个对象。。。。。。这就是Message Chain。实际代码中你看到的可能是一长串getThis()或一长串临时变量。采取这种方式,意味客户将与查找过程中的航行结构(structure of navigation)紧密耦合。一旦对象间的关系发生任何变化,客户端就不得不作出相应修改。

这时候你应该使用Hide Delegate(157)。你可以在Message Chain的不同位置进行这种重构手法。理论上你可以重构Message Chain上的任何一个对象,但这么做往往会把所有中介对象(intermediate object)都变成Middle Man.通常更好的选择是:先观察Message Chain最终得到的对象是用来干什么的,看看能否以Extract Method(110)把使用该对象的代码提炼到一个独立函数中,再运用Move Method(142)把这个函数推入Message Chain。如果这条链上的某个对象有多位客户打算航行此航线的剩余部分,就加一个函数来做这件事。
posted @ 2005-08-19 15:36 ivaneeo 阅读(725) | 评论 (0)编辑 收藏

有时你会看到这样的对象:其内某个instance变量仅为某种特定情势而设。这样的代码让人不易理解,因为你通常认为对象在所有时候都需要它的所有变量。在变量未被使用的情况下猜测当初其设置目的,会让你发疯。

请使用Extract Class(149)给这个可怜的孤儿创造一个家,然后把所有和这个变量相关的代码都放进这个新家。也许你还可以使用Introduce Null Object(260)在[变量不合法]的情况下创建一个null对象,从而避免写出[条件式代码]。

如果class中有一个复杂算法,需要好几个变量,往往就可能导致坏味道Temporary Field的出现。由于实现者不希望传递一长串参数(想想为什么),所以他把这些参数都放进值域(fields)中。但是这些值域只在使用该算法时才有效,其他情况下只会让人迷惑。这时候你可以利用Extract Class(149)把这些变量和其相关函数提炼到一个独立class中。提炼后的新对象将时一个method object[Beck](译注:其存在只是为了提供调用函数的途径,class本身并无抽象意味)。
posted @ 2005-08-19 15:24 ivaneeo 阅读(401) | 评论 (0)编辑 收藏

当有人说[噢,我想我们总有一天需要做这事]并因而企图以各式各样得挂钩(hooks)和特殊情况来处理一些非必要的事情,这种坏味道就出现了。那么做的 结果往往造成系统更难理解和维护。如果所有装置都会被用到,那就值得那么做;如果用不到,就不值得。用不上得装置只会挡你得路,所以,把它搬开吧。

如果你的某个abstract class其实没有太大作用,请运用Collapse Hierarchy(334)。非必要之delegation(委托)可运用Inline Class(154)除掉。如果函数的某些参数未被用上,可对它实施Remove Parameter(277)。如果函数名称带有多余的抽象意味,应该对它实施Rename Method(273)让它实现一些。

如果函数或class的唯一用户是test cases(测试用例),这就飘出了坏味道Speculative Generality。如果你发现这样的函数或clss,请把它们连同其test cases都删掉。但如果它们的用途是帮助test cases检测正当功能,当然必须刀下留人。
posted @ 2005-08-19 15:07 ivaneeo 阅读(411) | 评论 (0)编辑 收藏

项目中经常会出现这样的情况:某个class原本对得起自己得身价,但重构使它身形缩水,不再做那么多工作;或开发者事前规划了某些变化,并添加一个 class来应付这些变化,但变化实际上没有发生。不论上述哪一种原因,请让这个class庄严赴义吧。如果某些subclass没有做满足够工作,试试Collapse Hierarchy(344)。对于几乎没用得组件,你应该以Inline Class(154)对付它们。
posted @ 2005-08-19 14:50 ivaneeo 阅读(355) | 评论 (0)编辑 收藏

Parallel Inheritance Hierachies其实是Shotgun Surgery的特殊情况。在这种情况下,每当你为某个class增加一个subclass,必须也为另一个class相应增加一个subclass。如果你发现某个继承体系的class名称前缀和另一个继承体系的class名称前缀完全相同,便是闻到了这种味道。

消除这种重复性的一般策略是:让一个继承体系的实体(instances)指涉(参考、引用、refer to)另一个继承体系的实体(instances)。如果再接再厉运用Move Method(142)和Move Field(146),就可以将指涉端(referring class)的继承体系消弭于无形。
posted @ 2005-08-19 14:39 ivaneeo 阅读(490) | 评论 (0)编辑 收藏

面向对象程序的一个最明显特征就是:少用switch(或case)语句。从本质上说,switch语句的问题在于重复(duplication)。你常 会发现同样的switch语句散布于不同地点。如果要为它添加一个新的case子句,你必须找到所有switch语句并修改它们。面向对象中的多态 (ploymorphism)概念可为此带来优雅的解决办法。

大多数时候,一看到switch语句你就应该考虑以[多态]来替换它。问题是多态该出现在哪儿?switch语句常常根据type code(型别码)进行选择,你要的是[与该type code相关的函数或class]。所以你应该所用Extract Method(110)将switch语句提炼到一个独立函数中,再以Move Method(142)将它搬移到需要多态性的那个class里头。此时你必须决定是否使用Replace Type Code with Subclasses(223)或Replace Type Code with State/Strategy(227)。一旦这样完成继承结构之后,你就可以运用Replace Conditional with Polymorphism(225)了。

如果你只要在单一函数中有些选择事例,而你并不想改动它们,那么[多态]就有点杀鸡用牛刀了。这种情况下Replace Parameter with Explicit Methods(285)是个不错的选择。如果你的选择条件之一是null,可以试试Introduce Null Object(260)。
posted @ 2005-08-19 14:21 ivaneeo 阅读(506) | 评论 (0)编辑 收藏

大多数编程环境都有两种数据:结构型别(record types)允许你将数据组织成有意义的形式;基本型别(primitive types)则是构成结构型别的积木块。结构总是会带来一定的额外开销。它们有点像数据库中的表格,或是那些得不偿失(只为做一两件事而创建,却付出太大 额外开销)的东西。

对象技术的新手通常不原意在小任务上运用小对象-像是结合数值和币别的money class、含一个起始值和一个结束值的range class、电话号码或邮政编码(zip)等等的特殊Strings。你可以运用Replace Data Value with Object(175)将原本单独存在的数据值替换为对象,从而走出传统的洞窟,进入炙手可热的对象世界。如果欲替换之数据值是type code(型别码),而它并不影响行为,你可以运用Replace Type Code with Class(218)将它换掉。如果你有相依于此type code的条件式,可运用Replace Type Code with Subclass(227)或Replace Type Code with State/Strategy(227)加以处理。

如果你有一组应该总是被放在一起的值域(fields),可运用Extract Class(149)。如果你在参数列中看到基本型数据,不妨试试Introduce Parameter Object(295)。如果你发现自己正从array中挑选数据,可运用Replace Array with Object(186)。
posted @ 2005-08-19 11:16 ivaneeo 阅读(551) | 评论 (0)编辑 收藏

仅列出标题
共67页: First 上一页 50 51 52 53 54 55 56 57 58 下一页 Last