文档章节

java特训第四课(转)

旺仔没馒头
 旺仔没馒头
发布于 2017/09/03 16:42
字数 2783
阅读 6
收藏 0
点赞 0
评论 0

在重构入门篇中,简单地介绍了重构的定义、为何重构、何时重构等。我想对于重构是如何运作的,你已经有了较好的理解了。但是对于代码中的坏味道,你可能知道的并不多。坏味道可能是无形中产生的,也可能是开发人员偷懒造成的,还可能是其它某些因素导致的。不管怎么样,代码中的坏味道对程序没有半点好处,它会促使程序腐烂,甚至变质。对于开发人员,真的是很有必要对这些坏味道进行了解和熟悉,理解它们产生的场景。针对当前程序,发现坏味道,对代码进行重构,以消除坏味道,提高代码质量,提高自己水平。

下面让我们一起来熟悉和学习开发中经常出现的22种坏味道情形中的11种。其中,前四种坏味道在大多数开发过程中是不可避免的情形;后面若干种坏味道也会经常性地出现在程序中。我们应该发现它们的存在,并消除它们。

(1)重复的代码
重复的代码是坏味道中出现频率最高的情形非其莫属。如果在一个的以上地方看到相同的代码,那么就可以肯定:想办法将它们合而为一,代码会变得更好。最单纯的重复代码就是“同一个类的两个函数含有相同的表达式”,这时候可以采用抽取方法提炼出重复的代码,然后让这两个地点都调用被提炼出的那一段代码。 另一种常见情况就是“两个互为兄弟的子类内含相同的表达式”,这时候只需对两个类抽取方法,然后将提炼出的代码推入到超类中。如果代码之间只是类似而并非完全相同,那么就需要通过抽取方法将相似部分和差异部分分开,构成单独一个函数。如果有些函数以不同的算法做相同的事,可以使用比较清晰的一个替换掉其余的。

(2)过长的函数
程序员都喜欢简短的函数。拥有短函数的对象会活的比较好、比较长。不熟悉面向对象技术的人,常常觉得对象程序中只有无穷无尽的委托,根本没有进行任何计算。和此类程序共同生活数年后,你才会知道这些小小函数的价值。 应该积极地分解函数,将长长的函数变为多个短小的函数。一般会遵循这样的原则:每当感觉需要用注释来说明点什么的时候,就把需要说明的东西写进一个独立函数中,并以其用途命名。不要嫌麻烦。可以对一组甚至短短一行代码做这件事,哪怕替换后的函数调用动作比函数自身还长,只要函数名称能够解释其用途,也应毫不犹豫地那么做。关键不在于函数的长度,而在于函数“做什么”和“如何做”之间的语义距离。
(3)过大的类
如果想利用单个的类做太多的事情,其内往往会出现太多实例变量。一旦如此,重复的代码就接踵而来。 可以将几个变量一起提炼至新类内。提炼时应该选择类内彼此相关的变量,将它们放在一起。通常如果类内的数个变量有着相同的前缀或字尾,这就意味有机会把它们提炼到某个组件内。 和“太多实例变量”一样,类内如果有太多代码,也是代码重复、混乱并最终走向死亡的源头。最简单的方案是把多余的东西消弭于类内部。如果有五个“百行函数”,它们之中很多代码都相同,那么或许你可以把它们变成五个“十行函数”和十个提炼出的“双行函数”。

(4)过长的参数列
刚开始学编程的时候,或许都是“把函数所需的所有东西都以参数传递进去”。这样也是可以理解的,因为除此之外就只能选择全局数据,而全局数据是邪恶的东西。对象技术告诉我们,如果你手上没有所需的东西,总可以叫一个对象给你。有了对象,你就不必要把函数所需的所有东西都以参数传递给它,只需传给它足够的、让函数能从中获得自己的东西就行。 太长的的参数列难以理解,太多参数会造成前后不一致、不易使用,而且一旦需要更多数据,就不得不修改它。如果将对象传递给函数,大多数修改都将没有必要,因为很可能只需增加一两条请求,就能得到更多的数据。

(5)发散式变化
我们希望软件能够容易被修改——毕竟软件再怎么说本来就该是“软”的。一旦需要修改,我们希望能够跳到系统某一点,只在该处做修改。如果不能做到这点,你就会嗅出两种紧密相关的刺鼻味道中的一种。 如果某个类经常因为不同的原因在不同的方向上发生变化,发散式变化就出现了。其主要指“一个类受多种变化的影响”。当你看着一个类说:“呃,如果新加入一个数据库,就必须修改这三个函数;如果新出现一种工具,就必须修改这四个函数。”那么此时也许将这个对象分成两个会更好,这样对每个对象就可以只因一种变化而需要修改。

(6)霾弹式修改
如果每遇到变化,都必须在许多不同的类内做出许多小修改,你所面临的坏味道就是霾弹式修改。其主要指“一种变化引发多个类相应修改”。如果需要修改的代码散布四周,不但很难找到它们,也很容易忘记某个重要的修改。 这种情况可以把所有需要的代码放进同一个类。如果眼下没有合适的类可以安置这些代码,就创造一个。通常可以运用内联类把一系列相关行为放进同一个类。

(7)依恋情节
众所周知,对象技术的全部要点在于:其是一种“将数据和对数据的操作行为包装在一起”的技术。有一种经典的气味:函数对于某个类的兴趣高过对自己所处类的兴趣。在很多情况下,都能够看到:某个函数为了计算某个值,从另一个对象那儿调用几乎半打的取值函数。疗法也显而易见:把这个函数移至另一个地点,移到它该去的地方。‘ 有时候一个函数往往会用到几个类的功能,那么它究竟该被置于何处呢?处理原则通常为:判断哪个类拥有最多被此函数使用的数据,然后就把这个函数和那些数据摆在一起。

(8)数据泥团
如果用比较形象的事物来形容数据项,我想“小孩子”是一个不错的选择,数据项就像小孩子,喜欢成群结队地呆在一块儿。常常可以在很多地方看到相同的三四项数据:两个类中相同的字段、许多函数签名中相同的参数。这些总是绑在一起出现的数据真应该拥有属于它们自己的对象。 这种情况可以先找出这些数据以字段形式出现的地方,将它们提炼到一个独立对象中,然后将注意力转移到函数签名上,运用参数对象为它减肥。这样做的直接好处是可以将很多参数列缩短,简化函数调用。一个比较好的评判方法是:删掉众多数据中的一项。这么做其它数据有没有因而失去意义?如果它们不再有意义,这就是一个明确的信号:应该为它们产生一个新对象。

(9)基本类型偏执
大多数编程环境都有两种数据:结构类型允许你将数据组织成有意义的形式;基本类型则是构成结构类型的积木块。但是请记住:结构总是会带来一定的额外开销。它们可能代表着数据库中的表,如果只为做一两件事而创建结构类型也可能显得很麻烦。 对象的一个极大价值在于:它们模糊甚至打破横亘于基本数据和体积较大的类之间的界限。如果你有一组应该总是被放在一起的字段,可以将其抽取为一个独立的类。如果你在参数列中看到基本型数据,可以引入参数对象进行处理。如果你发现自己正从数组中挑选数据,可以运用以对象取代数组进行处理。

(10)Switch惊悚现身
面向对象程序的一个较明显特征是:少用switch语句。从本质上说,switch语句的问题在于重复。你常会发现同样的switch语句散布于不同的地方。如果要为它添加一个新的case语句,就必须找到所用switch语句并修改它们。面向对象中的多态概念可为此带来优雅的解决办法。 大多数时候,一看到switch语句,那就应该考虑以多态来替换它。switch语句常常根据类型码进行选择,你要的是“与该类型码相关的函数或类”,所以应该将switch语句提炼到一个独立函数中,再将它搬移到需要多态性的那个类里。

(11)平行继承体系
平行继承体系其实是霾弹式修改的特殊情况。在这种情况下,每当为某个类增加一个子类,必须也为另一个类增加一个子类。如果发现某个继承体系的类名称前缀和另一个继承体系的类名称前缀完全相同,这种坏味道就会被嗅出。 消除这种重复性的一般策略是:让一个继承体系的实例引用另一个继承体系的实例。

转自:这里

© 著作权归作者所有

共有 人打赏支持
旺仔没馒头
粉丝 2
博文 15
码字总数 10924
作品 0
潍坊
程序员
java安全沙箱(二)之.class文件检验器

java是一种类型安全的语言,它有四类称为安全沙箱机制的安全机制来保证语言的安全性,这四类安全沙箱分别是: 类加载体系 .class文件检验器 内置于Java虚拟机(及语言)的安全特性 安全管理器...

xionghuiCoder
2015/09/04
0
0
Java研发大学毕业后为何找不到理想的工作

现在大学生在大学学习Java技术,毕业后直接工作,我想在大家心里这只是再平常不过的事情了,可是为啥刚一毕业的Java应聘工程师会遭到各个研发企业的拒绝,这是刚毕业的每个大学生心中的疑虑,...

我爱编程学习
06/07
0
0
云栖社区专家系列课——Java必修课第一讲

本节课为 Java必修课第一讲。在本节课中,最课程创始人、微软MVP陆敏枝为了大家介绍了当前Java行业的IT人才供需情况、Java基本语法、JDK的下载与安装、Java环境变量的配置以及第一个Java程序...

笑傲江湖lcx
07/03
0
0
给代码减负,会RIA的程序猿你伤不起!

身为一名求学者,不得不说,在漫长的等待中,我终于盼到了RIA的实训课程。 其实起先我并不知道什么是RIA,之所以参与进来是因为之前在中达金桥学过LINUX的同学告诉我,他们现在开办了个新的培...

ZDJQ
2011/07/01
0
0
2018年暑假第一周周总结报告

一眨眼,暑假第一周过去了。这一周大部分时间都是在学校度过的。在7月14日之前,我在学校宿舍待着,便开始刷我的网络课程。虽然这些课看上去不是太重要,但从中也学到了不少知识。 周一,我对...

寂天风
07/15
0
0
五本值得一读的超棒Java电子书(附下载)

http://www.itwaka.com/ 网络上有很多关于Java的免费电子书,但是大多数都是过时的或者是不准确的。这是说的Java免费电子书是我收藏中最好的五本,它们在使用 Java编程语言的人群中是出名的,...

itwaka
2011/06/27
0
0
理解ThreadLocal 2

摘自《Spring 揭密》 王福强著 人民邮电出版社 1 ThreadLocal的背景 单单从程序层面来看,我们编写的代码实际上是在管理系统中各个对象的相关状态,如果不能对各个对象的状态的访问进行合理的...

i33
2012/03/22
0
0
学java还是javascript好?哪个更有前途?

  对于哪种语言好这种问题,其实并没有固定的答案,最重要的还是 兴趣!兴趣!兴趣!重要的事情说三遍。无论做什么开发,永远要以兴趣来驱动自己学习。 先大致的说一下,Java学习是一个需要...

W3Cschool小编
04/23
0
0
CHM格式的可以全文搜索的Spring3.2官方参考文档

Spring的官方参考文档是html格式的,并且没有目录树,用它本身的跳转功能,跳来跳去经常把头给跳晕了! 最重要的一个缺点是没有全文搜索,于是一生气就做了一个CHM格式的有目录,带全文搜索的最新S...

白石
2013/01/18
0
4
有写编译器的冲动?进来看看!(转)

http://blog.csdn.net/lm2302293/article/details/6798765 工作如果是和编译器相关的或者编译器爱好者们,谁没有点冲动想自己写个编译器出来。我也做了一些调研,分享如下: How to write y...

大卷卷
2011/09/24
0
3

没有更多内容

加载失败,请刷新页面

加载更多

下一页

Git 2.18版本发布:支持Git协议v2,提升性能

Git 2.18版本发布:支持Git协议v2,提升性能Git 2.18版本发布:支持Git协议v2,提升性能 新版本协议的主要驱动力是使 Git 服务端能够对各种 ref(分支与 tag)进行过滤操作。 这就意味着,G...

linux-tao
20分钟前
0
0
python浏览器自动化测试库【2018/7/22-更新】

64位py2.7版本 更新 document_GetResources 枚举页面资源 document_GetresourceText 获取指定url的内容 包括页面图片 下载地址下载地址 密码:upr47x...

开飞色
36分钟前
24
0
关于DCL双重锁失效及解决方案

关于DCL双重锁失效及解决方案 Double Check Lock (DCL)实现单例 DCL 方式实现单例的优点是既能够在需要时才初始化单例,又能够保证线程安全,且单例对象初始化后调用getInstance方法不进行...

DannyCoder
42分钟前
0
0
PowerDesigner 16.5 安装配置

PowerDesigner16.5破解版是一款业内领先且开发人员常用的数据库建模工具,PowerDesigner可以从物理和概念两个层面设计数据库,方便用户制作处清晰直观的数据流程图和结构模型,欢迎有需要的朋...

Gibbons
今天
0
0
mac Homebrew 指令积累

1通用命令 brew install [包名] //安装包 brew list //列举安装的包 brew info [包名] // 显示安装包的详细信息 mysql 相关 #启动mysql 服务 brew service start mysql my...

Kenny100120
今天
0
0
前端Tips: 创建, 发布自己的 Vue UI 组件库

创建, 发布自己的 Vue UI 组件库 前言 在使用 Vue 进行日常开发时, 我们经常会用到一些开源的 UI 库, 如: Element-UI, Vuetify 等. 只需一行命令, 即可方便的将这些库引入我们当前的项目: n...

ssthouse_hust
今天
1
0
大数据教程(2.13):keepalived+nginx(多主多活)高可用集群搭建教程【自动化脚本】

上一章节博主为大家介绍了目前大型互联网项目的keepalived+nginx(主备)高可用系统架构体系,相信大家应该看了博主的文章对keepalived/nginx技术已经有一定的了解,在本节博主将为大家分享k...

em_aaron
今天
5
0
Git 2.18版本发布:支持Git协议v2,提升性能

在最新的官方 Git 客户端正式版2.18中添加了对 Git wire 协议 v2 的支持,并引入了一些性能与 UI 改进的新特性。在 Git 的核心团队成员 Brandon Williams 公开宣布这一消息前几周,Git 协议 ...

六库科技
今天
0
0
Java8新特性之接口

在JDK8以前,我们定义接口类中,方法都是抽象的,并且不能存在静态方法。所有的方法命名规则基本上都是 public [返回类型] [方法名](参数params) throws [异常类型] {}。 JDK8为接口的定义带...

developlee的潇洒人生
今天
0
0
aop + annotation 实现统一日志记录

aop + annotation 实现统一日志记录 在开发中,我们可能需要记录异常日志。由于异常比较分散,每个 service 方法都可能发生异常,如果我们都去做处理,会出现很多重复编码,也不好维护。这种...

长安一梦
今天
2
0

没有更多内容

加载失败,请刷新页面

加载更多

下一页

返回顶部
顶部