PHP 杂谈《重构-改善既有代码的设计》之一 从新组织你的函数

 专业术语算法

 

咱们毕竟是用英文字母编码,因此用一些英语单词,更能显示出咱们的专业性。如下的英文单词,你若是掌握了,与其余coder交流的时候会更直接,更专业。——臭显摆一下吧,呵呵。编程

“*”表示文中常常提到的编程语言

 

inline:内联函数

function:函数性能

*method:方法优化

finely grained:细粒度的编码

rename:重命名spa

query:查询翻译

temp:临时(temporary)——通常指临时变量code

*extract:提取——我我的更喜欢翻译成“提炼”

*duplicate:复制

split:剖解

variable:变量

factor:因素,因子

 

 重构原则

 

1、何谓重构?

     名词形式:对软件内部结构的一种调整,目的是在不改变软件之可察行为前提下,提升其可理解型性,下降其修改为本。

  动词形式:使用一系列重构准则,在不改变软件之可察行为前提下,调整其结构。

 

 2、为什么重构 ?

  一、常常重构可让代码维持该有的形态。

  二、让代码找到合适的位置。

  三、让软件更易理解。

  四、能够找到bug。

  五、提升咱们的编码速度。

 3、重构的难题

  一、修改接口命名

    若是你的类中的方法是public,那么你在rename的时候,冒着很大的风险,你不知道到底有哪些 模块在调用你的这个方法(咱们常常的作法是在整个项目下作grep操做,而后逐一看各个模块的调用和逻辑)。——因此咱们在编写类的时候无论是属性仍是方 法尽可能作到private,避免接口开放。

 

  二、什么时候不应重构

    (1)重写全部代码,并且现有代码实在太混乱,重构还不如重写。

    (2)项目临近结束的时候,应该避免重构。咱们能够把重构放到二期去解决。 

 

 代码的坏味道

  1、Duplicate Code

  一、同一个类,两个方法含有相同表达式。

    解决方法:你能够Extract Method提炼重复代码,而后让这两个方法都调用这个Extract Method。

       二、两个类,有类似的方法。

     解决方法:(1)把两个类的方法提出来,共同构造一个父类。

             (2)把其中一个类的方法删除,调用另外一个类的方法。

 2、Long Method

  一、短函数:代码阅读费点力气,由于咱们必须常常转换上下文去看看子程序作了什么。可是让small method容易理解的真正关键在于一个好的名字。读者能够经过名字了解函数的做用,根本没必要去看其中写了些什么。——早期的编程语言中,调用方法须要额外开销,这使得coder不肯意使用small method。可是现代的OO语言几乎已经彻底免除了process内的额外开销(函数调用)。

 

  二、注释地方提炼信号:每当感受须要以注释来讲明点什么的时候,咱们就把须要说明的东西写进一个独立函数中,并以其用途命名。能够对一组或甚至短短一行代码作这件事。——只要函数名称可以解释其用户,咱们也该绝不犹豫地那么作。

 

"函数"理解为”作什么“或”如何作“

 

  三、条件式和循环经常也是提炼信号。

 

  四、《代码整洁之道》的一个例子。咱们能够想一想!

 

3、Large Class

 

  一、Class内数个属性变量有相同前缀或者字尾,可以使用Extract Class。

 

  二、Class内并不是大多数变量使用属性变量,可以使用Extract Class。

  

  三、有太多代码,可Extract Class。

 

4、Long Parameter

  作成Introduce Parameter Object。——这个我不太赞同,由于我在使用别人方法的时候,我不多去看代码实践,更不要说去看里面都用到了对象的那些属性或者方法,取我想要的数据了。

 

5、Switch Statements

  一、少用switch语句。——问题在于duplication。添加新case的时候,你必须找到全部case并修改它们。

  

  二、用多态来替换它。作法:1.将switch进行Extract Method;2.MoveMethod把case里的实践代码放到多态性的class里。

 

6、 Comments

  试试用Extract Method,若是还不行,那你试试Rename Method。

 

当你感受须要撰写注释,请先尝试重构,试着让全部注释变得多余。

 

  注释通常用于未来的打算,还能够用于你并没有十足把握的区域(为何作某事)。

 

 从新组织你的函数

 

  Long Method每每包含太多信息,这些信息又被错综复杂的逻辑掩盖,不易鉴别。

 

1、Extract Method

情况:我看见一个过长的函数或者须要一段注释才能让人理解用途的代码,那么将这段代码放进一个独立函数中,并让函数名称解释改函数的用途。

 

动机:

简短而有良好命名的函数:——finely grained

  一、复用机会大。

  二、函数读起来像读一系列comments。

  三、函数覆写容易。

重点:函数长度关键在于函数名称和函数本体之间的语义距离。若是提炼动做能够强化代码的清晰度,那么就去作。

做法:

  一、建立新函数,根据函数的意图命名——以它“作什么”命名,而不是以它“怎样作”命名。

    =》 即便Extract Function 很是简单,例如只是消息或函数调用,只要新Function可以以更好方式昭示代码意图,你也应该提炼它。但若是你想不出更有意义的名称,就别动它。

  二、将Extract的代码从Source Function 中Move到New Function中。

2、Inline Method

  Method Body与Method Name同样清晰易懂的时候,请Inline Method。

 

3、Inline Temp

一个临时变量,只被一个简单表达式赋值一次,并且赋值完也只使用了一次。——请Inline Temp

 

4、Replace Temp with Query

若是一个Temp变量,保存一个表达式,将这个表达式Extract Method。——这就是所谓的查询式,query

 

动机:

  一、局部变量会使代码难以提炼。

  二、临时变量会驱使你写出更长的代码。若是改为query method,那么class下的method,均可以得到这份信息。——将编写出更清晰的代码。

  三、Replace Temp with Query每每是你运用Extract Method以前必不可少的步骤。

做法:

  一、找出只被赋值一次的临时变量。

    =>  若是临时变量赋值超过一次,考虑使用Split Temporary Variable将它分割成多个变量。

  二、对Temp Variable赋值的右侧部分,Extract到一个独立函数中。

           =>  将Method声明为private,往后若是有其余class用的时候再放开它(public或protected)。

  

若是代码组织良好,那么你每每能发现更有效的优化方案。————若是性能真的很糟糕,那么放回去也很容易。

 

5、Introduce Explaining Variable

 

将复杂表达式中(或其中一部分)的结果放进一个临时变量,以此变量名称来解释表达式用途。

 

 

动机:

  表达式复杂并且难以阅读。在这种状况下,临时变量能够帮助你将表达式分解为比较容易管理的形式。

  

 6、Split Temporator Variable

 

 某个临时变量被赋值超过一次,它既不是循环变量,也不是集合变量。那么针对每次赋值,创造一个独立的,对应的临时变量。

 

 

动机:

  一、若是临时变量承担多个责任,它就应该被替换为多个临时变量。每一个变量只承担一个责任。

  二、同一个临时变量承担两件不一样的事情,会令review变得糊涂。

6、Remove Assignments To Parameters

若是你的代码对参数进行赋值,那么以一个临时变量取代该参数的位置

 

 

7、Replace Method with Method Object

大型函数对局部变量的使用没法采用Extract Method。那么将这个Method放进一个单独对象中,如此一来,让局部变量成为对象的filed,而后在同一个对象中将大型函数分解为数个小型Method。

 

 

动机:

  一、将相对独立的代码从大型Method中Extract出来,就能够大大提升代码的可读性。

  二、一个Method中,局部变量泛滥成灾,分解这个函数将会很是困难。

  三、Replace Method with Method Object 会将全部局部变量变成对象的值域。而后对这个新对象进行Extract Method了。

8、Substitute Algorithm

 

若是你想把某个算法替换为另外一个更清晰的算法,那么将Method Body替换为另外一个算法。——就是直接修改原来的Method Body。

 

动机:随着对问题有了更多的了解,你发现一件事能够有更清晰的方式,就应该以较清晰的方式取代复杂方式。

相关文章
相关标签/搜索