Martin Fowler在Refactoring: Improving the Design of Existing Code(中译名:《重构——改善既有代码的设计》)一书中与Kent Beck一起总结了22种代码坏味(Bad Smells in Code),因为Sunny这段时间正在做一些与代码味道自动识别与自动重构有关的研究工作,对这些内容进行了重新的深入理解与分析。后续将在博客中转载和原创一些相关的文章,希望对广大从事软件开发的朋友们能够带来些许帮助。你在编程过程中面临哪些代码味道?哪些代码味道你觉得最应该消除?对于消除这些代码味道你有何意见和建议?欢迎大家与我一起交流讨论。
注:本文中,代码坏味道的中文名称源于侯捷和熊节的中译本《重构——改善既有代码的设计》。
类内味道
1、Measured Smells(可度量的味道)
(1) Long Method(过长方法)
A method is too long.(方法太长。)
(2) Large Class(过大类)
A class is trying to do too much, it often shows up as too many instance variables.(一个类试图做太多的事情,通常会出现太多的实例变量。)
(3) Long Parameter List(过长参数列)
A method needs passing too many parameters.(一个方法需要传递太多的参数。)
(4) Comments(过多的注释)
Do not write comments when it is unnecessary. When you feel the need to write a comment, first try to refactor the code so that any comment becomes superfluous.(在非必要的情况下不要写注释。当你觉得需要去写一段注释时,你首先应该尝试去重构代码,这将使任何注释都变得是多余的。)
2、Unneccessary Complexity(不必要的复杂性)
(5) Speculative Generality(夸夸其谈的未来性)
If a machinery was being used, it would be worth it. But if it is not, it is not. The machinery just gets in the way, so get rid of it.(如果一个装置【一个设计或实现方案】会被用到,那就值得去做;如果用不到,就不值得。用不到的装置会成为拦路石,因此需要将它搬移。)
3、Duplication(重复)
(6) Duplicated Code(重复代码)
Same code structure happens in more than one place.(在一个以上的地方发现相似的代码结构。)
(7) Alternative Classes with Different Interfaces(异曲同工的类)
Classes are doing similar things but with different signatures. (不同的类做相同的事情,却拥有不同的签名,主要是指方法签名不同。)
4、Conditional Logic(条件逻辑)
(8) Switch Statements(Switch惊悚现身)
Switch statements often lead to duplication. Most times you see a switch statement which you should consider as polymorphism.(Switch语句通常会导致代码重复。大多数时候,一看到Switch语句你应该考虑使用多态来替换。)
类间味道
1、Data(数据)
(9) Primitive Obsession(基本类型偏执)
Primitive types are overused in software. Small classes should be used in place of primitive types in some situations.(在软件中,基本类型被过度使用。在某些场合下,应该使用一些小的类来代替这些基本类型。)
(10) Data Class(纯稚的数据类)
These are classes that have fields, getting and setting methods for the fields, and nothing else. Such classes are dumb data holders and are almost certainly being manipulated in far too much detail by other classes.(这些类拥有一些字段【成员变量】,并提供了对应的Getter和Setter方法,除此以外一无所有。这些类只是一些不会说话的数据容器, 而且它们必定会被其他类过分琐细地操作。)
(11) Data Clumps(数据泥团)
Some data items together in lots of places: fields in a couple of classes, parameters in many method signatures.(一些数据项同时出现在多个地方:例如一对类中的值域【成员变量】,多个方法签名中的参数等。)
(12) Temporary Field(令人迷惑的暂时值域)
Sometimes you see an object in which an instance variable is set only in certain circumstances. Such code is difficult to understand, because you expect an object to need all of its variables.(有时候你会看到一个对象的实例变量仅为某些特定的场合而设。这样的代码将导致难以理解,因为你期望一个对象需要它所有的变量。)
2、Inheritance(继承)
(13) Refused Bequest(被拒绝的遗赠)
Subclasses get to inherit the methods and data of their parents, but they just use a few of them.(子类继承父类的方法和数据,但是它们只需要使用其中的一部分。)
(14) Inappropriate Intimacy(狎昵关系)
Sometimes classes become far too intimate and spend too much time delving in each others’ private parts.(有时候,类之间的关系变得非常亲密,并且需要花费大量时间来探究彼此之间的私有成分。)
(15) Lazy Class(冗赘类)
Each class you create costs money to maintain and understand. A class that is not doing enough to pay for itself should be eliminated.(你所创建的每个类都需要花钱去维护和理解。一个类如果不值其身价,它就应该消失。)
3、Responsibility(职责)
(16) Feature Envy(依恋情节)
The whole point of objects is that they are a technique to package data with the processes used on that data. A Feature Envy is a method that seems more interested in a class other than the one it actually is in.(对象的全部要点在于它是一种封装数据以及施加于这些数据的处理过程的技术。依恋情节是指一个方法对别的类的兴趣高过它本身所在的类。)
(17) Message Chains(过度耦合的消息链)
You see message chains when a client asks one object for another object, which the client then asks for yet another object, which the client then asks for yet another object, and so on. Navigating in this way means that the client is coupled to the structure of the navigation. Any change to the intermediate relationships causes the client to have to change.(你看到的消息链是这样的:当一个客户端向一个对象请求另一个对象,然后再向后者请求另一个对象,然后再请求另一个对象,如此反复。这种方式的导航意味着客户端将与整个导航结构紧密耦合在一起。一旦对象之间的联系发生任何改变,将导致客户端也不得不做出相应的修改。)
(18) Middle Man(中间转手人)
You look at a class’s interface and find that half the methods are delegating to this other class. It may mean problems.(当你审查一个类的接口时发现其中有一半的方法都委托给了其他类,这也许就意味着存在问题了。)
4、Accommodating Change(协调变化)
(19) Divergent Change(发散式变化)
Divergent change occurs when one class is commonly changed in different ways for different reasons.(如果某个类经常因为不同的原因在不同的方向上发生变化就会产生发散式变化。也就是说,一个类拥有多个引起它发生变化的原因。)
(20) Shotgun Surgery(霰弹式修改)
Shotgun surgery is similar to divergent change but is the opposite. Every time you make a kind of change, you have to make a lot of little changes to a lot of different classes.(霰弹式修改与发散式变化类似,却又存在相反的一面。每次进行某种修改时,你都必须对多个不同的类进行很多对应的小修改。)
(21) Parallel Inheritance Hierarchies(平行继承体系)
Parallel inheritance hierarchies is really a special case of shotgun surgery. In this case, every time you make a subclass of one class, you also have to make a subclass of another. You can recognize this smell because the prefixes of the class names in one hierarchy are the same as the prefixes in another hierarchy.(平行继承体系是霰弹式修改的一个特例。在这种情况下,当你为某个类增加一个子类时,你不得不为另一个类也相应增加一个子类。你也许能够识别到这种味道,因为一个继承体系中类的类名前缀与另一个体系中的类名前缀一样。)
5、Library Classes(库类)
(22) Incomplete Library Class(不完善的程序库类)
Library classes should be used carefully, especially we do not know whether a library is completed.(库类在使用时一定要小心,特别是在我们不知道一个库是否完整时。)
【作者:刘伟 http://blog.csdn.net/lovelion】