什么时候需要重构,当你在项目代码里面嗅到这个味道的时候,就要进行重构。

 

首个介绍的味道是重复代码的味道。

 

它表现出来的特征是这些:

 

1.一个类里面,两个函数中,含有相同的代码,类似的代码;或者三个函数中,含有相同的代码,类似的代码。这是重复代码的味道。

 

2.两个互为兄弟的子类内含有相同的表达式。这也是重复代码的味道。

 

3.两个不相关的类,出现了重复代码。这也是重复代码的味道。

 
 

如何处理,如何重构

 

1.对于两个函数,出现重复代码,使用Extract Method方法。把某段代码组织到一个新的函数中,然后,将原来函数的某段代码替换为对新函数的调用。

 
 

Extract Method手法介绍
使用Extract Method手法处理原函数某段重复代码时,会面遇到如下几种情况:

 

a.该段代码没有局部变量。
对于a,直接将代码复制到一个新建的函数体中。

 
 

b.该段代码有局部变量。
如果,在段代码中,只是读取局部变量,并没有修改局部变量;或者,局部变量是个对象,这段代码只是调用该对象的某个方法。那么,只需要把这个局部变量当作新建函数的参数便可。

 
 

c.该段代码对局部变量再赋值。
被提炼代码段中,对源函数的某个局部变量进行了修改。
c1.并且,在被提炼代码段的后面,使用该修改后的局部变量。
这个处理手法是这样:
1.局部变量被修改后的结果作为新建函数的返回值。
2.源函数接收新建函数的返回值。

 

遵守的准则:一个函数,只有一个返回值。

 
 

------------------------------------------------------------------------------------------

 

2.两个互为兄弟的子类内含有相同的表达式。这也是重复代码的味道。

 

处理方式,首先使用Extract Method手法;然后,再对Extract Method手法处理后的结果使用Pull up Method,把提炼出来的代码推入超类。

 

Pull up Method(函数上移)手法介绍

 
针对不同情况的做法:

 

1.如果,兄弟类中,出现了相同的函数体。那么,在超类中新建一个函数,存放函数体,在各个子类冲调用该新建函数。

 

2.如果,兄弟类中,出现了相同的函数体,但是,该函数体还使用了所在类的一个字段,可以把该字段也提升到超类。

 

3.如果,兄弟类中,出现了相同的函数体,并且该函数体,还调用了所在类的一个函数。那么,可以考虑,在超类中声明一个抽象函数,由子类实现。然后,在新建的函数体中,调用超类声明的抽象函数。

 

4.兄弟类,有时候,不是出现完全相同的函数体,但是,是相似,这些函数体可以通过某种形式的参数调整,最后将相似的多个函数体调整为一个可以使用某种参数表示新函数。

 
 

-------------------------------------------------------------------------------------------------------

3.Form Template Method

 

两段函数体,它们以相同的顺序执行类似的操作,区别只是每个具体操作是不同的。那么,这是执行顺序的相同,也可以列为重复代码。

 
如下,兄弟类,各自某段函数执行操作顺序相同,每个操作的含义相同,区别只是操作的具体实现不同。
那么,可以这样做,把每段操作,抽象为一个父类函数。
然后,父类新建一个函数,该函数包含的是兄弟类中执行顺序和操作含义相同的代码。
 
比如:
类A
double base = _units*_rate*0.5; ----------------getBaseAmount();
double tax = base*Site.TAX_RATE*0.2;---------getTaxAmount();
return base+tax;-----------------return getBaseAmount()+getTaxAmount();
 
类B
步骤一样,操作步骤含义一样。
 
将getBaseAmount(),getTaxAmount()提到超类中,作为抽象函数,由具体的子类实现。
在超类中,实现 getBillableAmount()函数,它的返回值是getBaseAmount()+getTaxAmount()。
这样,就可以将类B,类A中类似的代码,提取为超类的 getBillableAmount()函数。
 

---------------------------------------------------------------------------

4.Extract Class 提炼类
 
两个不相关的类,出现了重复代码。这也是重复代码的味道。针对这种重复代码的重构手段,是使用Extract Class方法。
 
 
Extract Class手法的介绍
 
一个类,随着开发的进行,你不断往类里面添加方法和字段,不断给类添加各种职责。有一天,你回头,再来看这个类的时候,你发现,这个类过于庞大。
于是,你需要对这个类进行分解,提炼。
提炼的步骤简单的概括为:
1.关键是识别出类里面的各个职责。比如,在一个Person类中,识别出了专门用来打电话的代码,将电话相关的代码提炼到一个TelephoneNumber类中。这样就分离出了Person类中,打电话的职责。
 
 2.然后,在Person类中,使用一个提炼出来的类,作为成员。Person类中,原来需要的打电话功能,可以委托这个TelephoneNumber成员来执行。只保留,从Person到TelephoneNumber的单向连接。
 
3.决定,提炼出来的类,是一个引用类,还是一个值不可变的类。引用类,就是,值会被修改;值不可变类,则是值不会被修改,在首次初始化之后。
 
4.决定,提炼出来的类,是只放在原来的类中,作为原来类中的成员;还是公开,public,被其它类使用。这要考虑。
 
Extract Class手法处理两个不相关的类中的重复代码
 
1.识别出,两个类中,相同的重复代码。
2.将重复代码,提炼到一个新建的类中。
3.新建的类,包含了原来两个类的重复代码。新建的类,作为原来两个类的成员。
4.原来的两个类,委托新建的成员类进行访问,获得原有重复代码的功能。

重复代码Duplicated Code---要重构的信号的更多相关文章

  1. 代码的坏味道(14)——重复代码(Duplicate Code)

    坏味道--重复代码(Duplicate Code) 重复代码堪称为代码坏味道之首.消除重复代码总是有利无害的. 特征 两个代码片段看上去几乎一样. 问题原因 重复代码通常发生在多个程序员同时在同一程序 ...

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

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

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

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

  4. For循环重复代码的重构

    DRY(don't repeat yourself),重复往往是代码腐烂的开始,我们一般的处理手法是将重复的代码提取成一个方法,然后用新方法替换掉原来的代码. 但是对于for循环里面的重复代码要如何处 ...

  5. IntelliJ IDEA “Finds duplicated code”提示如何关闭

    发现重复的代码这个提示真的很烦啊,我们怎么关闭他呢. 设置在这里: Settings -> Editor -> Inspections -> General -> Duplic ...

  6. IntelliJ IDEA 自动导入包 关闭重复代码提示

    idea可以自动优化导入包,但是有多个同名的类调用不同的包,必须自己手动Alt+Enter设置 设置idea导入包 勾选标注 1 选项,IntelliJ IDEA 将在我们书写代码的时候自动帮我们优化 ...

  7. IntelliJ IDEA 自动导入包 快捷方式 关闭重复代码提示

    idea可以自动优化导入包,但是有多个同名的类调用不同的包,必须自己手动Alt+Enter设置 设置idea导入包 勾选标注 1 选项,IntelliJ IDEA 将在我们书写代码的时候自动帮我们优化 ...

  8. 关闭Found duplicated code

    IDEA中的这个“发现重复代码 - Found duplicated code“的这个提示甚是烦躁. Settings —> Editor —> Inspections —> Gen ...

  9. Large Class--过大的类--要重构的信号

    如果想利用单个类做太多事情,其内往往就会出现太多实例变量.一旦如此,Duplicated Code也就接踵而至.     解决方法:     1.将类内彼此相关的变量,将它们放在一起.使用Extrac ...

随机推荐

  1. 常用算法Java实现之冒泡排序

    冒泡排序是所有排序算法中最基本.最简单的一种.思想就是交换排序,通过比较和交换相邻的数据来达到排序的目的. 具体流程如下: 1.对要排序的数组中的数据,依次比较相邻的两个数据的大小. 2.如果前面的数 ...

  2. 让我们一起来做最漂亮的Android界面吧!

    让我们一起来做最漂亮的Android界面吧! AndroidiOS产品设计 摘要:如何为Android设备量身定制以打造出最为完美的应用?这是让诸多开发者很是头疼的问题.不同于iOS,Android设 ...

  3. OSG配置捷径,VS2013+WIN10

    在自己电脑上用CMAKE已经编译好了,上传到百度云里面了. 环境是WIN10+VS2013. 链接:http://pan.baidu.com/s/1hrO7GFE 密码:fwkw 解压之后放在C盘或者 ...

  4. 【Docker 命令】- rm命令

    docker rm :删除一个或多少容器 语法 docker rm [OPTIONS] CONTAINER [CONTAINER...] OPTIONS说明: -f :通过SIGKILL信号强制删除一 ...

  5. 在Centos中,大容量,且读写频繁的目录

    1./根目录 2./usr目录 3./home目录 4./var目录 5./Swap目录     比较特殊,只要物理内存没使用完,就不会被启用 以上为鸟哥的linuxPDF中的学习心得

  6. SPDY以及HTTP2.0

    背景介绍 HTTP2.0跟SPDY在不少理念上是相似的,目的都是为了提升HTTP1.1的性能. HTTP2.0将会是业界的标准,比SPDY要完善,今后可能会都转向http2.0而放弃SPDY. SPD ...

  7. jquery animate() stop() finish() 方法使用

    <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/ ...

  8. poj1065-Wooden Sticks

    题目 有很多小木棍需要机器处理.每个小木棍有重量和长度两个属性.不断把小木棍放入机器中,如果小木棍\(a\)放完后放入小木棍\(b\),那么如果\(a.weight<=b.weight\ and ...

  9. P3385 【模板】负环

    题目描述 暴力枚举/SPFA/Bellman-ford/奇怪的贪心/超神搜索 输入输出格式 输入格式: 第一行一个正整数T表示数据组数,对于每组数据: 第一行两个正整数N M,表示图有N个顶点,M条边 ...

  10. CentOS 配置无线网络,开启wifi

    背景:一台老笔记本安装CentOS7.x,最小安装模式,安装后无法开启wifi 1.先用NetworkManager包的nmcli命令检查网卡,发现无线网卡wlo1信息里有个错误plugin miss ...