重構方法數組
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
方法。分佈式
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
$basePrice = AnOrder->basePrice(); return $basePrice > 1000; /** R **/ return AnOrder->basePrice() > 1000;
動機:Inline Temp多半是做爲
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
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
拒絕臨時變量的屢次賦值,致使不一樣位置而具備不一樣意義。server
function discount($inputVal, $quantity, $yearToDate){ if($inputVal > 50){ $inputVal -= 2; } } /** R **/ function discount($inputVal, $quantity, $yearToDate){ $result = $inputVal; if($inputVal > 50){ $result -= 2; } }
拒絕對參數賦值,保持對參數入出不變。
若是一個函數過大(問題函數),考慮新建一個類來代替這個問題函數。
若是一個類與另外一個類有太多合做而造成高度耦合,則須要搬移函數,構建新類。
同理上面的方法。
若是某個類作了兩個類作的事情,考慮新建一個類來處理。
若是某個類沒有作太多事情,能夠將這個類的特性搬移到另外一個類中,移除原類。
客戶經過一個委託類來調用另外一個對象。在服務類上創建客戶所需的全部函數,用以隱藏委託關係。
某個類作了過多的簡單委託動做。這個時候能夠考慮讓客戶直接調用受託類。
你須要位提供服務的類增長一個函數,但你沒法修改這個類時。
能夠在客戶類中創建一個函數,並以第一參數形式傳入一個服務類實例。
$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); }
你須要爲服務類提供一些額外函數,但你沒法修改這個類。
那麼就新建一個類,使它包含這些額外函數。讓這個擴展類稱爲源類的子類或者包裝類。
本地擴展的兩種方式:
就是經過繼承
-構建子類來做出對源類的擴展。
經過構建包裝類:將源類經過構造函數傳入包裝類,包裝類對源類的每個函數都進行再處理,經過包裝類調用源類。
經過對象來表示數據類型,即Replace Value with Object
,即經過函數訪問每個數據。
把數組變成對象,能夠更好的展露數組的數據結構。
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; }
動機:開發初期,每每決定以簡單的數據表示簡單的狀況。可是隨着開發深刻,發現簡單數據項也須要一些其它的概念或特殊行爲。此時就能夠把數據值抽象出來,變成一個可操做的對象。
當你從一個類衍生出許多彼此相等的實例時,但願將他們替換爲同一個對象進行操做
那麼就將這個值對象變成引用對象。這樣來保證全部操做的實物是同一個實物(每每是真實世界中同一個物體)。
在分佈式系統和併發系統中,不可變的值對象特別有用。由於你無需考慮他們的同步問題。
值對象自己應有一個特性:他們是不可變的。若是保證了這一點,就能夠以多個對象表示同一個事物。若是是可變的,則考慮使用引用對象。
view層數據和controller邏輯數據是須要拆分出來的。若是兩層系統使用了一樣的數據,那麼view層能夠經過觀察者模式(Observer/Observable模式)
來得到領域類的數據。
也可使用事件監聽器
來取代觀察者模型,每當領域對象發生變化,就向監聽器發送一個事件。view層系統在適當時候調用update。
若是類中存在public字段,則將它聲明爲private,並提供相應的訪問函數。
參考
重構-改善既有代碼的設計