美文网首页
代码的坏味道

代码的坏味道

作者: 塞外的风 | 来源:发表于2018-06-09 19:51 被阅读0次

0. 本章内容导图

代码坏味道

1. 常见的代码坏味道

(1)重复代码

坏味道中首当其冲的就是重复代码,重复代码是万恶之源,如果在一个以上的地点看到相同的程序结构,应设法将它们合二为一。

根据重复代码出现的位置,有以下几种情形:

<1> 同一个类的两个函数中含有相同的表达式

<2> 两个互为兄弟的子类内含有相同的表达式

<3> 两个毫不相关的类中出现重复代码

(2)过长函数

很明显,函数过长会很影响理解,尤其是对于超过一屏的函数,过长的函数也容易让初次接触的人陷入具体的实现之中,函数短小且函数名自身就可以解释函数的功能,会使代码变得容易理解,也使得阅读者可以用一种更高的视角来理解程序。

有些公司会限制每个函数的最大代码长度,如最长不超过多少行,对于超过规定行数的函数要进行说明。这种规定虽然过于死板,也有其可取之处,起码可以强迫我们在实现功能时,去仔细琢磨如何以更简练的方式完成功能。

(3)过大的类

过大的类很可能意味着这个类承担了太多的功能,往往会出现太多实例变量,容易造成重复代码。类本身代码过多也可能会造成重复代码。

类的设计要符合单一职责原则,类过大也可能是其承担了过多的职责。

从面向对象的角度出发,类的每个实例都有一个接口,都提供一组相关的服务,通过划分接口,可以把握类所提供的服务,从而判断其是否承担了过多的职责,从而需要对其进行分解。

(4)过长的参数列

函数的参数过多会比较难以理解,也会造成前后不一致,不易使用。更极端的是,如果这些参数类型相同,但取值范围不同,还会造成难以察觉的bug。

(5)发散式变化

发散式变化指的是某个类经常会因为不同的原因在不同的方向上发生变化。

单一职责原则告诉我们,类的职责应该单一,这意味着引起类发生变化的原因也是同一维度的,如果不同维度的变化点都会造成某个类需要被修改,这个类肯定不止承担一种职责。

从面向对象的角度出发,不同的变化维度也需要有不同的封装。

(6)散弹式修改

散弹式修改指的是每遇到某种变化,都需要在许多不同的类内进行很多小修改。如果需要修改的代码散布各处,不但很难找到它们,也会容易忘记某个重要的修改。

面向对象的封装应该包括:

<1> 数据的封装

<2> 接口实现的封装

<3> 变化点的封装

模式的背后往往都隐藏对某种变化的封装。

(7)依恋情结

依恋情结指的是函数对某个类的兴趣高过对自己所在类的兴趣,通常指的是某个函数为了实现某个功能,需要从另一个对象那里调用很多的取值函数。

(8)数据泥团

数据泥团指的是经常会一起结对出现的数据,对于这些数据,删掉众多数据中的一项,其他数据就会变得不再有意义。

例如:结对出现在不同类的字段中;结对出现在很多函数参数中。

(9)基本类型偏执

基本类型偏执指的是习惯于用语言提供的基本类型去组织数据。

面向对象技术的新手通常意识不到在完成一些小功能时采用小对象的好处,例如封装了数值和币种的Money类,封装了起始值和结束值的Range类。

(10)switch惊悚现身

从本质上说,switch语句的问题在于重复。面向对象程序的一个最明显特征就是少用switch语句。大多数时候,看到switch语句,应该考虑是否应该以多态来替换它。

(11)平行继承体系

平行继承体系指的是每当你为某个类增加一个子类,必须也为另一个类相应增加一个子类。它是散弹式修改的一种特殊情况。

(12)冗赘类

程序中创建的每一个类都得有人去理解它、维护它,如果一个类的所得不值其身价,这个类就变得冗余,需要消除它。

(13)夸夸其谈未来性

如果某些抽象类、函数存在的原因仅仅是因为觉得将来会用到,就要考虑删除。

即便将来需求发生变更,重构也会让我们很容易地扩展功能。

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

这里的暂时字段指的是仅为某种特定情况而设的字段。

通常会认为对象内的字段在所有时候都是需要的,为一些特殊情况设置的字段往往会令人非常迷惑,尤其是在不知道特殊情况是什么时。

这种字段很多时候是在修改bug时引入的,为了快速修复bug,往往会引入一些标志位等字段来处理特殊情况。这种以短期目的所做的修改,会加速代码腐败。

(15)过度耦合的消息链

用户向一个对象请求另一个对象,然后再向后者请求另一个对象,然后再请求另一个对象......

这意味着用户代码与导航结构紧密耦合,一旦消息链中所涉及的对象间的关系发生任何变化,客户端都不得不做出相应的修改。

消息是对象之间的通信机制。当对象A调用了对象B的一个方法,对象A就向对象B发送了一个消息。对象B的响应由其返回值定义。

迪米特法则:也叫最少知识原则,意思是一个对象应当对其它对象有尽可能少的了解。

(16)中间人

这里的中间人指的是过度的委托。例如某个类接口有一半的函数都委托给其他类,就是过度运用。

封装意味着对外部世界隐藏其内部细节,这种隐藏往往伴随着委托。

理解适配器模式、代理模式中对委托的使用。

(17)狎昵关系

狎昵关系指的是两个类关系过于亲密,过多的去关注对方的成员(包括field和method),尤其是private成分。

(18)异曲同工的类

异曲同工的类指的是两个类提供的服务相似,类中的函数所作的事情相同,区别仅在于函数签名不同。

(19)不完美的类库

这种坏味道是由于所使用的类库构造的不够完美导致的。

我们几乎总是在系统快要构筑完成的时候才弄清楚它的设计,类库的构筑者也不能未卜先知,有些时候我们需要在类库的基础上做些扩展才能满足实际业务的需求。

《软件设计重构》一书中分析了很多JDK中的设计坏味道,后续会对这块的内容做总结介绍。

(20)纯稚的数据类

数据类指的是拥有一些字段,以及用于访问(读写)这些字段的函数,除此以外没有其他功能的类。

这里所讲的数据类不同于Bean类。

(21)被拒绝的遗赠

子类复用了超类的行为,但不愿意支持超类的接口。

合成复用原则:在涉及复用时,优先使用组合,而非继承。

继承是面向对象最基本的特征之一,它代表一种is-a的关系,表示子类是父类的一种类型,要避免单纯因为复用代码而采用继承。

(22)过多的注释

这里的注释坏味道指的是因为代码设计的很糟糕,而不得不通过引入注释来说明代码的意图。

注释存在的地方往往是需要重构的一种指引,理想情况下是函数可以自注释,即以一种自然语言的方式来命名函数,组织功能。

相关文章

  • 识别代码中的坏味道(三)

    前两篇文章 《识别代码中的坏味道(一)》 和 《识别代码中的坏味道(二)》 中已经介绍了 18 个代码坏味道。《重...

  • 代码坏味道

    Duplicated Code(重复代码) 如果你在一个以上的地点看到相同的程序结构,那么可以肯定:设法将它们合而...

  • 代码的坏味道

    0. 本章内容导图 1. 常见的代码坏味道 (1)重复代码 坏味道中首当其冲的就是重复代码,重复代码是万恶之源,如...

  • 代码的坏味道

    简述 今天主要简单的谈谈重构。重构在项目的开发周期中其实蛮重要的,不过很多小公司并不在乎。多数创业公司和产品都是试...

  • 代码的坏味道

    7.Feature Envy(依恋情结) 表现形式: 一个类的函数对其他类的操作多于自己类中数据的操作。 重构方案...

  • 代码的坏味道

    从我们的经验来看,没有任何度量工具比得上一个见识广博的直觉。你必须培养自己的判断力,学会判断一个类有多少实例变量算...

  • 代码的坏味道

    代码首先是写给人看的,只是恰巧(incidentally)能够运行。 ----Paul Gr...

  • 代码的坏味道

    神秘命名(Mysterious Name) 说白了就是命名不规范,无意义,字段、变量、函数、类等 重复代码(Dup...

  • 代码的坏味道

    软件设计的目的 软件设计的最终目的是使软件代码达到 高内聚低耦合从而使软件 易扩展,更强壮,可移植,更简单 不好的...

  • 代码坏味道:落后的代码

    我之所以称呼这个坏味道为落后的代码,主要是看其是否跟随语言的发展和趋势,是否使用了语言的新特性。通常来说,新的语言...

网友评论

      本文标题:代码的坏味道

      本文链接:https://www.haomeiwen.com/subject/rcczsftx.html