重构笔记——代码的坏味道(下)

来源:互联网 发布:家谱制作软件免费版 编辑:程序博客网 时间:2024/05/11 20:58

本文是在学习中的总结,欢迎转载但请注明出处:http://blog.csdn.net/pistolove/article/details/42083495


      在重构笔记——代码的坏味道(上)中介绍了22种坏味道中的11种,本文将介绍其余的11种坏味道。之所以将其分为两篇文章介绍,是因为一篇文章介绍22种方法显得篇幅太长,担心读者难以坚持看完。(PS:在对这些"代码的坏味道“了解和熟悉后,我们就要开始有针对性地进行重构了,但是在进行重构之前,我们似乎还缺少点什么!对了,我们还缺少测试环境!在开发的过程中,大多数程序员可能会忽视构筑测试体系,但是殊不知编写优良的测试程序,可以极大地提高程序员的编程速度,并确保程序相对“稳定“和”牢靠”。在下一篇文章中将会介绍:构筑测试体系,提高编程速度)。

      其余的11种坏味道如下所示。(如果你想坚持并学习重构,希望你能够有耐心地看完本文)


(12)冗赘类

      你所创建的每一个类,都得有人去理解它、维护它,这些工作都是需要花钱的。如果一个类的所得并不值其身价,他就应该消失。项目中经常会出现这样的情况:某个类原本对得起自己的价值,但重构使它身形缩水,不再做那么多工作;或开发者事先规划了某些变化,并添加一个类来应付这些变化,但变化实际没有发生。

      不管是哪种原因,都应该让这个类庄严赴义吧。如果某些子类并没有做足够的工作,我们可以尝试“折叠继承体系”,将超类和子类合为一体,那样就会减少维护时间。对于那些几乎没用的组件,就应该将这个类的所有特性搬移到另一个类中,然后移除原类。


(13)夸夸其谈未来性

      我们经常会说:“我想总有一天需要做这事”,并因而企图以各样的钩子和特殊情况来处理一些非必要的事情。一旦这样,坏味道就浮现出来了。夸夸其谈未来的结果往往会造成系统更加难以理解和维护。如果所有的装置都被用到了,那就值得那么做;如果用不到,就不值得。用不上的装置只会阻挡你的路,给你添乱,那就搬开它吧。

      如果某个抽象类其实没有太大作用,可以将超类和子类合为一体。将不必要的委托转移到另一个类中,并消除原先的类。如果函数的某些参数未被用上,那么就将参数移走。如果函数名称带有多余的抽象意味,就应该对它重命名,让它现实一些。


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

      有时候你会发现:类中的某个实例变量仅为某种特定情况而设。这样的代码让人难以理解,因为你通常认为对象在所有时候都需要它的所有变量。当变量在未被使用的情况下去猜测其当初设置的目的,会让你发疯的。

      可以使用提炼新类为这个可怜的孤儿创造一个家,然后把所有和这个变量相关的代码都放进这个新家。

      也许还可以使用“将Null值替换为Null对象”在“变量不合法”的情况下创建一个Null对象,从而避免写出条件式代码。

      

(15)过度耦合的消息链

      如果你看到用户向一个对象请求另一个对象,然后再向后者请求另一个对象,然后再请求另一个对象.....这就是消息链。这种方式意味着客户代码将与某些功能函数中的导航结构紧密耦合。一旦对象间的关系发生任何变化,客户端就不得不做出相应修改。

      这时候我们可以隐藏“委托关系”,并在服务类上建立客户所需要的所有函数。你可以在消息链的不同位置进行这种重构手法。理论上是可以重构消息链上的任何一个对象,但是这样做往往会把一系列对象都变成“中间人”。通常更好的选择是:先观察消息链最终得到的对象是用来干什么的,再看看能否通过抽取方法把使用该对象的代码提炼到一个独立函数中,然后再将这个函数推入消息链。


(16)中间人

      我们都知道对象的基本特征之一就是封装——对外部世界隐藏其内部细节。封装往往伴随着委托。比如你对Boss说是否有时间参加一个会议,他把这个消息“委托”给他的记事本,然后才能回答你。但是,你没有必要知道Boss到底使用传统记事本或电子记事本亦或秘书来记录自己的约会。

      人们可能会过度使用委托。你也许会看到某个类接口中有一半的函数都委托给其它类,这样就是过度委托。这时候就应该移除中间人,直接和真正的负责人打交道。如果这样“不干实事”的函数只有少数几个,可以将它们放进调用端。如果中间人还有其它行为,可以把它变成实责对象的子类,这样你既可以扩展原对象的行为,又不必负担那么多的委托动作。


(17)狎昵关系

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

      也许就像古代的恋人一样,过分狎昵的类必须拆散。可以通过“移动方法”和“移动字段”帮它们划清界限,从而减少狎昵行径。如果两个类实在是情投意合,可以把两者共同点提炼到一个安全地点,让它们坦荡地使用这个新类。或者通过隐藏“委托关系”让另一个类来为它们传递相思情。


(18)异曲同工的类

      如果两个函数做同一件事,却有着不同的签名,可以根据它们的用途重新命名。

      但这往往不够,可以反复将某些行为移入类中,直到两者的协议一致为止。


(19)不完美的库类

     复用常被视为对象的终极目的。不过我们认为复用的意义经常被高估——大多数对象只要够用就好。但是无可否认,许多编程技术都建立在程序库的基础上。库类构建者没有未卜先知的能力,我们不能因此责怪它们。

      幸好我们有两个专门应付这种情况的工具。如果你只想修改库类的一两个函数,可以使用“引入外加参数”来进行修改。如果想要添加一大堆额外行为,就得运用“引入本地扩展(建立一个新类,使它包含这些额外函数。让这个扩展品成为源类的子类或包装类)”来进行修改。


(20)纯稚的数据类

      纯稚的数据类是指:它们拥有一些字段,以及用于访问(读写)这些字段的函数,除此之外一无长物。这样的类只是一种不会说话的数据容器,它们几乎一定被其它类过分细琐地操控着。

      这些类早期可能拥有public字段,果真如此就应该在别人注意到它们之前将它们封装起来。如果这些类内含容器类的字段,就应该检查它们是不是得到了恰当的封装;如果没有,就把它们封装起来。对于那些不该被其它类修改的字段,就应该去掉该字段的所有设值函数。


(21)被拒绝的遗赠

      子类应该继承超类的函数和数据。但是如果它们不想或者不需要继承,又该怎么办呢?它们得到了所有的礼物,但却只从中挑选几样来玩!

      这可能意味着继承体系设计错误。你需要为这个子类新建一个兄弟类,再把所有用不到的函数下推给那个兄弟。这样一来,超类就只持有所有子类共享的东西。你常常会听到这样的建议:所有超类都应该是抽象的。


(22)过多的注释

      不要担心,并不是说不应该写注释。从嗅觉上说,注释不是一种坏味道,事实上它还是一种香味呢。常常还有这样的情况:你看到一段代码有着长长的注释,然后发现,这些注释之所以存在乃是因为代码很糟糕。这种情况出现次数多的实在令人吃惊。

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

      如果你需要注释来解释一块代码做了什么,试试将该代码抽取为一个单独的函数;如果函数已经被提炼出来,但还是需要注释来解释其行为,试着对其重新命名。当你感觉需要撰写注释时,请先尝试重构,试着让所有注释都变得多余。


      “代码的坏味道”相关的两篇文章主要是对常见的22种坏味道的了解和熟悉,以促使我们在开发过程中,能够经常性地分析和思考程序,寻找已经散发出坏味道的地方并对其进行适当重构,使得代码更加“漂亮”。在后续的文章中,会比较细致地介绍由坏味道而引发的各种重构手法。每种手法会对应一篇文章,每一篇文章中会介绍坏味道的去除方法,并会列举一些简单的例子加以阐述,使得你能够更加清晰地学习和理解。


      希望本文对你有所帮助。有问题可以讨论、沟通。