膜拜下 Martin Fowler 大神 , 开始学习 圣经 重构-改善既有代码设计 . 代码的坏味道就意味着需要重构, 对代码的坏味道了然于心是重构的比要前提; . 作者 : 万境绝尘 转载请注明出处 : http://blog.csdn.net/shulianghan/article/details/20009689 . 1. 重复代码 (Duplicated Code) 用到的重构方法简介 : Extract Method(提炼函数), Pull Up Method(函数上移), From…
坏味道--重复代码(Duplicate Code) 重复代码堪称为代码坏味道之首.消除重复代码总是有利无害的. 特征 两个代码片段看上去几乎一样. 问题原因 重复代码通常发生在多个程序员同时在同一程序的不同部分上工作时.由于他们正在处理不同的任务,他们可能不知道他们的同事已经写了类似的代码. 还有一种更隐晦的重复,特定部分的代码看上去不同但实际在做同一件事.这种重复代码往往难以找到和消除. 有时重复是有目的性的.当急于满足deadline,并且现有代码对于要交付的任务是"几乎正确的"时…
膜拜下 Martin Fowler 大神 , 开始学习 圣经 重构-改善既有代码设计 . 代码的坏味道就意味着需要重构, 对代码的坏味道了然于心是重构的比要前提; . 作者 : 万境绝尘 转载请注明出处 : http://blog.csdn.net/shulianghan/article/details/20009689 . 1. 重复代码 (Duplicated Code) 用到的重构方法简介 : Extract Method(提炼函数), Pull Up Method(函数上移), From…
所谓Data Class是指:它们拥有一些值域(fields),以及用于访问(读写]这些值域的函数,除此之外一无长物.这样的classes只是一种「不会说话的数据容器」,它们几乎一定被其他classes过份细琐地操控着.这些classes早期可能拥有public值域,果真如此你应该在别人注意到它们之前,立刻运用Encapsulate Field (封装值域,(就是将public 域变成private然后设置set和get).将它们封装起来.如果这些classes内含容器类的值域(collecti…
坏味道--夸夸其谈未来性(Speculative Generality) 特征 存在未被使用的类.函数.字段或参数. 问题原因 有时,代码仅仅为了支持未来的特性而产生,然而却一直未实现.结果,代码变得难以理解和维护. 解决方法 如果你的某个抽象类其实没有太大作用,请运用 折叠继承体系(Collapse Hierarch) . 不必要的委托可运用 将类内联化(Inline Class) 消除. 无用的函数可运用 内联函数(Inline Method) 消除. 函数中有无用的参数应该运用 移除参数(…
1 代码的坏味道 重构一书中提到了22种代码的坏味道,大致可以分为几类. 识别代码的坏味道,有助于发现代码的潜在问题,从而可以有的放矢的修改现有代码,使之不断完善. 1.1 Bloaters(臭鲱,暂译臭代码) 这种类型的味道意味着:代码.函数和类的问题没有立马凸显,但是随着代码不断改变,问题就会越来越明显. 包含五种: 1.1.1 Long Method(过长方法) 特征: 一个方法含有太多行代码.一般来说,任何方法超过10行时,你就可以考虑是不是过长了.函数中的代码行数原则上不要你超过100…
"如果尿布臭了,就换掉它." --Beck奶奶,论保持小孩清洁的哲学 代码的坏味道这一章集中论述该何时重构.具体的重构方法在后面的章节. "没有任何度量规矩比得上见识广博者的直觉.你必须培养自己的判断力,学会判断一个类中有多少实例变量才算太大,一个函数内有多少代码才不算太长." ​ --Martin Flower 3.1 改名 深思熟虑给函数,模块,变量和类命名,使其清晰的表明自己的功能和用法. 重构手法之一:改名(改变函数声明,变量改名,字段改名) 3.2 消除重…
sourcemaking 如果一段代码是不稳定或者有一些潜在问题的,那么代码往往会包含一些明显的痕迹.正如食物要腐坏之前,经常会发出一些异味一样, 我们管这些痕迹叫做 "代码异味".今天让我们一起来熟悉开发中经常出现的22种坏味道情形和解决方法. Duplicated Code 重复代码 不良影响 解决方法 重复代码,难维护 提取公共函数 Long Method 函数长 不良影响 解决方法 函数长, 难理解 拆分成若干函数 Large Class 类大 不良影响 解决方法 类大, 难理…
消灭 Java 代码的“坏味道” 原创: 王超 阿里巴巴中间件 昨天 导读 明代王阳明先生在<传习录>谈为学之道时说: 私欲日生,如地上尘,一日不扫,便又有一层.着实用功,便见道无终穷,愈探愈深,必使精白无一毫不彻方可. 代码中的"坏味道",如"私欲"如"灰尘",每天都在增加,一日不去清除,便会越累越多.如果用功去清除这些"坏味道",不仅能提高自己的编码水平,也能使代码变得"精白无一毫不彻".这…
坏味道--不完美的库类(Incomplete Library Class) 特征 当一个类库已经不能满足实际需要时,你就不得不改变这个库(如果这个库是只读的,那就没辙了). 问题原因 许多编程技术都建立在库类的基础上.库类的作者没用未卜先知的能力,不能因此责怪他们.麻烦的是库往往构造的不够好,而且往往不可能让我们修改其中的类以满足我们的需要. 解决方法 如果你只想修改类库的一两个函数,可以运用 引入外加函数(Introduce Foreign Method): 如果想要添加一大堆额外行为,就得运…
坏味道--狎昵关系(Inappropriate Intimacy) 特征 一个类大量使用另一个类的内部字段和方法. 问题原因 类和类之间应该尽量少的感知彼此(减少耦合).这样的类更容易维护和复用. 解决方法 最简单的解决方法是运用 搬移函数(Move Method) 和 搬移字段(Move Field) 来让类之间斩断羁绊. 你也可以看看是否能运用 将双向关联改为单向关联(Change Bidirectional Association to Unidirectional) 让其中一个类对另一个…
坏味道--过度耦合的消息链(Message Chains) 特征 消息链的形式类似于:obj.getA().getB().getC(). 问题原因 如果你看到用户向一个对象请求另一个对象,然后再向后者请求另一个对象,然后再请求另一个对象--这就是消息链.实际代码中你看到的可能是一长串getThis()或一长串临时变量.采取这种方式,意味客户代码将与查找过程中的导航紧密耦合.一旦对象间关系发生任何变化,客户端就不得不做出相应的修改. 解决方法 可以运用 隐藏委托关系(Hide Delegate)…
坏味道--中间人(Middle Man) 特征 如果一个类的作用仅仅是指向另一个类的委托,为什么要存在呢? 问题原因 对象的基本特征之一就是封装:对外部世界隐藏其内部细节.封装往往伴随委托.但是人们可能过度运用委托.比如,你也许会看到一个类的大部分有用工作都委托给了其他类,类本身成了一个空壳,除了委托之外不做任何事情. 解决方法 应该运用 移除中间人(Remove Middle Man),直接和真正负责的对象打交道. 收益 减少笨重的代码. 何时忽略 如果是以下情况,不要删除已创建的中间人: 添…
坏味道--纯稚的数据类(Data Class) 特征 纯稚的数据类(Data Class) 指的是只包含字段和访问它们的getter和setter函数的类.这些仅仅是供其他类使用的数据容器.这些类不包含任何附加功能,并且不能对自己拥有的数据进行独立操作. 问题原因 当一个新创建的类只包含几个公共字段(甚至可能几个getters / setters)是很正常的.但是对象的真正力量在于它们可以包含作用于数据的行为类型或操作. 解决方法 如果一个类有公共字段,你应该运用 封装字段(Encapsulat…
坏味道--依恋情结(Feature Envy) 特征 一个函数访问其它对象的数据比访问自己的数据更多. 问题原因 这种气味可能发生在字段移动到数据类之后.如果是这种情况,你可能想将数据类的操作移动到这个类中. 解决方法 As a basic rule, if things change at the same time, you should keep them in the same place. Usually data and functions that use this data ar…
坏味道--冗余类(Lazy Class) 特征 理解和维护类总是费时费力的.如果一个类不值得你花费精力,它就应该被删除. 问题原因 也许一个类的初始设计是一个功能完全的类,然而随着代码的变迁,变得没什么用了. 又或者类起初的设计是为了支持未来的功能扩展,然而却一直未派上用场. 解决方法 没什么用的类可以运用 将类内联化(Inline Class) 来干掉. 如果子类用处不大,试试 折叠继承体系(Collapse Hierarchy) . 收益 减少代码量 易于维护 何时忽略 有时,创建冗余类是为…
坏味道--过多的注释(Comments) 特征 注释本身并不是坏事.但是常常有这样的情况:一段代码中出现长长的注释,而它之所以存在,是因为代码很糟糕. 问题原因 注释的作者意识到自己的代码不直观或不明显,所以想使用注释来说明自己的意图.这种情况下,注释就像是烂代码的除臭剂. 最好的注释是为函数或类起一个恰当的名字. 如果你觉得一个代码片段没有注释就无法理解,请先尝试重构,试着让所有注释都变得多余. 解决方法 如果一个注释是为了解释一个复杂的表达式,可以运用 提炼变量(Extract Variab…
坏味道--平行继承体系(Parallel Inheritance Hierarchies) 平行继承体系(Parallel Inheritance Hierarchies) 其实是 霰弹式修改(Shotgun Surgery) 的特殊情况. 特征 每当你为某个类添加一个子类,必须同时为另一个类相应添加一个子类.这种情况的典型特征是:某个继承体系的类名前缀或类名后缀完全相同. 问题原因 起初的继承体系很小,随着不断添加新类,继承体系越来越大,也越来越难修改. 解决方法 一般策略是:让一个继承体系的…
坏味道--霰弹式修改(Shotgun Surgery) 霰弹式修改(Shotgun Surgery) 类似于 发散式变化(Divergent Change) ,但实际上完全不同.发散式变化(Divergent Change) 是指一个类受多种变化的影响.霰弹式修改(Shotgun Surgery) 是指多种变化引发多个类相应的修改. 特征 任何修改都需要在许多不同类上做小幅度修改. 问题原因 一个单一的职责被拆分成大量的类. 解决方法 运用搬移函数(Move Method) 和 搬移字段(Mov…
坏味道--发散式变化(Divergent Change) 发散式变化(Divergent Change) 类似于 霰弹式修改(Shotgun Surgery) ,但实际上完全不同.发散式变化(Divergent Change) 是指一个类受多种变化的影响.霰弹式修改(Shotgun Surgery) 是指多种变化引发多个类相应的修改. 特征 你发现你想要修改一个函数,却必须要同时修改许多不相关的函数.例如,当你想要添加一个新的产品类型时,你需要同步修改对产品进行查找.显示.排序的函数. 问题原因…
坏味道--异曲同工的类(Alternative Classes with Different Interfaces) 特征 两个类中有着不同的函数,却在做着同一件事. 问题原因 这种情况往往是因为:创建这个类的程序员并不知道已经有实现这个功能的类存在了. 解决方法 如果两个函数做同一件事,却有着不同的签名,请运用 函数改名(Rename Method) 根据它们的用途重新命名. 运用 搬移函数(Move Method) . 添加参数(Add Parameter) 和 令函数携带参数(Parame…
坏味道--被拒绝的馈赠(Refused Bequest) 特征 子类仅仅使用父类中的部分方法和属性.其他来自父类的馈赠成为了累赘. 问题原因 有些人仅仅是想重用超类中的部分代码而创建了子类.但实际上超类和子类完全不同. 解决方法 如果继承没有意义并且子类和父类之间确实没有共同点,可以运用 以委托取代继承(Replace Inheritance with Delegation) 消除继承. 如果继承是适当的,则去除子类中不需要的字段和方法.运用 提炼超类(Extract Superclass) 将…
坏味道--临时字段(Temporary Field) 特征 临时字段的值只在特定环境下有意义,离开这个环境,它们就什么也不是了. 问题原因 有时你会看到这样的对象:其内某个实例变量仅为某种特定情况而设.这样的代码让人不易理解,因为你通常认为对象在所有时候都需要它的所有变量.在变量未被使用的情况下猜测当初设置目的,会让你发疯. 通常,临时字段是在某一算法需要大量输入时而创建.因此,为了避免函数有过多参数,程序员决定在类中创建这些数据的临时字段.这些临时字段仅仅在算法中使用,其他时候却毫无用处. 这…
坏味道--Switch声明(Switch Statements) 特征 你有一个复杂的 switch 语句或 if 序列语句. 问题原因 面向对象程序的一个最明显特征就是:少用 switch  和 case 语句.从本质上说,switch 语句的问题在于重复(if 序列也同样如此).你常会发现 switch 语句散布于不同地点.如果要为它添加一个新的 case 子句,就必须找到所有 switch 语句并修改它们.面向对象中的多态概念可为此带来优雅的解决办法. 大多数时候,一看到 switch 语…
坏味道--数据泥团(Data Clumps) 特征 有时,代码的不同部分包含相同的变量组(例如用于连接到数据库的参数).这些绑在一起出现的数据应该拥有自己的对象. 问题原因 通常,数据泥团的出现时因为糟糕的编程结构或"复制-粘贴式编程". 有一个判断是否是数据泥团的好办法:删掉众多数据中的一项.这么做,其他数据有没有因而失去意义?如果它们不再有意义,这就是个明确的信号:你应该为它们产生一个新的对象. 解决方法 首先找出这些数据以字段形式出现的地方,运用 提炼类(Extract Clas…
坏味道--过大的类(Large Class) 特征 一个类含有过多字段.函数.代码行. 问题原因 类通常一开始很小,但是随着程序的增长而逐渐膨胀. 类似于过长函数,程序员通常觉得在一个现存类中添加新特性比创建一个新的类要容易. 解决方法 设计模式中有一条重要原则:职责单一原则.一个类应该只赋予它一个职责.如果它所承担的职责太多,就该考虑为它减减负. 如果过大类中的部分行为可以提炼到一个独立的组件中,可以使用 提炼类(Extract Class). 如果过大类中的部分行为可以用不同方式实现或使用于…
坏味道--基本类型偏执(Primitive Obsession) 特征 使用基本类型而不是小对象来实现简单任务(例如货币.范围.电话号码字符串等). 使用常量编码信息(例如一个用于引用管理员权限的常量USER_ADMIN_ROLE = 1 ). 使用字符串常量作为字段名在数组中使用. 问题原因 类似其他大部分坏味道,基本类型偏执诞生于类初建的时候.一开始,可能只是不多的字段,随着表示的特性越来越多,基本数据类型字段也越来越多. 基本类型常常被用于表示模型的类型.你有一组数字或字符串用来表示某个实…
坏味道--过长参数列(Long Parameter List) 特征 一个函数有超过3.4个入参. 问题原因 过长参数列可能是将多个算法并到一个函数中时发生的.函数中的入参可以用来控制最终选用哪个算法去执行. 过长参数列也可能是解耦类之间依赖关系时的副产品.例如,用于创建函数中所需的特定对象的代码已从函数移动到调用函数的代码处,但创建的对象是作为参数传递到函数中.因此,原始类不再知道对象之间的关系,并且依赖性也已经减少.但是如果创建的这些对象,每一个都将需要它自己的参数,这意味着过长参数列. 太…
1.1.2 Large Class(过大的类) 特征:一个类包含过多的字段.方法.代码行. 问题原因: 类通常一开始很小,但是随着程序的增长而逐渐膨胀. 类似于过长方法,程序员通常觉得在一个现存类中添加新特性比创建一个新的类要容易. 解决方法: 设计模式中有一条重要原则:职责单一原则.一个类应该只赋予它一个职责.如果它所承担的职责太多,就该考虑为它减减负. 如果过大类中的部分行为可以提炼到一个独立的组件中,可以使用 提炼类(Extract Class). 如果过大类中的部分行为可以用不同方式实现…
1.Duplicated Code(重复的代码) 臭味行列中首当其冲的就是Duplicated Code.如果你在一个以上的地点看到相同的程序结构,那么当可肯定:设法将它们合而为一,程序会变得更好. 最单纯的Duplicated Code就是[同一个class内的两个方法含有相同表达式(expression)].这时候你需要做的就是采用Extract Method提炼出重复的代码,然后让这两个地点都调用被提炼出来的那一段代码. 另一种常见情况就是[两个互为兄弟(sibling)的subclass…