重构
重构:(名)在软件内部结构的一种调整,目的是在不改变[软件之可察行为]前提下,提高其可理解性,降低其修改成本。
重构:(动)使用一系列重构准则(手法),在不改变[软件之可察行为]前提下,调整其结构。
在使用重构技术开发软件时,把自己的时间分配给两种截然不同的行为:[添加新功能]和[重构]。添加新功能时,
不应该修改既有代码,只管添加新功能,并通过测试。重构时不应该再添加新功能,只管改进程序结构。此时不该添加任
何测试,只在绝对必要(用以处理接口变化)时才修改测试。
何时重构
1.三次法则,事不过三,三次重构。
2.添加功能时一并重构。
3.修补错误时,一并重构。
4.复审代码时,一并重构。
重构价值
程序有两面价值:[今天可以为你做什么]和[明天可以为你做什么]。大多数时候只关注今天想要程序做什么。不论是修复错误或是添加特性,我们都是为了让程序能力更强,让他在今天更有价值。
但是,系统今天的行为,只是整个软件的某一部分,如果没认识到这点,那么无法从事长期的编程工作。只为求完成今天的任务而采取的手法,而不能完成明天的任务,那么还是失败的。
我们希望程序:(1)容易阅读;(2)所有逻辑都只在唯一地点指定;
(3)新的改动不会危及现有行为;(4)尽可能简单表达添加逻辑;
间接层和重构
重构往往把大型对象拆成数个小型对象,把大型函数拆成数个小型函数。但是间接层是一把双刃剑,每次把一个东西分成两份,你就
需要多管理一个东西。如果某个对象委托(delegate)另一个对象,后者又委托另一个对象,程序会难以阅读。基于这个观点,我们希望尽量的减少间接层。
但是间接层确实存在很大的价值:
(1)它允许逻辑共享。比如说一个子函数在两个不同的地点被调用,或superclass中的某个函数被所有subclasses共享。 (2)分开意图和实现。(3)将变化加以隔离。
(4)将条件逻辑加以编码。
何时不该重构
(1)重构它还不如重新写一个来得简单
(2)如果项目已经接近最后期限,也应该避免重构
自我测试
程序员最多的时间并不是花在编写代码上。有些时间用来决定下一步做什么,有些时间花在设计上,最多的时间可能是用来调试。
频繁的运行测试(极限编程的重要一环)能使你的项目更加不容易出错,或者说更快的找出错误。这就需要:确保所欲测试都完全自动化,
让他们检查自己的测试结果。一整组测试就是一个强大的[臭虫]侦测器,能够大大缩减查找[臭虫]所需要的时间。考虑可能出错的边界条件,把测试精力集中在那里。
1. Duplicated Code(重复的代码)
代码重复几乎是最常见的臭味,不管你的经验多么丰富,它总是经常出现在项目中,作者提出的第一个准则就是
Extract Method(110,提炼函数),这我想大家平时可能都会经常用到(我觉得本书不仅仅是告诉你很多不知道的,还把很多你知道的重构手法给出了适当的定义,即使他简单的不能再简单)。
如果提炼动作可以强化代码的清晰度,那就去做,就算函数名称比提炼出来的代码还长也无所谓。
当你运用Extract Method将相似部分和差异部分开时,构成单独一个函数,你可能发这些函数以相同的顺序执行类似的措施,但个措施实际上有所不同。这时候你可以使用
Form Template Method(345,塑造模板函数)。回顾我维护过的一个项目,负责帮别人写几张报表,一共有七八张报表,数目也不是很多,每次生成的时候总会调用类似的方法,比如是设置背景色,标题,页眉,页脚等,当时采用的方法是,每个报表都复制粘贴相同的代码,设置一下不同的页眉或者角色就OK了,虽然觉得代码有改进的地方,但是当时并没有看到重构这本书,而且是别人的项目,我只是临时参与,所以也就没管那么多,现在发现确实可以使用Form Template Method重构当时的代码,增加可读性和可理解性。
如果两个毫不相关的classes内出现重复的代码,应该考虑对其中一个使用
extract Class(149,提炼类),将重复的代码提练到一个独立的Class中,然后在另一个class内使用这个新class。
2.Long Method(过长函数)
程序愈长愈难以理解,如果能给程序起一个好名字,就可以通过名字了解函数的作用,根本不用去管代码里面写了什么。对于过长的函数我们通常才去extract method,但有时候过多的临时变量会让你的提炼方法有过长的参数列,使得可读性几乎没有提升,这时候可以采用
Replac Temp With Query(120,查询替换临时变量),那么同一个class中都可以获得这份信息,对于某些赋值多次的临时变量可以使用
Split Temporary Variable(128,剖析临时变量),针对每次赋值,创建一个独立的、对应的临时变量。对于赋值超过一次,既不是循环变量也不是一个集用临时变量时,针对每次赋值,创造一个独立的对应的临时变量,这里可以将变量申明为final,确保他只被赋值一次。
对于过长的参数列可以用
Introduce Parameter Object(295,引入参数对象)或者Preserve Whole Object(288,保持对象完整,改传递对象的某些属性而传递整个对象),对于一个复杂一点的查询总是容易引入过长的参数,这时用这两个方法,再结合某些框架,将会得到非常简洁的代码,比如struts2的模型驱动。
如果这样还有过多的临时变量和参数,可以使用
Replace Method with Method Object(135,以函数对象取代函数),将函数放进一个单独的对象中,再采用前面的方法。
对于提炼哪一段代码,很好的技巧就是:寻找注释,这通常是提炼函数的信号,就算只有一行代码,如果它需要注释来说明,那也值得将他提练到一个函数中去。
条件式和循环常常也是提炼的信号,条件式可以使用Decompose Conditional(238,分解条件式)从if else 中分别提炼出独立的函数。至于循环,应该将循环和其内的代码提炼到一个独立函数中。
3
.Large Class(过大类)
如果单一的Class做太多的事情,其内往往会出现太多的instance变量,同时也会照成Duplicated Code。如果Class内的数个变量有着相同的前缀或者字尾,就意味着,有机会把他们提练到某个组件内,例如
Extract Subclass(330,提炼子类,Class中的某些特性只被某些实体用到),一个可能的信号就是,你的类中有一些属性充当标志位的作用:如果A,那么…..,如果B,那么…….,这时,你就可以考虑提炼子类,并运用
Replace Conditional Polymorphism(225,运用多态取代条件式)
当然前面提到的Extract Class 和提炼函数等都是可以结合使用,这里作者还提到了一个技巧,就是
先确定客户端如何使用类,然后运用Extract Interface(341,提炼接口)为每一种使用方式提炼出一个接口,如果某个class在不同环境下扮演截然不同的角色,使用interface就是个个好主意。可以针对每个角色提炼出相应的接口。将这种不同分离出来更加清晰,同时也更加容易看清楚系统的责任划分,当然公共的接口不能提供公共的代码,所以通常一个公共的借口会照成代码重复的臭味,这里有一个小原则,针对每一个公共的接口,总应该提供一个公共的实现类。
4.Long Parameter List(过长参数列)
过长参数列对程序的可读性确实会照成非常大的影响,而且更重要的是过长的参数通常都是开发初期的不合理设计,随着系统开发会不断增加参数或者去除参数,这种频繁的改变对调用者来说是非常讨厌的,而且容易照成错误,这时候,使用Introduce Parameter Object(295,引入参数对象),当然有时候你也可以使用Replace Parameter with method(292,以函数取代参数)和Preserve Whole Object(288,保持对象的完整)
5.Divergent Change(发散式变化)
如果因为某些外部事物的变化或者加入一个新的事物,那么这个类里面的几个方法就得改变,此时将改变的部分和不改变部分分为两个更好。
这个臭味通常很难发现,通常要有外部因素的时候你才会发现可以提炼的部分,但是问题不大,事不过三嘛
6.Shotgun Surgery
这个和Divergent Change有点类似,只不过这个是指Divergent Change一个class受多种变化的影响,而这里则是一个变化引发多个class相应的修改。我们可以使用
Move Method(142,搬移函数)和Move Field(146,搬移值域)把所有需要改的地方移进同一个class。有时你将使用Inline Class(154,将类内联化)对于那些不再承担责任,就应该将类内联化。
7.Feature Envy(依恋情节)
这里面的一些依赖关系以及取舍则是仁者见仁智者见智,反正无论何时,move method和extracr method都是方便使用的。
8.Data Clumps(数据泥团)
前面提到的过长参数项就好像属于这一项的一个子集,前面提到的方法都是可用的
分享到:
相关推荐
四参数随机生长法
二维二进小波的快速分解与重构算法matlab实现-ex7-4.rar 使用matlab来实现非正交二次样条二维二进小波的快速分解和重构 编程实现例7.4中可分离二维二进小波的快速分解与重构算法 算法实现 使用matlab来实现...
ART算法图像重构(PPT52页).ppt
Matlab将二维图像三维重构源代码,把下面的代码写成m文件,运行就可以了。具体你要看到什么样的三维模型,你可以在此基础上修改。
matlab 实现一维和二维离散小波变换,以及小波的重构。 matlab实现一维和二维离散小波变换,以及小波的重构,同时有代码实现的截图和各种系数重构的二范式比较 离散小波变换 小波的重构 matlab
重构——改善既有代码设计,经典文档,架构师必须教程
压缩感知 OMP重构一维二维信号matlab仿真
重构英文版 M. Fowler, K. Beck, J. Brant, W. Opdyke and D....重构(Refactoring)是指在不改变软件系统外部功能的前提下,对软件系统的内部结构重新设计,以提高代码的可复用性和可扩展性等质量。...《软工双雄》之二。
mra_mallat_2D_iterate.m实现二维图像的分解,mra_mallat_2D_merge_iterate.m实现二维图像的重构。程序针对2^N*2^M像素的图像设计,可以实现任意次数的分解与重构。也很很方便改写成针对任意像素的程序。
网站重构 web标准设计参考 网站重构 web标准设计参考
三维重构 可以检测有效的系统缺陷,进行缺陷的定位,缺陷体积的测量等,如何进行三维重构(3D reconstuction)的输入是各种三维以下的数据,比如纯二维的RGB图像(序列)、带有深度信息的RGBD数据等,出来的是三维...
二维小波变换二级分解和重构,里面没有用库函数,基本上都是手写卷积函数等等,直接下载实现即可!
二维图像(二维图像的压缩感知重构算法程序代码、内含完整的MATLAB代码)
这是讲解 前端重构实践(二) —— 模块化开发
第1章 重构,第一个案例 1.1 起点 1.2 重构的第一步 1.3 分解并重组Statemen 1.4 运用多态取代与价格相关的条件逻辑 1.5 结语 第2章 重构原则 2.1 何谓重构 2.2 为何重构 2.3 何时重构 2.4 怎么对经理说 2.5 重构的...
提出了一种基于对象的二值图像的重构算法。该算法利用二值图像中像素间自然的、基本的关系,达到含有噪音的二值图像去噪的效果。首先将水印图像的所有邻接分量标注出来,然后计算每个邻接分量包含的元素的数目;因为...
流场的本征正交分解与流场重构,包括读取数据,生成模态,模态系数,重构。代码清晰,每部分都有注释。
面对新型电力系统建设的快速推进,二次系统面临测量不准确、保护失效、控制不协同、监控不全面等问题,必须全面研究解决,重构二次系统架构,研究新的保护原理,加强监控能力建设,保障新型系统的安全可靠运行。...
经典重构书籍,以Java语言为基础编写,讲解了重构的意义,介绍了多种重构方法。
二维图像的小波分解与重构,并画图显示。通过多分辨率分析实现。