欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

php設(shè)計(jì)模式介紹之編程慣用法第2/3頁

 更新時(shí)間:2008年04月13日 22:07:20   作者:  
《PHP設(shè)計(jì)模式介紹》第一章 編程慣用法 學(xué)習(xí)一門新的語言意味著要采用新的慣用法。這章將介紹或者可能重新強(qiáng)調(diào)一些慣用法。你會(huì)發(fā)現(xiàn)這些慣用法在你要在代碼中實(shí)現(xiàn)設(shè)計(jì)模式時(shí)候是非常有用的。

重構(gòu)

即使最有思想性且最熟練的程序員也不能預(yù)見一個(gè)軟件項(xiàng)目中的任何細(xì)微之處。問題總是出乎意外的出現(xiàn),需求也可能在變化,結(jié)果是代碼被優(yōu)化,共享然后代替。

重構(gòu)是一個(gè)慣用的方法:檢查你所有的代碼,找出其中能統(tǒng)一化和簡單化的共同或者類似之處,使得你的代碼更加容易維護(hù)和擴(kuò)展。重構(gòu)也包括探索一個(gè)設(shè)計(jì)模式是否能夠應(yīng)用到這個(gè)具體的問題上——這也能使解決方案簡單化。

重構(gòu),簡單點(diǎn)說是重命名一個(gè)屬性或者方法,復(fù)雜點(diǎn)說是壓縮一個(gè)已有的類。改變你的代碼使得它符合一個(gè)或者更多的設(shè)計(jì)模式是另外一種重構(gòu)——讀完這本書后,你可能會(huì)去實(shí)現(xiàn)的。

沒有什么能比例子來更好的解釋重構(gòu)了!

讓我們考慮兩個(gè)簡單的類:CartLine和Cart。CartLine記錄了購物車?yán)锩婷總€(gè)項(xiàng)目的單件價(jià)格和數(shù)量。比如CartLine可能記錄著“四見紅色的polo襯衣,每件19.99$”。Cart 是一個(gè)容器,用來裝載一個(gè)或者更多的CartLine對(duì)象并執(zhí)行一些相關(guān)的計(jì)算工作,比如購物車?yán)锩娴乃猩唐返目偦ㄙM(fèi)。

下面是CartLine和Cart的簡單實(shí)現(xiàn):

// PHP5
class CartLine {
public $price = 0;
public $qty = 0;
}
class Cart {
protected $lines = array();
public function addLine($line) {
$this->lines[] = $line;
}
public function calcTotal() {
$total = 0;
// add totals for each line
foreach($this->lines as $line) {
$total += $line->price * $line->qty;
}
// add sales tax
$total *= 1.07;
return $total;
}
}
重構(gòu)的第一步必須有足夠的測(cè)試來覆蓋你所有的代碼。這樣才能保證你修改的代碼不能產(chǎn)生和你原來代碼不同的結(jié)果。順便提一下,除非你改變了需求(你代碼期望的結(jié)果)或者在測(cè)試實(shí)例中發(fā)現(xiàn)了錯(cuò)誤,你的測(cè)試代碼是是不能改變的。

下面是一個(gè)測(cè)試CartLine和Cart的例子,它在重構(gòu)的過程中是不會(huì)改變的。

function TestCart() {
$line1 = new CartLine;
$line1->price = 12; $line1->qty = 2;
$line2 = new CartLine;
$line2->price = 7.5; $line2->qty = 3;
$line3 = new CartLine;
$line3->price = 8.25; $line3->qty = 1;
$cart = new Cart;
$cart->addLine($line1);
$cart->addLine($line2);
$cart->addLine($line3);
$this->assertEqual(
(12*2 + 7.5*3 + 8.25) * 1.07,
$cart->calcTotal());
}
看著上面的代碼,你可能會(huì)發(fā)現(xiàn)它們有一些“code smells”(代碼臭味)——有著古怪的樣子而且看起來好像是有問題的代碼——它們就像重構(gòu)的候選項(xiàng)。(更多關(guān)于code smells的資料請(qǐng)看http://c2.com/cgi/wiki?codesmell)。兩個(gè)最直接的重構(gòu)候選者是注釋和計(jì)算(與銷售稅等相關(guān)的計(jì)算)。重構(gòu)的一種形式:析取函數(shù)(Extract Method)將把這些難看的代碼從cart::calcTotal()中提取出來,然后用一個(gè)合適的方法來替代它,從而使得代碼更加簡潔。

比如,你可以增加兩個(gè)計(jì)算方法:lineTotal()和calcSalesTax():

protected function lineTotal($line) {
return $line->price * $line->qty;
}
protected function calcSalesTax($amount) {
return $amount * 0.07;
}
現(xiàn)在你可以重寫calcTotal()函數(shù):

public function calcTotal() {
$total = 0;
foreach($this->lines as $line) {
$total += $this->lineTotal($line);
}
$total += $this->calcSalesTax($total);
return $total;
}
到目前為止的改動(dòng)都是有意義的(至少在這個(gè)例子的上下文中),它對(duì)于再次暫停和運(yùn)行這些代碼來驗(yàn)證結(jié)果依然正確是很有幫助的。記得,一個(gè)綠色的成功條的顯示出來了?。ㄗg者注:本章開始時(shí),作者提及到:綠色的條意味著測(cè)試都通過了。)

然而,目前的代碼依然有一些可以挑剔的地方。其中一個(gè)就是在新方法lineTotal()中存取公共屬性。很明顯計(jì)算每行的之和的責(zé)任不應(yīng)該屬于Cart類,而應(yīng)該在類CartLine里面實(shí)現(xiàn)。

再次重構(gòu),在CartLine中增加一個(gè)新的方法total()用來計(jì)算訂單里面的每個(gè)項(xiàng)目的長期價(jià)錢。

public function total() {
return $this->price * $this->qty;
}
然后從類Cart中移除方法lineTotal(),并改變calcTotal()方法來使用新的cartLine::Total()方法。重新運(yùn)行這個(gè)測(cè)試,你依然會(huì)發(fā)現(xiàn)結(jié)果是綠色條。

全新重構(gòu)后的代碼就是這樣:

class CartLine {
public $price = 0;
public $qty = 0;
public function total() {
return $this->price * $this->qty;
}
}
class Cart {
protected $lines = array();
public function addLine($line) {
$this->lines[] = $line;
}
public function calcTotal() {
$total = 0;
foreach($this->lines as $line) {
$total += $line->total();
}
$total += $this->calcSalesTax($total);
return $total;
}
protected function calcSalesTax($amount) {
return $amount * 0.07;
}
}
現(xiàn)在這代碼不再需要每行注釋了,因?yàn)榇a本身更好的說明了每行的功能。這些新的方法,更好的封裝了計(jì)算這個(gè)功能,也更加容易適應(yīng)將來的變化。(比如說,考慮不同大的銷售稅率)。另外,這些類也更加平衡,更容易維護(hù)。

這個(gè)例子顯然是微不足道的,但是希望你能從中推斷并預(yù)想出如何重構(gòu)你自己的代碼。

在編碼的時(shí)候,你應(yīng)該有出于兩種模式中的一種:增加新的特征或者重構(gòu)代碼。當(dāng)在增加特征的時(shí)候,你要寫測(cè)試和增加代碼。在重構(gòu)的時(shí)候,你要改變你原有的代碼,并確保所有相關(guān)的測(cè)試依然能正確運(yùn)行。

關(guān)于重構(gòu)的主要參考資料有Martin Fowler著作的《重構(gòu):改進(jìn)原有代碼的設(shè)計(jì)》(Refactoring:Improving the Design of Existing Code)。用一些精簡點(diǎn)來總結(jié)Fowler的書,重構(gòu)的步驟如下所示:

定義需要重構(gòu)的代碼
有覆蓋所有代碼的測(cè)試
小步驟的工作
每步之后都運(yùn)行你的測(cè)試。編碼和測(cè)試都是相當(dāng)重復(fù)的——和編譯型語言相比,解釋型語言,比如PHP是容易很多的。
使用重構(gòu)來使你的代碼有更好的可讀性和可修改性。

相關(guān)文章

最新評(píng)論