目录

  • Duplicated Code(重复代码)
  • Long Method(过长函数)
  • Large Class(过大的类)
  • Long Parameter List(过长的参数列)
  • Divergent Change(发散式变化)
  • Shotgun Surgery(散弹式修改)
  • Feature Envy(依恋情结)
  • Data Clumps(数据泥团)
  • Primitive Obsession(基本类型偏执)
  • Switch Statements(switch 惊悚现身)
  • Parallel Inheritance Hierarchies(平行继承体系)
  • Lazy Class(冗赘类)
  • Speculative Generality(夸夸其谈的未来性)
  • Temporary Field (令人迷惑的暂时字段)
  • Message Chains(过度耦合的消息链)
  • Middle Man(中间人)
  • Inappropriate Intimacy(狎昵关系)
  • Alternative Class with Different Interfaces(异曲同工的类)
  • Incomplete Library Class(不完美的类库)
  • Data Class(纯稚的数据类)
  • Refused Bequest(被拒绝的遗赠)
  • Comments(过多的注释)

坏的味道:指的是应该被修改,被重构的代码,不具有可读性,难理解,冗余代码。应该使用各种重构的手法去改变它!


Duplicated Code(重复代码)

如果你在一个以上的地点看到相同的程序结构,那么可以肯定的:设法将他们合而为一,程序会变得更好。

  • 同一个类的两个函数含有相同的表达式
  • 两个互为兄弟子类内含相同表达式
  • 如果两个毫不相关的类出现Duplicated Code 应该考虑对其中一个将重复代码提炼到一个独立类种,然后在另一个类内使用这个新类。

Long Method(过长函数)

我们应当遵循这样一条原则:每当感觉需要以注释来说明点什么的时候,我们就需要说明的东西写进一个独立的函数中,并以器用途(而非实现手法)命名。

  • 我们可以对一组甚至短短一行代码做这件事。哪怕替换后的函数调用动作比函数自身还长,只要函数名称能够解释其用途,我们也该毫不犹豫得那么做。关键不在于函数得长度,而在于函数:“做什么”和“如何做”之间得语义距离。
  • 如何确定该提炼哪一段代码呢?一个很好得技巧是:寻找注释。它们通常能指出代码用途和实现手法之间的语义距离。如果代码前方有一行注释,就是再提醒你L可以将这段代码替换成一个函数,而且可以在注释得基础上给这个函数命名。 就算只有一行代码,如果他需要以注释来说明,那也值得将它提炼导独立函数去。
  • 条件表达式和循环常常也是提炼得信号。可以使用Decompose Conditional处理条件表达是。至于循环,你应该将循环和期内的代码提炼导一个独立的函数中

Large Class(过大的类)

  • 如果类中有太多的实例变量,可以将几个变量提炼至新类内。提炼时应该选择类内彼此相关的变量,将它们放在一起
  • 类内如果有太多代码,把多余的东西消弭于类内部。如果有五个“百行代码”,它们之中很多代码都相同,那么或许你可以把它们变成五个“十行函数”和十个提炼出的“双行函数”。

Long Parameter List(过长的参数列)

如果已有的对象发出一条请求就可以取代一个参数,那么你应该激活重构手法Replace Paramter with Method。在这里,“已有的对象”可能时函数所属类内一个字段,也可能是另一个参数。你也可以运用Preserve Whole Object将来自同一个对象的一堆数据收集起来,并以该对象替换它们。如果某些数据缺乏合理的对象归属,可以使用Introduce Parameter Object 为它们制造出一个“参数对象”。

Divergent Change(发散式变化)

一旦需要修改,我们希望能够跳到系统的某一点,只在该处做修改。如果不能做到这点,你就嗅出两种相关的刺鼻味道中的一种了。

  • 针对某一外界变化的所有相应修改, 都只应发生在单一类中,而这个新类内的所有内容都应该反应此变化,为此,你应该找出某特定原因而造成的所有变化,然后运用Extract Class将它们提炼导另一个类中。

Shotgun Surgery(散弹式修改)

遇到某种变化,你都必须在不同类内做出许多小修改,你所面临的坏味道就是shotgun Surgery,如果需要修改的代码散布四处,你不但很难找到它们,也很容易忘记某个重要的修改

  • 这种情况下应该使用Move MethodMove Field把所有需要修改的代码放进同一个类。如果眼下没有合适的类可以安置这些代码,就创造一个。通常可以运用inline class把一系列相关行为放进同一个类。
  • Divergent change 是指“一个类受多种变化影响”,shotgun surgery则是指“一种变化引发多个类相应修改”。者两种情况下你都会希望整理代码,使“外界变化”与“需要修改的类”趋于一一对应。

Feature Envy(依恋情结)

函数对某个类的兴趣高过对自己所处类的兴趣,通常焦点便是数据,某个函数为了计算某个值,从另一个对象那调用几乎半打的额取值函数。

  • 疗法显而易见:把这个函数移至另一个地点。
  • 一个函数往往会用到几个类的功能,那么它究竟该被置于何处呢?我们的原则是判断哪个类拥有最多被此函数使用的数据,然后把这个函数和那些数据摆在一起。

Data Clumps(数据泥团)

  • 两个类中相同的字段、许多函数签名中相同的参数。这些总是绑在一起出现的数据真应该拥有属于它们自己的对象
  • 一个好的评判方法是:删掉众多数据中的一项。这么做,其他数据有没有因而失去意义?如果它们不在有意义,这就是个明确信号:你应该为它们产生一个新对象

Primitive Obsession(基本类型偏执)

对象的一个极大的价值在于:它们模糊(甚至打破)了横亘于基本类型数据和体积较大类之间的界限

  • 可以运用Replace Data Vlaue with Object将原本单独存在的数据值替换为对象
  • 如果想要替换的数据值是类型码,而它并不影响行为,则可以运用Replace type Code with class 将它替换
  • 如果有与类型码有关的条件表达式,可运用 Replace Type Code with Subclass 或 Replace Type Code with State/Strategy

Switch Statements(switch 惊悚现身)

大多数时候,一看到switch语句,你就应该考虑以多态来替换它。问题是多态应该出现在哪儿?switch语句常常根据类型码进行选择,你要的是“与该类型码相关的函数或类

Parallel Inheritance Hierarchies(平行继承体系)

Shotgun Surgery的特殊情况,在这种情况下,每当你为某个类增加一个子类,也必须为另一个类相应的增加一个子类。如果你发现某个继承体系的名称前缀和另一个继承体系名称前缀完全相同,便是闻到了这种坏味道

消除这种重复性的一般策略是:让一个继承体系的实例引用另一个继承体系的实例。再运用Move Method 和Move Field,就可以就将引用端的继承体系消弭于无形

Lazy Class(冗赘类)

如果一个类的所得不值其身价,它就该消失

如果某些子类没有做足够的工作,试试Collapse Hierarchy。对于几乎没用的组件,你应该以Inline Class对付它们

Speculative Generality(夸夸其谈的未来性)

不要过分对的为未来考虑

如果你的某个抽象类其实没有太大作用,请运用Collapse Hierarchy。不必要的委托可运用Inline Class除掉。如果函数的某些参数违背用上,可对它实施Remove Parameter。如果函数名称带有多余的抽象意味,应该对它实施rename Method,让它现实一点

Temporary Field (令人迷惑的暂时字段)

某个实例变量仅为某种特定的情况而设。这样的代码让人不易理解,因为你通常认为对象在所有时候都需要它的所有变量,在未被使用的情况下猜测当初其设置目的,会让你发疯的。把所有和这个变量相关的代码新建一个类放入。

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

如果你看到用户一个对象请求另一个对象,然后后者请求另一个对象,然后再请求另一个对象这就是消息链

先观察消息链最终得到的对象用来干什么的,看看能否以Extract Method 把使用该对象的代码提炼到一个独立的函数中再运用Move Method 把这个函数推入消息链

Middle Man(中间人)

人们可能过度运用委托,会有某个接口有一半的函数都委托给其他类,这样就是过度运用, 使用Remove Middle Man ,直接和真正负责的对象打交道

Inappropriate Intimacy(狎昵关系)

  • 过分狎昵的类必须拆散. 你可以采用Move MethodMove Field 帮它们划分界限, 从而减少狎昵行径. 你可以可以看看是否可以运用Change Bidirectional Association to Unidirectional (将双向关联改为单向关联)让其中一个类对另一个斩断情丝.
  • 如果两个类实在是情投意合, 可以运用Extract Class 把两者的共同点提炼到一个安全的地点,让它们坦荡地使用这个新类. 或者也可以尝试运用Hide Delegate让另一个类来为它们传递相思情.
  • 继承往往造成过度亲密, 因为子类对超类的了解总是超过超类的主管愿望. 如果你觉的该让这个孩子独立生活了, 请运用Replace Inheritance with Delegation 让它离开继承体系.

Alternative Class with Different Interfaces(异曲同工的类)

如果两个函数做同一件事,却有着不同的签名,请运用Rename Method根据它们的用途重新命名。但这往往不够,请反复运用 Move Method将某些行为移入类,直到2者的协议一致为止。如果你必须反复而赘余的移入代码才能完成这些,或许可运用Extract SuperClass

Incomplete Library Class(不完美的类库)

如果只想修改类库的一两个函数,可以运用Introduce Foreign Method 如果想要添加一大堆额外行为,就得运用Introduce Local Extension

Data Class(纯稚的数据类)

所谓Data Class是指:它们拥有一些值域(fields),以及用于访问(读写〕这些值域的函数,除此之外一无长物。

  • 这样的classes只是一种「不会说话的数据容器」,它们几乎一定被其他classes过份细琐地操控着。这些classes早期可能拥有public值域,果真如此你应该在别人注意到它们之前,立刻运用Encapsulate Field (封装值域)将它们封装起来。如果这些classes内含容器类的值域(collection fields),你应该 检査它们是不是得到了恰当的封装;如果没有,就运用 Encapsulate Collection(封装群集) 把它们封装起来。对于那些不该被其他classes修改的值域,请运用 Remove Setting Method(移除设置函数)。
  • 然后,找出这些「取值/设值」函数(getting and setting methods)被其他classes运用的地点。尝试以Move Method(搬移函数) 把那些调用行为搬移到Data Class来。如果无法搬移整个函数,就运用 Extract Method(提炼函数) 产生一个可被搬移的函数。不久之后你就可以运用Hide Method (隐藏某个函数)把这些「取值/设值」函数隐藏起来了。

Refused Bequest(被拒绝的遗赠)

指的是一个子类,不需要父类中的过多方法

这样我们可以为这个子类创建一个兄弟类,把父类中不需要的方法下移到兄弟类中去。 如果子类复用了超类的行为(实现),却又不愿意支持超类的接口。不过即使不愿意继承接口,也不要胡乱修改继承体系,应该运用Replace Inheritance with Delegation 来达到目的

Comments(过多的注释)

引用作者的一句话"当你感觉需要撰写注释,请先尝试重构,试着让所有注释都变得多余。"

并不是说写注释不好,而是当你写一段很长的注释来说明代码逻辑的时候,说明这段代码真的很糟糕,你就要考虑重构了。

转载于:https://www.cnblogs.com/cchen93/p/10031412.html

重构改善既有的代码设计(代码的坏味道)相关推荐

  1. 重构-改善既有的代码设计-------代码的坏味道

    重构-改善既有的代码设计 代码的坏味道 神秘命名(Mysterious Name) 给函数.变量.模块和类命名时,要使它能清晰地表明自己的功能和用法,使得写下的代码直观明了. 常用重构手法为重命名,包 ...

  2. 【重构】 代码的坏味道总结 Bad Smell (一) (重复代码 | 过长函数 | 过大的类 | 过长参数列 | 发散式变化 | 霰弹式修改)

    膜拜下 Martin Fowler 大神 , 开始学习 圣经 重构-改善既有代码设计 . 代码的坏味道就意味着需要重构, 对代码的坏味道了然于心是重构的比要前提; . 作者 : 万境绝尘 转载请注明出 ...

  3. 代码的坏味道与重构技术

    一.前言 本文大部分内容.图片来自Martin Flower的<Refactoring>一书以及refactoringguru网站(一个很棒的网站),之前在博客发表过,这次属于整理后重新发 ...

  4. 重构笔记——代码的坏味道(上)

    本文是在学习中的总结,欢迎转载但请注明出处:http://blog.csdn.net/pistolove/article/details/42041757 在重构入门篇中,简单地介绍了重构的定义.为何 ...

  5. 讲点码德!避免这些代码坏味道,努力做一名优秀的程序员

    Martin Fowler:任何一个傻瓜都能写出计算机可以理解的代码.唯有写出人类容易理解的代码,才是优秀的程序员. 大家闭着眼睛想一下什么是好代码?也许你的脑海中漂浮着一堆词:干净.整洁.命名规范. ...

  6. 讲点武德!避免这些代码坏味道,努力做一名优秀的程序员

    Martin Fowler:任何一个傻瓜都能写出计算机可以理解的代码.唯有写出人类容易理解的代码,才是优秀的程序员. 大家闭着眼睛想一下什么是好代码?也许你的脑海中漂浮着一堆词:干净.整洁.命名规范. ...

  7. java 代码坏味道_代码中的坏味道

    前言 在日常生活中,当我们买的水果放久了之后会发出一种难闻的气味("坏味道"),这个时候我们就应该把它扔掉.同样,代码也有"坏味道",当然确定什么是和不是代码& ...

  8. 在项目中寻找代码的坏味道(命名)

    介绍 这段时间一直做项目,所以相对忙碌些,今天终于有时间回过头来好好看一下自己写的代码,看哪里有问题,哪里有"坏味道". 慢慢过,慢慢回忆代码.开始捕捉坏味道. 常做的和常想的事情 ...

  9. 重构-改善既有代码的设计:重构原则(二)

    1.什么是重构 重构(Refactoring):在不改变软件的功能和外部可见性的情况下,为了改善软件的结构,提高清晰性.可扩展性和可重用性而对软件进行的改造,对代码内部的结构进行优化. 2.为何重构 ...

  10. 《重构-改善既有代码设计》读书笔记-重构篇

    2019独角兽企业重金招聘Python工程师标准>>> 重构定义 名词 对软件内部结构的一种调整,目的是在不改变软件可观察行为的前提下,提高其可理解性,降低其修改成本.--<重 ...

最新文章

  1. 专访百度熊辉:有人转AI纯粹因为好找工作,这样的人不是我想要的
  2. LiveVideoStackCon深圳-嵌入式音频开发
  3. Pattern Discovery and Anomaly Detection via Knowledge Graph-学习笔记
  4. 【ArcGIS Pro微课1000例】0014:两种坐标系全国1km分辨率DEM下载地址(WGS84+Albers投影)
  5. Qt5.7+Opencv2.4.9人脸识别(二)人脸采集
  6. chrome+android+浏览器下载图片不显示,chrome谷歌浏览器部分图片不显示怎么办
  7. c语言链表实践报告,双向链表的实践(C语言)
  8. springboot 设置默认访问index.html_【SpringBoot WEB系列】WebFlux静态资源配置与访问
  9. yarn install node-sass(gulp-sass) 安装失败解决方案
  10. 《神经网络与深度学习》课程笔记(2)-- 神经网络基础之逻辑回归
  11. [渝粤教育] 西南科技大学 交通运输经济 在线考试复习资料
  12. Day-04 基础数据类型list, tuple
  13. Linux系统启动的标准流程
  14. colorUI的使用
  15. 垃圾企业微信网页开发记录.md
  16. 深度学习分类pytorch_pytorch使用转移学习的狗品种分类器
  17. MySQL的学习笔记(超详细超完整)
  18. 无线网卡和无线上网卡
  19. pdf怎么转换成word文档呢?
  20. GitHub的raw.githubusercontent.com无法链接

热门文章

  1. PS 动图修改背景坑
  2. 有道云笔记同步失败原因之一
  3. Python高级教程
  4. python怎么跳出while循环_怎么跳出while循环
  5. CSS font-weight 值对应(Regular、Normal、Medium、Light)
  6. python3-欢乐斗牛-实战
  7. Cisco(思科)远程登录交换机
  8. manacher魔板
  9. 动词ing形式的5种用法_动词ing形式的用法及变化规则
  10. linux Permission 0644 for are too open 错误解决方案