`
czjxdm
  • 浏览: 124994 次
社区版块
存档分类
最新评论

重构重构

 
阅读更多
如果你想重构,重要的前提就是有强力的测试.哪怕你有自动化重构工具在手.

如果你想对既有代码进行测试,你就必须先重构,因为代码根本就没有办法在测试工具中实例化.

……

新写的代码大多是可以先进行测试,然后再挂接到原有代码中.而对付遗留的代码,我们则需要一点点地把代码抠出来测试.修改遗留代码时,我们需要将代码解依赖出来,建立其测试,然后才对它进行修改.

并不是所有的重构手法都需要测试,特别是我们已经有了自动化的重构工具.下面说的一些解依赖技术就是一些特殊的重构技术.只要我们小步地前进,细心地操作,并借且自动化重构工具,无须测试就能进行重构.而这些重构技术的目标就是为重构出来的代码建立测试.一旦测试建立,则可对代码进行更为自信的修改,则可对代码进行更自信的进一步重构.

这些解依赖技术来自于<<Working effectively with legacy code1>> 第三部分解依赖技术.当然这里面的技术在<<Refactoring…>>中也有,只不过这里更强调的是解除依赖与测试.


我们虔诚追求的,乃是代码的可理解性。

(一)、Bad Smell
1、Duplicated  Code – 重复的代码
    这是最容易看到和被理解的bad smell,如果你在一个以上的地方看到相同的代码,它一定可以改善为复用,提炼出那一段相同代码。
如果重复代码是同一个class内的二个Method,那么直接提炼出来,然后在需要处调用;
如果重复代码位于二个互为兄弟的subClasses 中,需要把重复代码提到superclass内;
如果代码间只是类似,并不完全相同,要先分割它们的相同和异处,或者用Template Method 模式;
如果几个函数以不同的算法做相同的事,就选择较清晰的一个,并统一之;
如果二个不相关的classes 内出现相同的代码,应该考虑将代码提炼到一个独立的class中,然后在另一个class中调用。等等,方法比较多。要多读源码,参考在别人的代码中,这种情况都是怎么处理的。

2、Long Method  -- 过长的方法与函数
    在我不熟悉OO的时候,总觉得程序里到处充满了delegation- 委托,就是找不到它在哪里计算,那时候总以过程式的思维来阅读,处处都是疑惑。后来慢慢就习惯了小型的函数,并且书中讲它的优点与利益 --  解释能力、共享能力、选择能力。
让small method 容易理解的真正关键在于一个好名字。如果你能给method起个一目了然其作用的好名字,阅读者就可以通过名字了解其作用,一般不必去看内部怎样实现。我们应当遵循这样一个原则,每当感觉需要注释来说明一些什么的时候,就将要说明的东西写进独立函数,并以其用途(而不是实现手法)命名。
据说99%的情况下,只要用Extract Method ,找到函数适合集中在一起的地方,提炼出来形成新的Method,就可以将其改小。条件式和循环也常常是需要提炼的信号。

3、Large Class   -- 过大的类
    如果单一class做了太多了事情,这往往是代码“重复、混乱”的信号。
    可以试着将变量提出来、抽出subclass,抽出Interface,抽出domain object,逐步地把它分解变小。

4、Long Parameter List  -- 过长参数列
   参数太长会造成难以理解,参数太多还会带来前后不一致,不易使用,一旦你需要更多的数据,或对某一项改变,修改复杂度都会越来越高。一般情况下,这些参数都可以提为一个Object,即使它确实缺乏合事的归属对像,还可以创建一个参数对像,这样对参数的修改就化为对对像值域的修改。
   但是这里还要注意一点,如果写的方法参数过长,或可能的变化过于频繁,就需要考虑一下自己的结构设计是否合理。

5、Divergent Change -- 发散式变化
良好的设计期待在变化发生的时候,程序更容易修改。一旦需要,只在该改的地方来改,而不是若干地方都涉及。
针对某一外界变化的所有相应修改,都只应该发生在单一class中,这个class的所有内容都应该反映外界变化。为此,我们应当找出可能发生变化之处,然后将它们提炼至另一个class中。
着重指一个class受多种变化的影响。

6、Shotgun Surgery  -- 霰弹式修改
与“发散式变化”类似,它着重指,一个变化引发多个class相应修改。
应该把所有能预见到发生的变化放一个class.

7、Feature Envy   -- 依恋情结
这是一种经典的bad small ,某个函数为了计算一个问题,大量引用另一个对像中的数据。函数对某个class的兴趣高过对自己所在的host class 兴趣。

8、Data Clumps – 数据泥团
常常在很多地方看到相同的几笔数据:例如二个Classes 内的相同的值域、几个函数的相同的参数列表,这些总是在一起出现的数据,应该放在一个类里面。
可以这样来评测: 删掉这些数据中的一个,然后看其它的是否还有意义,如果其它的不再有意义,这就是个明确的信息,应该为它们单独产生一个类的。

9、Primitive Obsession – 基本型别偏执
    我们可以试着在小任务上运用小对像,例如,结合了数值和币别的money class,含起始值和结束值的range class,将原本单独存在的数值替换为对象。
    如果你有一组总是放在一起的值域、或在参数列表中看到基本型别的数据、或发现自己正在从Array中挑选数据。这些时候,不妨考虑下用Object 代替分散的数据。

10、Switch Statements
   从本质上来讲,switch语句的问题在于重复。一旦使用,你会发现同样的switch语句散步于不同的地点,如果要为它添加一个新的case,必须找到所有的switch语句并修改它们。这时,就要考虑用polymorphism多态。

11、Parallel Inheritance Hierarchies – 平行继承体系
    如果你为某个class增加subclass,时,必须也为另一个class相应增加一个subclass,如果你发现某个继承体系的class名称前缀和另一个继承体系的class名称前缀完全相同。消除这种重复性的一般策略是,让一个继承体系的实体引用另一个继承体系的实体,再接着用Move field,Move method。


      重构(Refactoring)技巧读书笔记 之一
General Refactoring Tips, Part 1

本文简要整理重构方法的读书笔记及个人在做Code Review过程中,对程序代码常用的一些重构策略。通过适当的重构代码,的确可以显著提高代码的质量,令人赏心悦目。毫无疑问,这些重构策略均来自于Martin Fowler的《重构-改善既有代码的设计》,只是如何在实际项目中灵活运用而已。(注:本文重构策略的名称及其大部分内容来自《重构-改善既有代码的设计》一书,Martin Fowler 著,侯捷等译)。
先看看重构的定义吧:
(1)Refactoring means rewriting existing source code with the intent of improving its design rather than changing its external behavior. The focus of refactoring is on the structure of the source code, changing the design to make the code easier to understand, maintain, and modify. - 来自Borland Together提供的文档,觉得这个定义很清晰明了。
(2)重构是这样一个过程:在不改变代码外在行为的前提下,对代码做出修改,已改进程序的内部结构。-来自Martin Fowler的定义。
不过,我一般使用一些重构的工具,如ReSharper for VS.Net v1.0和Borland Together for VS.Net v2.0,这些重构工具可以帮助你做很多事情,可以简化你许多工作,同时也可以避免出现一些错误。关于ReSharper for VS.Net v1.0的简单介绍,可以参考本人以前的一篇Posting【体验ReSharper V1.0 for VS.Net 2003 - Part I, 体验ReSharper V1.0 for VS.Net 2003 - Part II】。另外VS.Net 2005已经内置了重构功能。不过,目前这些重构工具还远远不能涵盖各种重构方法,有总比没有好了。
因此,掌握必要的重构技巧逐步成为对程序员基本的要求,重要的是在掌握这些技巧后,也有助于类库初期设计的质量,避免或减少代码的坏味道(bad smell)。

一、代码坏味道(Bad Smell in Codes)及其重构策略
1.尽量消除重复的代码,将它们合而为一
根据重复的代码出现在不同的地方,分别采取不同的重构的策略:
在同一个Class的不同地方:通过采用重构工具提供的Extract Method功能提炼出重复的代码, 然后在这些地方调用上述提炼出方法。
在不同Subclasses中:通过Extract Method提炼出重复的代码,然后通过Pull Up Method将该方法移动到上级的Super class内。
在没有关系的Classes中:通过对其中一个使用Extract Class将重复的代码提炼到一个新类中,然后在另一个Class中调用生成的新类,消除重复的代码。

2.拆解过长的函数
过长的函数在我们的日常代码中经常可见,在C#中常通过#region #endregion区隔为不同的功能区域。
重构策略:通过Extract Method将过长的函数按照功能的不同进行适当拆解为小的函数,并且给这些小函数一个好名字。通过名字来了解函数提供的功能,提高代码的理解性。

3.拆解过大的类
过大的类也经常见到,特别是类中含有大量的成员变量。
重构策略:通过Extract Class将一些相关成员变量移植到新的Class中,如Employee类,一般会包含有联系方式的相关属性(电话, Mobile,地址,Zip等等),则可以将这些移植到新的EmployeeContact类中。

4.过长的参数列
过长的参数列的主要问题是难以理解,并且难以维护。如果要增加新的参数或者删除某一参数,易造成参数前后不一致。
重构策略:如果可以通过向已存在的对象查询获取参数,则可通过Replace Parameter with Method,移除参数列,通过在函数内部向上述已存在的对象查询来获取参数。
如果参数列中若干参数是已存在对象的属性,则可通过Preserve Whole Object将这些参赛替换为一个完整对象,这样不仅提高代码的可读性,同时已易于代码今后的维护。
另外,还可以将若干不相关的参数,使用Introduce Parameter Object来创建一个新的参数类。不过,我个人觉得如果这些情况过多的话,会产生很多莫名其妙的参数类了,反而降低代码的可读性。

个人觉得前面4种坏味道比较显而易见,也比较容易处理。



  • e15.pdf (100.8 KB)
  • 下载次数: 7
分享到:
评论

相关推荐

    学习重构技术的好帮手

    ### 学习重构技术的好帮手 #### 一、重构技术概述 重构是软件开发过程中一个重要的环节,它指的是在不改变外部行为的前提下对现有代码进行改进,优化其内部结构,提升可读性和可维护性。《重构:改善既有代码的...

    何谓重构,为什么要重构?

    ### 何谓重构 重构是一种优化现有代码结构的技术,在不影响软件功能的前提下,通过调整代码来提升其质量和可维护性。这种做法旨在使代码更加清晰、易于理解和修改,从而降低未来维护的成本。 ### 重构的目的 ####...

    【EMD重构】.rar_EMD重构函数_IMF变量重构_tomorrowi4n_模态分解_重构

    标题中的"【EMD重构】.rar"指的是包含EMD重构过程的压缩文件,而"EMD重构函数"是指在处理EMD分解后的IMF分量时使用的特定函数。"IMF变量重构"则是指将分解得到的各个IMF重新组合成原始信号的过程。"tomorrowi4n"可能...

    重构-改善既有代码的设计

    标题与描述均指向了一个核心概念:重构——改善既有代码的设计。这一主题在软件开发领域具有极其重要的地位,它不仅关乎代码质量的提升,更直接影响到软件的可维护性、可扩展性和开发效率。 ### 一、重构的概念 ...

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

    ### 重构_改善既有代码的设计 #### 知识点概览 《重构_改善既有代码的设计》这本书由Martin Fowler撰写,是软件开发领域内的一部经典之作。它不仅为开发者提供了一套系统的重构方法论,还详细介绍了各种实用的重构...

    程式 - 重构与模式

    标题:"程式 - 重构与模式" 此标题指向的是在软件工程和编程领域内,两个核心概念:重构和设计模式。这两个概念是提升代码质量和可维护性的关键策略。 ### 重构 重构是指在不改变程序外部行为的前提下,对内部...

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

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

    重构-改善既有代码的设计+中文版

    根据提供的信息,我们可以了解到这本书名为《重构-改善既有代码的设计》中文版,它是一本旨在帮助程序员提升代码质量的专业书籍。接下来,我们将深入探讨书中所涵盖的一些关键知识点,并结合重构的基本概念来阐述其...

    几种常见的稀疏重构算法代码.rar_FOCUSS重构_Focuss算法_focuss稀疏重构_压缩感知算法_稀疏重构

    在IT领域,稀疏重构算法是信号处理和数据科学中的一个重要概念,特别是在压缩感知理论(Compressive Sensing, CS)中。压缩感知是一种革命性的理论,它表明,如果一个信号可以用较少的非零元素(即稀疏表示)来描述...

    用于信号的EMD、EEMD、VMD分解_vmd重构_故障诊断emd_故障诊断_故障重构_VMD信号重构

    资源名:用于信号的EMD、EEMD、VMD分解_vmd重构_故障诊断emd_故障诊断_故障重构_VMD信号重构 资源类型:matlab项目全套源码 源码介绍:用于信号的分解、降噪和重构,实现故障诊断 源码说明: 全部项目源码都是经过...

    重构改善既有代码的设计PPT课件

    重构是软件开发过程中的一个重要环节,它关注于改善已有代码的设计,以提高代码的可读性和维护性,同时保持原有功能不变。通过重构,程序员能够更有效地管理代码,提升开发效率,减少错误,并促进团队成员之间的沟通...

    重构(Refactoring)英文版

    ### 重构(Refactoring):改善现有代码的设计 #### 一、重构概念解析 重构(Refactoring)是一种软件工程中的重要技术,它指的是在不改变软件系统外部行为的前提下,通过改进其内部结构来提高代码质量的过程。重构...

    重构_改善既有代码的设计[高清版].pdf

    根据提供的文件信息,我们可以推断出这是一份关于软件开发资源汇总的文档,但主要的关注点在于“重构——改善既有代码的设计”这一主题。以下将围绕这个核心知识点展开详细的介绍和解释。 ### 重构——改善既有代码...

    27丨理论一:什么情况下要重构?到底重构什么?又该如何重构?1

    重构是软件开发过程中的一个重要环节,它涉及到代码的优化、设计改进和质量提升,而不改变程序的外部行为。本文将详细探讨重构的目的、对象、时机和方法,帮助开发者理解和掌握重构的核心理念。 **重构的目的(Why...

    Matlab重构算法_matlab_matlab压缩感知重构算法程序实现_压缩感知_

    在本文中,我们将深入探讨基于Matlab的压缩感知(Compressive Sensing,简称CS)重构算法的实现。压缩感知是一种理论先进的信号处理方法,它允许我们以远低于奈奎斯特定理所要求的采样率捕获信号,并能恢复原始信号...

    [电子书] 重构与模式

    Addison-Wesley Professional出版社出版的《重构与模式》一书,正是从理论和实践两个层面探讨了重构和设计模式的结合应用。 重构是一种编程技巧,它允许开发者在不改变软件外部行为的前提下,改善软件内部结构。...

    软件重构 软件重构经典PPT

    【软件重构】是一种重要的软件开发实践,旨在提升代码的质量、可读性和可维护性,同时保持软件原有的功能和外部行为不变。这一概念由 Martin Fowler 在他的著作《重构:改善既有代码的设计》中进行了深入阐述。重构...

    相空间重构,相空间重构理论,matlab

    相空间重构是复杂系统动力学研究中的一个重要方法,它通过从单变量的时间序列数据中恢复出系统的多维相空间,从而揭示系统的行为特征。在MATLAB中,我们可以利用各种算法来实现这一过程,以深入理解非线性系统的动态...

Global site tag (gtag.js) - Google Analytics