`
碧海山城
  • 浏览: 192569 次
  • 性别: Icon_minigender_1
  • 来自: 杭州
社区版块
存档分类
最新评论
阅读更多
重构

重构:(名)在软件内部结构的一种调整,目的是在不改变[软件之可察行为]前提下,提高其可理解性,降低其修改成本。
重构:(动)使用一系列重构准则(手法),在不改变[软件之可察行为]前提下,调整其结构。

在使用重构技术开发软件时,把自己的时间分配给两种截然不同的行为:[添加新功能]和[重构]。添加新功能时,
    不应该修改既有代码,只管添加新功能,并通过测试。重构时不应该再添加新功能,只管改进程序结构。此时不该添加任
    何测试,只在绝对必要(用以处理接口变化)时才修改测试。

何时重构

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实现-ex7-4.rar 使用matlab来实现非正交二次样条二维二进小波的快速分解和重构 编程实现例7.4中可分离二维二进小波的快速分解与重构算法 算法实现 使用matlab来实现...

    ART算法图像重构(PPT52页).ppt

    ART算法图像重构(PPT52页).ppt

    重构_重构_改善既有代码_

    《重构:改善既有代码设计》是一本由Martin Fowler所著的经典IT著作,它详细阐述了在软件开发过程中如何通过重构来提升代码质量、可读性和维护性。重构是一种系统性的方法,旨在不改变软件外在行为的前提下,改进其...

    重构(Refactoring)英文版

    #### 二、重构的重要性 重构之所以重要,是因为随着软件系统的不断发展和演变,代码往往会变得越来越复杂和难以管理。如果不进行重构,随着时间的推移,这些系统可能会变成所谓的“遗产系统”或“技术债务”,这将...

    图片二维小波变换的分解与重构_matlab代码

    在MATLAB环境中,实现二维小波变换通常需要编写或调用相关的库函数,但在这个案例中,提供的代码是直接手写卷积函数来完成小波变换的分解与重构过程,这为理解小波变换的底层运算提供了良好的学习机会。 首先,我们...

    Matlab将二维图像三维重构

    ### Matlab将二维图像三维重构 #### 知识点解析 在本知识点中,我们将探讨如何使用Matlab将一张二维图像转换为三维模型的过程。通过分析提供的代码片段,我们可以了解到实现这一转换的基本步骤。 #### 图像读取与...

    matlab 实现一维和二维离散小波变换,以及小波的重构

    matlab 实现一维和二维离散小波变换,以及小波的重构。 matlab实现一维和二维离散小波变换,以及小波的重构,同时有代码实现的截图和各种系数重构的二范式比较 离散小波变换 小波的重构 matlab

    压缩感知 OMP重构一维二维信号matlab仿真

    在MATLAB环境下实现一维和二维信号的压缩感知OMP重构,需要考虑以下关键点: 1. **信号生成**:首先生成一维或二维的测试信号,如随机信号、正弦波、图像等。 2. **稀疏表示**:找到合适的基(如DCT、Wavelet)使得...

    二维图像(二维图像的压缩感知重构算法程序代码、内含完整的MATLAB代码)

    这个压缩包提供的内容是关于二维图像的压缩感知重构算法的MATLAB代码实现,这对于理解和应用CS理论具有很高的价值。 一、压缩感知理论概述 压缩感知理论基于一个假设:如果一个信号是稀疏的或者可以通过某种变换变...

    重构 改善既有代码的设计 pdf 中文

    在软件工程领域中,重构是指对软件内部结构的重新梳理而不改变其外部行为的过程。Martin Fowler所著的《重构:改善既有代码的设计》是一本深入探讨重构技术的经典著作,它与《设计模式》齐名,为软件开发人员提供了...

    haar小波二维图像分解重构matlab代码

    mra_mallat_2D_iterate.m实现二维图像的分解,mra_mallat_2D_merge_iterate.m实现二维图像的重构。程序针对2^N*2^M像素的图像设计,可以实现任意次数的分解与重构。也很很方便改写成针对任意像素的程序。

    重构改善既有代码的设计第2版.pdf

    2. 重构的原则:包括何谓重构、两顶帽子、为何重构、何时重构、重构的挑战、重构、架构和YAGNI、重构与软件开发过程、重构与性能、重构起源何处、自动化重构等。 3. 代码的坏味道:包括神秘命名、重复代码、过长函数...

    结合滤波和深度玻尔兹曼机重构的指纹增强.pdf

    在指纹增强中,DBM被用来重构二值增强指纹图像中的误增强区域。由于DBM能够学习和捕获复杂的数据分布,因此在识别和修复指纹图像的不准确部分时表现出较高的容错能力。 【指纹块质量评价】在指纹增强算法中,对每个...

    Python代码重构的艺术:探索自动化重构工具

    #### 二、代码重构的重要性 代码重构对于软件开发来说至关重要。它不仅能提高代码的质量,还能确保项目的长期可维护性。在Python中,由于其语法设计上的简洁性和易读性,使得代码重构变得更加容易实现。重构不仅...

    二维小波分解与重构程序

    ### 二维小波分解与重构程序的关键知识点 #### 一、二维小波分解与重构概述 二维小波变换是图像处理领域中一种重要的数学工具,主要用于图像压缩、去噪、特征提取等方面。它通过将图像分解成不同分辨率的子带(如...

    POD.rar_POD 重构_POD正交分解_we75t_本征正交分解_流场重构

    在这个主题中,"POD.rar_POD 重构_POD正交分解_we75t_本征正交分解_流场重构" 提到了一种名为“主成分分析”(Principal Component Analysis,PCA)在流体力学中的应用,通常称为“正交分解”(Proper Orthogonal ...

    重构_改善既有代码的设计 Java

    《重构:改善既有代码的设计》是一本在IT领域广受推崇的经典著作,专注于软件开发中的重构实践,尤其针对Java编程语言。重构是软件开发过程中的一个重要环节,它旨在提升代码的可读性、可维护性和整体质量,而不会...

Global site tag (gtag.js) - Google Analytics