转发:22 种代码坏味道(code smell)

[

Code Smell中文译名一般为“代码异味”,或“代码味道”,它是提示代码中某个地方存在错误的一个暗示,开发人员可以通过这种smell(异味)在代码中追捕到问题。

在计算机编程社区中,code smell代表了任何标志着事物变坏的征兆。它常常标志代码应该被refactored或者全部的设计都应该被reviewed。这个短语出现在 WardsWiki上,它是被Kent Beck杜撰出来的。在refactoring兴起之后,这个短语的使用率骤增。

判断是否存在code smell经常是主观判断,并且随着语言、开发者、开发理论的不同而存在差异。

经验丰富和知识渊博的开发人员通过对优秀设计有一种“感觉”,他们已经达到一种称之为“无意识能力 (UnconsciousCompetence)”的状态。也就是说,他们无需思考,只要通过查看代码或一段设计就可以立马对这个项目的代码质量有一种 “感觉”,能够对代码设计的优劣有一个大致的判断。

但大家需要注意,code smell只是一种“暗示”,而非一种“确定”。将某些事物称之为“code smell”并未是一种攻击,它只是一种提示:开发人员需要对项目设计进行更进一步的查看。因此,code smell更多是“直觉的,本能的”。

]

1.Duplicated Code(重复的代码)

坏味道的首当其冲是重复的代码Duplicated Code。假设你在一个以上的地点看到同样的程序结构,那么当可肯定:设法将它们合而为一,程序会变得更好。最单纯的Duplicated Code就是[同一个class内的两个方法含有同样表达式(expression)]。

[代码重复几乎是最常见的异味了。他也是Refactoring 的主要目标之一。代码重复往往来自于copy-and-paste 的编程风格。与他相对应OAOO 是一个好系统的重要标志。]

2.Long Method(过长方法)

我们遵循这样一条原则:每当感觉须要写注释来说明代码的时候。我们就把须要说明的东西写进一个独立的方法中,并以其意图(而非实现手法)命名。

[它是传统结构化的“遗毒”。一个方法应当具有自我独立的意图,不要把几个意图放在一起,特别注意大类和长方法。]

3.Large Class(过大的类)

说明这个类做太多事情。其内往往就会出现太多instance变量。一旦如此。Duplicated Code也就接踵而至了。

[大类就是你把太多的责任交给了一个类。这里的规则是One Class One。]

4.Long Parameter List(过长參数列)

 

5.Divergent Change(发散式修改)

我们希望软件可以更简答被改动——毕竟软件再怎么说本来就该是[软]的。一旦须要改动,我们希望可以找到系统的某一点,仅仅在该处做改动。Divergent Change是指一个class受多种变化的影响。

[一个类里面的内容变化率不同。某些状态一个小时变一次,某些则几个月一年才变一次;某些状态因为这方面的原因发生变化,而另一些则因为其他方面的原因变一 次。面向对象的抽象就是把相对不变的和相对变化相隔离。把问题变化的一方面和另一方面相隔离。这使得这些相对不变的可以重用。问题变化的每个方面都可以单 独重用。这种相异变化的共存使得重用非常困难。]

6.Shotgun Surgery(霰弹式改动)

Shotgun Surgery类似Divergent Change。但恰恰相反。假设每遇到某种变化,你都必须在很多不同的class内做出很多小改动以响应之。你所面临的坏味道就是Shotgun Surgery。假设须要改动的代码散布四处。你不但非常难找到它们。也非常easy忘记某个重要的改动。Shotgun Surgery是指一种变化引发多个classes对应改动。

[这正好和上面相反。对系统一个地方的改变涉及到其他许多地方的相关改变。这些变化率和变化内容相似的状态和行为通常应当放在同一个类中。]

7.Feature Envy(依恋情结)

我们会看到某个方法为了计算某值,从还有一个对象那儿调用差点儿半打的取值方法。最根本的原则是:将总是一起变化的东西放在一块儿。[数据]和[引用这些数据]的行为总是一起变化的。

[对象的目的就是封装状态以及与这些状态紧密相关的行为。如果一个类的方法频繁用get 方法存取其他类的状态进行计算,那么你要考虑把行为移到涉及状态数目最多的那个类。]

8.Data Clumps(数据泥团)

数据项就像小孩子:喜欢成群结队地待在一块儿。你经常能够在非常多地方看到同样的三或四个数据项:两个classes内的同样字段、很多方法签名式中的同样參数。这些[总是绑在一起出现的数据]真应该放进属于它们自己的对象中。

[某些数据通常像孩子一样成群玩耍:一起出现在很多类的成员变量中,一起出现在许多方法的参数中……,这些数据或许应该自己独立形成对象。]

9.Primitive Obsession(基本类型偏执)

大多数编程环境都有两种数据:结构类型让你将数据组织成有意义的形式;基本类型则是构成结构型别的积木块。

[面向对象的新手通常习惯使用几个原始类型的数据来表示一个概念。譬如对于范围,他们会使用两个数字。对于Money,他们会用一个浮点数来表示。因为你没 有使用对象来表达问题中存在的概念,这使得代码变的难以理解,解决问题的难度大大增加。好的习惯是扩充语言所能提供原始类型,用小对象来表示范围、金额、 转化率、邮政编码等等。]

10.Switch Statements(switch惊悚现身)

面向对象程序的一个最明显特征就是:少用switch(或case)语句。

[基于常量的开关语句是OO 的大敌,你应当把他变为子类、state 或strategy。]

11.Parallel Inheritance Hierarchies(平等继承体系)

Parallel Inheritance Hierarchies事实上是Shotgun Surgery的特殊情况。在这样的情况下。每当你为某个class添加一个subclass,必须也为其它已实现的兄弟class对应添加一个subclass。

[并行的继承层次是shotgun surgery 的特殊情况。因为当你改变一个层次中的某一个类时,你必须同时改变另外一个层次的并行子类。]

12.Lazy Class(冗赘类)

你所创建的每个class,都得有人去理解它、维护它,这些工作都是要花钱的。假设一个class的所得不值其身份。它就应该消失。

[一个干活不多的类。类的维护需要额外的开销,如果一个类承担了太少的责任,应当消除它。]

13.Speculative Generality(夸夸其谈未来性)

这个令我们十分敏感的坏味道,命名者是Brian Foote。当有人说“噢,我想我们总有一天须要做这事”并因而企图以各式各样的挂勾和特殊情况来处理一些非必要的事情,这样的坏味道就出现了。

[一个类实现了从未用到的功能和通用性。通常这样的类或方法唯一的用户是test case。不要犹豫,删除它。]

14.Temporary Field(令人迷惑的临时字段)

有时你会看到这种对象:其内某个instance 变量仅为某种特定情势而设。这种代码让人不易理解,由于你通常觉得对象在全部时候都须要它的全部变量。在变量未被使用的情况下推測当初其设置目的,会让你发疯。

[一个对象的属性可能只在某些情况下才有意义。这样的代码将难以理解。专门建立一个对象来持有这样的孤儿属性,把只和他相关的行为移到该类。最常见的是一个特定的算法需要某些只有该算法才有用的变量。]

15.Message Chains(过度耦合的消息链)

假设你看到用户向一个对象索求还有一个对象,然后再向后者索求还有一个对象,然后再索求还有一个对象……这就是Message Chain。实际代码中你看到的可能是一长串getThis()或一长串暂时变量。採取这样的方式,意味客户将与查找过程中的航行结构紧密耦合。

[消息链发生于当一个客户向一个对象要求另一个对象,然后客户又向这另一对象要求另一个对象,再向这另一个对象要求另一个对象,如此如此。这时,你需要隐藏分派。]

16.Middle Man(中间转手人)

人们可能过度运用delegation。你或许会看到某个class接口有一半的方法都托付给其他class,这样就可能是过度运用。

[对象的基本特性之一就是封装,而你经常会通过分派去实现封装。但是这一步不能走得太远,如果你发现一个类接口的一大半方法都在做分派,你可能需要移去这个中间人。]

17.Inappropriate Intimacy(狎昵关系)

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

继承往往造成过度亲热,由于subclass对superclass的了解总是超过superclass的主观愿望。假设你认为该让这个孩子独自生活了,请运用Replace Inheritance with Delegation让它离开继承体系。

[某些类相互之间太亲密,它们花费了太多的时间去砖研别人的私有部分。对人类而言,我们也许不应该太假正经,但我们应当让自己的类严格遵守禁欲主义。]

18.Alternative Classes with Different Interfaces(异曲同工的类)

假设两个方法做同一件事,却有着不同的签名式。

[做相同事情的方法有不同的函数signature,一致把它们往类层次上移,直至协议一致。]

19.Incomplete Library Class(不完美的程序类库)

[要建立一个好的类库非常困难。我们大量的程序工作都基于类库实现。然而,如此广泛而又相异的目标对库构建者提出了苛刻的要求。库构建者也不是万能的。有时 候我们会发现库类无法实现我们需要的功能。而直接对库类的修改有非常困难。这时候就需要用各种手段进行Refactoring。]

20.Data Class(纯稚的数据类)

所谓Data Class是指:它们拥有一些字段,以及用于訪问这些字段的方法,除此之外一无长物。

[对象包括状态和行为。如果一个类只有状态没有行为,那么肯定有什么地方出问题了。]

21.Refused Bequest(被拒绝的遗赠)

Subclasses应该继承superclass的方法和数据。但假设它们不想或不须要继承,又该怎么办呢?它们得到全部礼物。却仅仅从中挑选几样来玩!按传统说法,这就意味继承体系设计错误。

[超类传下来很多行为和状态,而子类只是用了其中的很小一部分。这通常意味着你的类层次有问题。]

22.Comments(过多的注释)

别操心,我们并非说你不该写注释。从嗅觉上说,Comments不是一种坏味道;其实它们还是一种香味呢。我们之所以要在这里提到Comments,由于人们常把它当作除臭剂来使用。经常会有这种情况:你看到一段代码有着长长的注释。然后发现,这些注释之所以存在乃是由于代码非常糟糕。这种情况的发生次数之多。实在令人惊讶。Comments能够带我们找到本章先前提到的各种坏味道。

[超类传下来很多行为和状态,而子类只是用了其中的很小一部分。这通常意味着你的类层次有问题。]



作者:汤姆英朗
链接:https://www.jianshu.com/p/80eec4147835
来源:简书
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。

 

[]内内容转自:https://www.cnblogs.com/feichexia/archive/2012/10/12/2721601.html

你可能感兴趣的:(软件工程)