重构方法数组
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,并提供相应的访问函数。
参考
重构-改善既有代码的设计