读书笔记之《重构》第三章—代码的坏味道

第三章 代码的坏味道
这一章告诉我们,什么样的代码需要去重构,该用什么方法。寻找代码的坏味道,就是从代码中找出特定的结构,这些结构指出重构的可能性。寻找这些结构,需要学会判断,判断一个类里面有多少实例变量算多,多少行代码算长, 我想这个是需要直觉的,这样的直觉应该是来自代码量,以及平时的学习。
作者给出的第一个坏味道是Duplicated Code(重复代码),如果在同一个程序中看到一处以上的相同代码,就应该想办法重构,消灭重复代码。同一个类的两个函数含有相同的表达式,或者两个互为兄弟的子类内含有相同的表达式,避免这种情况,需要使用提炼函数的方法,提炼出来的函数,推入超类。另一种情况,如果代码只是类似,而非相同,仍然要用到提炼函数,讲函数相似部分和差异部分分割开,构成单一的函数。
Long Method(过长函数)。如果我们了解面向对象,一般不会在一个类中写很长的函数。但是有时候仍然会无知或者无意出现这种情况,以后维护这样的代码会比较痛苦,函数应该尽量短小,还有一个关键是要取一个好名字,让阅读的人能通过函数名直观了解这段函数的作用。当一段代码需要用注释来解释的时候,就应该考虑是否可以将其提炼到一个单独的函数中,用这段函数的用途来取名。
Large Class(过大的类)。最好不要利用单个类来做太多的事情,这就会导致类过大,可以运用提炼类,将几个变量提炼到一个新的类中,应选择类内彼此相关的变量放在一起。
Long Parameter List(过长参数列)。不必把所有函数需要的东西通过参数传递给他,太长的参数可能难以理解,比较好的方式是通过对象传入进来。
Divergent Change(发散式变化)。软件应该很容易被修改,如果系统在应对外来变化时不易修改,我们就应该考虑重构它,如果某个类经常因为不同的原因在不同的方向上发生变化,这时候将对象一分为二也许更好,这样,出现变化我们只需修改其中某一个。
Shotgun Surgery(霰弹式修改)。与发散式变化相反,当程序发生变化需要修改时,发现需要对很多类作出小修改,这时候尝试将所有需要修改的代码放进同一个类,也可以防止修改有遗漏,方便管理。
Feature Envy(依恋情结)。产生这个坏味道的原因是函数为了计算某个值,从别的对象调用函数,也就是函数对某个类的兴趣高于自己所处类的兴趣。方法是使用搬移函数的方法将这个函数移走,或者是先提炼之后在搬移,这个要看具体的情况,判断哪个类拥有最多被此函数使用的数据,然后把这个函数和那些数据放在一起。
Data Clumps(数据泥团)。常常可以在很多地方看到相同的三四项数据:两个类中相同的字段、许多函数签名中相同的参数。这是问题所在,方法是:先找出这些数据以字段形式出现的地方,运用提炼类方法将其提炼到独立的对象中。对于数据泥团的评判方法:删掉众多数据中的一项,其他数据没有因此失去意义,如果失去了意义,就是明确的信号,需要为它们产生一个新对象。
Primitive Obsession(基本类型偏执)。结构类型将数组组成有意义的形式,但是会有额外的开销,如果只为了做一两件事情创建结构类型显得麻烦。对象的极大价值在于它模糊了基本数据和体积较大的类之间的界限。但是对象技术的新手通常不愿意在校任务上运用小对象。方法:可以使用以对象取代数据值的方法(Replace Data Value Object(175)),将原本单独存在的数据值替换为对象。
Switch Statements(switch惊悚现身)。面向对象的程序要少用Switch,本质上讲就是避免重复。解决方法是使用多态,将switch语句提炼到一个函数中,搬移到需要多态性的类,但是如果只在一个类里面好似用switch,则不必大动干戈,显得杀鸡用牛刀了。
Parallel Inheritance Hierarchies(平行继承体系)。其实是霰弹式修改的特殊情况,这种情况下,为某个类增加一个子类,也必须为另一个类相应增加一个子类,这就是坏味道。方法是让一个继承体系的实例引用另一个继承体系的实例。
Lazy Class(冗赘类)。所谓冗赘类就是这个类的作用不值得单独作为一个类,不及其本身的价值,这样的类应该消失。如果某些子类没有做足够的工作,可以用折叠继承体系。对于没用的组件,用Inline Class(将类内联化)。
Speculative Generality(夸夸其谈未来性)。考虑得太远,企图用各式各样钩子和特殊情况来处理一些非必要的事情,没找到重点,结果往往造成系统更难维护和理解。应对方法:如果是抽象类没有太大作用,运用折叠继承体系处理。不必要的委托可以使用将类内联化处理。
Temporay Field(令人迷惑的暂时字段)。表现为:其内某个实例变量仅为某种特殊情况而设,这样的代码会让人不易理解,因为你通常会认为对象在所有时候都需要它的所有变量。
方法:使用提炼类的方法提炼一个类,把变量相关的代码都放在这里,然后还可以引入null对象,创建null对象,避免写条件对象来判断它。
Message Chains(过度耦合的消息链)。表现为:用户向一个对象请求另一个对象,然后再向后者请求另一个对象,再请求另一个对象,这就是消息链。一旦对象间的关系发生任何的变化,客户端就必须做出相应的修改。解决方法:应该使用隐藏委托关系(Hide Delegata)类解决,先观察消息链最终得到的对象是用来干什么的,再使用相应的方法。
Middle Man(中间人)。表现为:你也许会看到某个类接口有一半的函数都委托给其他的类,这样就是过度运用。解决方法:应该使用Remove Middle Man方法,直接和正真负责的对象打交道,而不是中间人。
Inappropriate Intimacy(狎昵关系)。表现为:两个类过度亲密,花费太多的时间去探索彼此的private部分。解决方法:过于狎昵的类必须拆散,可以使用Move Method和Move Field帮它们划清界限。
Alterantive Class with Different Interfaces(异曲同工的类)。两个函数做着同样的事情,却有着不同的签名。方法:运用Rename Method(函数改名)根据其用途重新命名。
Incomplete Library Class(不完美的类库)。复用常被认为是对象的终极目的,但是也常被高估,因为大多数对象够用就好。问题:麻烦的是类库往往构造得不够好,而且往往不可能让我们修改其中的类使它完成我们希望完成的工作。方法:如果只想修改类库中的一两个函数,可以使用Introduce Foreign Method解决。如果想要添加一大堆额外行为,就要运用Introduce Local Extension解决。
Data Class(纯稚的数据类)。表现为:拥有一些字段,以及用于访问这些字段的函数,除此之外一无长物,这样的类知识一种不会说话的数据容器。方法:运用封装字段方法将其封装起来,如果这些类内含容器类的字段,检查是否得到了封装,如果没有,就封装起来。不该被修改的字段,用移除设值函数解决。
Refused Bequest(被拒绝的遗赠)。子类应该继承超类的函数和数据。表现的味道:如果子类复用超类的行为(实现),却又不愿意之处超类的接口。方法:运用Replace Inheritance with Delegation来解决。
Comments(过多的注释)。注释往往是香味,但是在使用的时候如果使用不当,使用过量了,味道也很呛人。Comments很多时候可以帮我们找到之前提到的坏味道然后来解决它。解决之后,这些注释就成为多余的了,因为代码很清楚,不需要注释了,其本身就成为了坏味道,需要做的就是移除之。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值