重构|重构方法汇总&代码Demo

重构方法数组

从新组织函数

提炼函数 Extract Method

function printOwing($amount){
    printBanner();
    
    // print details
    echo NAME;
    echo $amount;
}

/** Refactor **/

function printOwing($amount){
    printBanner();
    printDetails($amount);
}

function printDetails($amount){
    echo NAME;
    echo $amount;
}

动机: 当遇到过长的函数或者一段须要注释才能让人理解的代码时使用。数据结构

当遇到局部变量时,要当心!并发

当发现源函数的参数被赋值时,应该使用Remove Assignments to Parameters方法。分布式

内联函数-Inline Method

function getRating(){
    return moreThanFiveLateDeliveries() ? 2 : 1;
}

function moreThanFiveLateDeliveries(){
    return NUMBER_OF_LATE_DELIVERIES > 5;
}
/** R **/

int getRating(){
    return NUMBER_OF_LATE_DELIVERIES > 5 ? 2 : 1;
}

注意:重构函数不该具备多态性ide

内联临时变量-Inline Temp

$basePrice = AnOrder->basePrice();
return $basePrice > 1000;

/** R **/

return AnOrder->basePrice() > 1000;

动机:Inline Temp多半是做为Replace Temp with Query的一部分使用的。函数

查询渠道临时变量-Replace Temp with Query

$basePrice = $quantity * $itemPrice;
if($basePrice > 1000){
    return $basePrice * 0.95;
}else{
    return $basePrice * 0.98;
}

/** R **/

function basePrice(){
    return $quantity * $itemPrice;
}

if(basePrice() > 1000){
    return basePrice() * 0.95;
}else{
    return basePrice() * 0.98;
}

动机:将临时变量做为查询,同一个类中的全部函数都可以访问设计

注意:要肯定下来final型的变量,为了更好的编写后续程序。code

引入解释性变量-Introduce Explaining Variable

if((Platform->toUpperCase()->indexOf("MAC") > -1)
 && (Browser->toUpperCase()->indexOf("IE") > -1)
 && wasIntialized() && $resize > 0)
 {
     // Do sth
 }

/** R **/

final boolean isMacOs = Platform->toUpperCase()->indexOf("MAC") > -1;
final boolean isIEBrowser = Browser->toUpperCase()->indexOf("IE") > -1;
final boolean wasResized = resize > 0;

if(isMacOs && isIEBrowser && wasIntialized() && wasResized){
    // Do sth
}

动机:消除复杂表达式,用临时变量解释、归总每一步的意义orm

分解临时变量-Split Temporary Variable

拒绝临时变量的屡次赋值,致使不一样位置而具备不一样意义。server

移除对参数的赋值-Remove Assignments to Parameters

function discount($inputVal, $quantity, $yearToDate){
    if($inputVal > 50){
        $inputVal -= 2;
    }
}

/** R **/

function discount($inputVal, $quantity, $yearToDate){
    $result = $inputVal;
    if($inputVal > 50){
        $result -= 2;
    }
}

拒绝对参数赋值,保持对参数入出不变。

以函数对象取代类中函数-Replace Method with Method Object

若是一个函数过大(问题函数),考虑新建一个类来代替这个问题函数。

在对象之间搬移特性-决定责任归属

搬移函数-Move Method

若是一个类与另外一个类有太多合做而造成高度耦合,则须要搬移函数,构建新类。

搬移字段-Move Field

同理上面的方法。

提炼类-Extract Class

若是某个类作了两个类作的事情,考虑新建一个类来处理。

将类内联化-Inline Class

若是某个类没有作太多事情,能够将这个类的特性搬移到另外一个类中,移除原类。

隐藏委托关系-Hide Delegate

客户经过一个委托类来调用另外一个对象。在服务类上创建客户所需的全部函数,用以隐藏委托关系。

移除中间人-Remove Middle Man

某个类作了过多的简单委托动做。这个时候能够考虑让客户直接调用受托类。

引入外加函数-Introduce Foreign Method

你须要位提供服务的类增长一个函数,但你没法修改这个类时。

能够在客户类中创建一个函数,并以第一参数形式传入一个服务类实例。

$newStart = new Date(PreviousEnd->getYear(), PreviousEnd->getMonth(), PreviousEnd->getDate() + 1);

/** R **/

$newStart = nextDay(PreviousEnd);

function nextDay($date){
    return new Date($date->getYear(), $date->getMonth(), $date->getDate() + 1);
}

引入本地扩展-Introduce Local Extension

你须要为服务类提供一些额外函数,但你没法修改这个类。

那么就新建一个类,使它包含这些额外函数。让这个扩展类称为源类的子类或者包装类。

本地扩展的两种方式:

  1. 就是经过继承-构建子类来做出对源类的扩展。

  2. 经过构建包装类:将源类经过构造函数传入包装类,包装类对源类的每个函数都进行再处理,经过包装类调用源类。

从新组织数据

经过对象来表示数据类型,即Replace Value with Object,即经过函数访问每个数据。

把数组变成对象,能够更好的展露数组的数据结构。

自封装字段-Self Encapsulate Field

private $_low, $_high;

function includes($arg){
    return $arg >= self::$_low && $arg <= self::$_high;
}

/** R **/

private $_low, $_high;

function includes($arg){
    return $arg >= getLow() && $arg <= getHigh();
}

function getLow(){
    return self::$_low;
}

function getHigh(){
    return self::$_high;
}

以对象取代数据值-Replace Data Value with Object

动机:开发初期,每每决定以简单的数据表示简单的状况。可是随着开发深刻,发现简单数据项也须要一些其它的概念或特殊行为。此时就能够把数据值抽象出来,变成一个可操做的对象。

将值对象改成引用对象-Change Value to Reference

当你从一个类衍生出许多彼此相等的实例时,但愿将他们替换为同一个对象进行操做

那么就将这个值对象变成引用对象。这样来保证全部操做的实物是同一个实物(每每是真实世界中同一个物体)。

将引用对象改成值对象-Change Reference to Value

在分布式系统和并发系统中,不可变的值对象特别有用。由于你无需考虑他们的同步问题。

值对象自己应有一个特性:他们是不可变的。若是保证了这一点,就能够以多个对象表示同一个事物。若是是可变的,则考虑使用引用对象。

以对象取代数组-Replace Array with Object

复制‘被监视数据’-Duplicate Observed Data

view层数据和controller逻辑数据是须要拆分出来的。若是两层系统使用了一样的数据,那么view层能够经过观察者模式(Observer/Observable模式)来得到领域类的数据。

也可使用事件监听器来取代观察者模型,每当领域对象发生变化,就向监听器发送一个事件。view层系统在适当时候调用update。

双向关联 & 单向关联

使用字面常量

封装字段

若是类中存在public字段,则将它声明为private,并提供相应的访问函数。

以类和子类取代类型码(Type Code)

参考

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

相关文章
相关标签/搜索