编写代码22宗罪
1 Duplicated Code重复代码
1)同一个类的2个函数含有相同的表达式,这时可以采用Extract Method(提炼函数)提炼出重复的代码,然后让这2个地点都调用被提炼出来的那段代码。
2)两个互为兄弟的子类内含相同表达式,只需对2个类都是用Extract Method(提炼函数),然后对被提炼出来的函数是用Pull Up Method (方法上移) ,将它推入超类。如果代码之间只是类似, 并非完全相同,那么就得运用Extract Method(提炼函数 将相似部分和差异部分隔开,构成单独一个的函数。然后你可能发现可以运用Form Template Method (塑造模板函数)获得一个 Template Method设计模式。如果有些函数以不同的算法做相同的事,你可以选择其中较清晰地一个,并是用 Substitute Algorithm (替换算法)将其他函数的算法替换掉。
如果2个毫不相关的类出现 重复代码,你应该考虑对其中一个运用 Extract Class (提炼类),将重复代码提炼到一个独立类中,然后在另一个类内使用这个新类。但是,重复代码所在的函数可能只应该属于某个类,另一个类只能调用它,抑或这个函数可能属于第三个类,而另2个类应该引用这第三个类。你必须决定这个函数放在哪儿最合适,并确保它被安置后就不会再在其他任何地方出现。
2 Long Method 过长函数
如果已经这么做了,仍然有太多的临时变量和参数,就应该使用 Replace Method with Method Object (以函数对象取代函数)。如何确定提炼哪一段代码呢?一个很好的技巧是:寻找注释。它们通常指出代码用途和实现手法之间的语义距离。如果代码前方有一行注释,就是在提醒你:可以将这段代码替换成一个函数,而且可以在注释的基础上给这个函数命名。就算只有一行代码,如果它需要以注释来说明,那也值得将它提炼到独立函数中。
3 Large Class 过大的类
运用Extract Class (提炼类)将几个变量一起提炼到新类里。提炼类时应该选择类内彼此相关的变量,将它们放在一起。通常类内的数个变量有相同的前缀或字尾,这就意味有机会把它们提炼到某个组件内。如果这个组件适合作为一个子类,就可以运用 Extract Subclass (提炼子类)。
有时类并非在所有时刻都使用所有实例变量。可多次使用Extract Class (提炼类)和Extract Subclass (提炼子类)
一个类如果拥有太多代码,往往也适合使用Extract Class (提炼类)和Extract Subclass (提炼子类)。技巧:先确定客户端如何使用它们,然后运用 Extract Interface(提炼接口) 为每个使用方式提炼出一个接口。可帮助你看清楚如何分解这个类。
如果是个GUI类,可能需要把数据和行为移到一个独立的领域对象去。可能需要2边各保留一些重复数据,并保持2边同步。Duplicate Observed Data (复制"被监视数据")告诉你该这么做。
4. Long Parameter List 过长参数列
重要的例外:如果你明显不想造成"被调用对象"与"较大对象"间的某种依赖关系。这时候将数据从对象中拆解出来单独作为参数,也很合情理。但是请注意其所引发的代价。如果参数列太长或变化太频繁,就需要重新考虑自己的依赖结构了。
5. Divergent Change 发散式变化(相对聚焦式)
6. Shotgun Surgery 霰弹式修改
7. Feature Envy 依恋情节
8. Data Clumps 数据泥团
一个好的评判方法是:删除众多数据中的一项。这么做,其他数据有没有因而失去意义?如果它们不再有意义,这就是个明确信号:你应该为它们产生一个新对象。
9. Primitive Obsession 基本类型偏执
10. Switch Statement (switch 惊悚现身)
11. Parallel Inheritance Hierarchies 平衡继承体系
12. Lazy Class(冗赘类)
如果一个类的所得不值其身价,它就应该消失: 即如果某些子类没有足够的工作,试试Collapse Hierarch (折叠继承体系)。对应几乎没用的组件,应该以Inline Class (将类内联化)对付它们。13. Speculative Generality(夸夸其谈未来性)
14. Temporary Field(令人迷惑的暂时值域)
15. Message Chains(过度耦合的消息链)
16. Middle Man(中间转手人)
17. Inappropriate Intimacy(狎昵关系)
18. Alternative Classes with Different Interfaces(异曲同工的类)
19. Incomplete Library Class(不完善的库类)
复用常被视为对象的终极目的。不过复用的意义常被高估:大多数对象只要够用就好。但是无可否认,许多编程技术都建立在程序库的基础上。库类的构筑者没用未卜先知的能力,不能因此责怪他们。麻烦的是库往往构造的不够好,而且往往不可能让我们修改其中的类使它们完成我们希望完成的工作。这是否意味着那些经过实践检验的技术,如今都派不上用场了?幸好我们有2个专门应付这种情况的工具。如果你只想修改类库的一两个函数,可以运用Introduce Foreign Method (引入外加函数);如果想要添加一大堆额外行为,就得运用 Introduce Local Extension (引入本地扩展) 。
20. Data Class(纯稚的数据类)
21 Refused Bequest(被拒绝的遗赠)
22 Comments(过多的注释)
我们之所以在这里提到注释,是因为人们常把它当做除臭剂来使用。常常会有这样的情况:你看到一段代码有着长长的注释,然后发现,这些注释之所以存在是因为代码很糟糕。注释可以带我们找到代码中的坏味道。找到坏味道后,我们首先应该以各种重构手法把坏味道去除。完成之后我们常常会发现:注释已经变得多余了,因为代码已经清楚说明了一切。如果你需要注释来解释一块代码做了说明,试试 Extract Method (提炼函数);如果函数已经提炼出来,但还是需要注释来解释其行为,试试 Rename Method (函数改名);如果你需要注释说明某些系统的需求规格,试试 Introduce Assertion (引入断言)。
本文转载自:真实的归宿
本文来自互联网用户投稿,文章观点仅代表作者本人,不代表本站立场,不承担相关法律责任。如若转载,请注明出处。 如若内容造成侵权/违法违规/事实不符,请点击【内容举报】进行投诉反馈!
