PHP 雜談《重構(gòu)-改善既有代碼的設(shè)計(jì)》之一 重新組織你的函數(shù)
思維導(dǎo)圖 點(diǎn)擊下圖,可以看大圖。 
介紹
我把我比較喜歡的和比較關(guān)注的地方寫(xiě)下來(lái)和大家分享。上次我寫(xiě)了篇《php 跟老大的對(duì)話》。還是有很多疑問(wèn),這書(shū)幫了我不少的忙。
如果你比較繁忙,或者懶得看文字,建議你直接看截圖,也會(huì)有很大的收獲的。你可以通過(guò)比較截圖中的代碼就能知道孰優(yōu)孰劣了。
代碼部分我為什么用圖呢?因?yàn)槲医?jīng)常用手機(jī)看代碼,博客園的代碼在手機(jī)里亂七八糟的,還是看圖比較舒服。
專(zhuān)業(yè)術(shù)語(yǔ)
我們畢竟是用英文字母編碼,所以用一些英語(yǔ)單詞,更能顯示出我們的專(zhuān)業(yè)性。以下的英文單詞,你如果掌握了,與其他coder交流的時(shí)候會(huì)更直接,更專(zhuān)業(yè)?!麸@擺一下吧,呵呵。
“*”表示文中經(jīng)常提到的
inline:內(nèi)聯(lián)
function:函數(shù)
*method:方法
finely grained:細(xì)粒度的
rename:重命名
query:查詢(xún)
temp:臨時(shí)(temporary)——一般指臨時(shí)變量
*extract:提取——我個(gè)人更喜歡翻譯成“提煉”
*duplicate:復(fù)制
split:剖解
variable:變量
factor:因素,因子
重構(gòu)原則
一、何謂重構(gòu)?
名詞形式:對(duì)軟件內(nèi)部結(jié)構(gòu)的一種調(diào)整,目的是在不改變軟件之可察行為前提下,提高其可理解型性,降低其修改成本。
動(dòng)詞形式:使用一系列重構(gòu)準(zhǔn)則,在不改變軟件之可察行為前提下,調(diào)整其結(jié)構(gòu)。
二、為何重構(gòu) ?
1、經(jīng)常重構(gòu)可以讓代碼維持該有的形態(tài)。
2、讓代碼找到合適的位置。
3、讓軟件更易理解。
4、可以找到bug。
5、提高我們的編碼速度。
三、重構(gòu)的難題
1、修改接口命名
如果你的類(lèi)中的方法是public,那么你在rename的時(shí)候,冒著很大的風(fēng)險(xiǎn),你不知道到底有哪些模塊在調(diào)用你的這個(gè)方法(我們經(jīng)常的做法是在整個(gè)項(xiàng)目下做grep操作,然后逐一看各個(gè)模塊的調(diào)用和邏輯)?!晕覀?cè)诰帉?xiě)類(lèi)的時(shí)候不管是屬性還是方法盡量做到private,避免接口開(kāi)放。
2、何時(shí)不該重構(gòu)
?。?)重寫(xiě)所有代碼,而且現(xiàn)有代碼實(shí)在太混亂,重構(gòu)還不如重寫(xiě)。
?。?)項(xiàng)目臨近結(jié)束的時(shí)候,應(yīng)該避免重構(gòu)。我們可以把重構(gòu)放到二期去解決。
代碼的壞味道
一、Duplicate Code
1、同一個(gè)類(lèi),兩個(gè)方法含有相同表達(dá)式。
解決方法:你可以Extract Method提煉重復(fù)代碼,然后讓這兩個(gè)方法都調(diào)用這個(gè)Extract Method。
2、兩個(gè)類(lèi),有相似的方法。
解決方法:(1)把兩個(gè)類(lèi)的方法提出來(lái),共同構(gòu)造一個(gè)父類(lèi)。
(2)把其中一個(gè)類(lèi)的方法刪除,調(diào)用另一個(gè)類(lèi)的方法。
二、Long Method
1、短函數(shù):代碼閱讀費(fèi)點(diǎn)力氣,因?yàn)槲覀儽仨毥?jīng)常轉(zhuǎn)換上下文去看看子程序做了什么。但是讓small method容易理解的真正關(guān)鍵在于一個(gè)好的名字。讀者可以通過(guò)名字了解函數(shù)的作用,根本不必去看其中寫(xiě)了些什么?!缙诘木幊陶Z(yǔ)言中,調(diào)用方法需要額外開(kāi)銷(xiāo),這使得coder不愿意使用small method。但是現(xiàn)代的OO語(yǔ)言幾乎已經(jīng)完全免除了process內(nèi)的額外開(kāi)銷(xiāo)(函數(shù)調(diào)用)。
2、注釋地方提煉信號(hào):每當(dāng)感覺(jué)需要以注釋來(lái)說(shuō)明點(diǎn)什么的時(shí)候,我們就把需要說(shuō)明的東西寫(xiě)進(jìn)一個(gè)獨(dú)立函數(shù)中,并以其用途命名。可以對(duì)一組或甚至短短一行代碼做這件事?!灰瘮?shù)名稱(chēng)能夠解釋其用戶(hù),我們也該毫不猶豫地那么做。
"函數(shù)"理解為”做什么“或”如何做“
3、條件式和循環(huán)常常也是提煉信號(hào)。
4、《代碼整潔之道》的一個(gè)例子。我們可以想想!

三、Large Class
1、Class內(nèi)數(shù)個(gè)屬性變量有相同前綴或者字尾,可使用Extract Class。
2、Class內(nèi)并非大多數(shù)變量使用屬性變量,可使用Extract Class。
3、有太多代碼,可Extract Class。
四、Long Parameter
做成Introduce Parameter Object?!@個(gè)我不太贊同,因?yàn)槲以谑褂脛e人方法的時(shí)候,我很少去看代碼實(shí)踐,更不要說(shuō)去看里面都用到了對(duì)象的那些屬性或者方法,取我想要的數(shù)據(jù)了。
五、Switch Statements
1、少用switch語(yǔ)句?!獑?wèn)題在于duplication。添加新case的時(shí)候,你必須找到所有case并修改它們。
2、用多態(tài)來(lái)替換它。做法:1.將switch進(jìn)行Extract Method;2.MoveMethod把case里的實(shí)踐代碼放到多態(tài)性的class里。
六、 Comments
試試用Extract Method,如果還不行,那你試試Rename Method。
當(dāng)你感覺(jué)需要撰寫(xiě)注釋?zhuān)?qǐng)先嘗試重構(gòu),試著讓所有注釋變得多余。
注釋一般用于將來(lái)的打算,還可以用于你并無(wú)十足把握的區(qū)域(為什么做某事)。
重新組織你的函數(shù)
Long Method往往包含太多信息,這些信息又被錯(cuò)綜復(fù)雜的邏輯掩蓋,不易鑒別。
一、Extract Method



動(dòng)機(jī):
簡(jiǎn)短而有良好命名的函數(shù):——finely grained
1、復(fù)用機(jī)會(huì)大。
2、函數(shù)讀起來(lái)像讀一系列comments。
3、函數(shù)覆寫(xiě)容易。
重點(diǎn):函數(shù)長(zhǎng)度關(guān)鍵在于函數(shù)名稱(chēng)和函數(shù)本體之間的語(yǔ)義距離。如果提煉動(dòng)作可以強(qiáng)化代碼的清晰度,那么就去做。
作法:
1、創(chuàng)建新函數(shù),根據(jù)函數(shù)的意圖命名——以它“做什么”命名,而不是以它“怎樣做”命名。
=》 即使Extract Function 非常簡(jiǎn)單,例如只是消息或函數(shù)調(diào)用,只要新Function能夠以更好方式昭示代碼意圖,你也應(yīng)該提煉它。但如果你想不出更有意義的名稱(chēng),就別動(dòng)它。
2、將Extract的代碼從Source Function 中Move到New Function中。
二、Inline Method
Method Body與Method Name一樣清晰易懂的時(shí)候,請(qǐng)Inline Method。



三、Inline Temp
一個(gè)臨時(shí)變量,只被一個(gè)簡(jiǎn)單表達(dá)式賦值一次,而且賦值完也只使用了一次?!?qǐng)Inline Temp



四、Replace Temp with Query
如果一個(gè)Temp變量,保存一個(gè)表達(dá)式,將這個(gè)表達(dá)式Extract Method?!@就是所謂的查詢(xún)式,query



動(dòng)機(jī):
1、局部變量會(huì)使代碼難以提煉。
2、臨時(shí)變量會(huì)驅(qū)使你寫(xiě)出更長(zhǎng)的代碼。如果改成query method,那么class下的method,都可以獲得這份信息?!獙⒕帉?xiě)出更清晰的代碼。
3、Replace Temp with Query往往是你運(yùn)用Extract Method之前必不可少的步驟。
作法:
1、找出只被賦值一次的臨時(shí)變量。
=> 如果臨時(shí)變量賦值超過(guò)一次,考慮使用Split Temporary Variable將它分割成多個(gè)變量。
2、對(duì)Temp Variable賦值的右側(cè)部分,Extract到一個(gè)獨(dú)立函數(shù)中。
=> 將Method聲明為private,日后如果有其他class用的時(shí)候再放開(kāi)它(public或protected)。






動(dòng)機(jī):
1、如果臨時(shí)變量承擔(dān)多個(gè)責(zé)任,它就應(yīng)該被替換為多個(gè)臨時(shí)變量。每個(gè)變量只承擔(dān)一個(gè)責(zé)任。
2、同一個(gè)臨時(shí)變量承擔(dān)兩件不同的事情,會(huì)令review變得糊涂。



七、Replace Method with Method Object
大型函數(shù)對(duì)局部變量的使用無(wú)法采用Extract Method。那么將這個(gè)Method放進(jìn)一個(gè)單獨(dú)對(duì)象中,如此一來(lái),讓局部變量成為對(duì)象的filed,然后在同一個(gè)對(duì)象中將大型函數(shù)分解為數(shù)個(gè)小型Method。



動(dòng)機(jī):
1、將相對(duì)獨(dú)立的代碼從大型Method中Extract出來(lái),就可以大大提高代碼的可讀性。
2、一個(gè)Method中,局部變量泛濫成災(zāi),分解這個(gè)函數(shù)將會(huì)非常困難。
3、Replace Method with Method Object 會(huì)將所有局部變量變成對(duì)象的值域。然后對(duì)這個(gè)新對(duì)象進(jìn)行Extract Method了。
總結(jié)
這只是本書(shū)的一部分內(nèi)容,我知道會(huì)有很多的coder應(yīng)該有不同的觀點(diǎn),我自己也是,有的很贊同,有的我也是不太贊同的。所以要“則其善之而從之,其不善之而改之”。
歡迎大家發(fā)表下自己的看法。
- 五款PHP代碼重構(gòu)工具推薦
- PHP代碼維護(hù),重構(gòu)變困難的4種原因分析
- PHP 雜談《重構(gòu)-改善既有代碼的設(shè)計(jì)》之五 簡(jiǎn)化函數(shù)調(diào)用
- PHP 雜談《重構(gòu)-改善既有代碼的設(shè)計(jì)》之四 簡(jiǎn)化條件表達(dá)式
- PHP 雜談《重構(gòu)-改善既有代碼的設(shè)計(jì)》之三 重新組織數(shù)據(jù)
- PHP 雜談《重構(gòu)-改善既有代碼的設(shè)計(jì)》之二 對(duì)象之間搬移特性
- rephactor 優(yōu)秀的PHP的重構(gòu)工具
- PHP代碼重構(gòu)方法漫談
相關(guān)文章
php動(dòng)態(tài)添加url查詢(xún)參數(shù)的方法
這篇文章主要介紹了php動(dòng)態(tài)添加url查詢(xún)參數(shù)的方法,涉及php通過(guò)正則替換操作URL的技巧,具有一定參考借鑒價(jià)值,需要的朋友可以參考下2015-04-04
php實(shí)現(xiàn)動(dòng)態(tài)口令認(rèn)證的示例代碼
這篇文章主要為大家詳細(xì)介紹了php實(shí)現(xiàn)動(dòng)態(tài)口令認(rèn)證的相關(guān)知識(shí),文中的示例代碼講解詳細(xì),感興趣的小伙伴可以跟隨小編一起學(xué)習(xí)一下2024-02-02
淺析PHP中Collection 類(lèi)的設(shè)計(jì)
本篇文章是對(duì)PHP中Collection 類(lèi)進(jìn)行了詳細(xì)的分析介紹,需要的朋友參考下2013-06-06
PHP依賴(lài)注入(DI)和控制反轉(zhuǎn)(IoC)詳解
這篇文章主要介紹了PHP依賴(lài)注入(DI)和控制反轉(zhuǎn)(IoC)的相關(guān)資料,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2017-06-06
淺談php處理后端&接口訪問(wèn)超時(shí)的解決方法
下面小編就為大家?guī)?lái)一篇淺談php處理后端&接口訪問(wèn)超時(shí)的解決方法。小編覺(jué)得挺不錯(cuò)的,現(xiàn)在就分享給大家,也給大家做個(gè)參考。一起跟隨小編過(guò)來(lái)看看吧2016-10-10
PHP+redis實(shí)現(xiàn)的悲觀鎖機(jī)制示例
這篇文章主要介紹了PHP+redis實(shí)現(xiàn)的悲觀鎖機(jī)制,簡(jiǎn)單介紹了redis鎖機(jī)制與樂(lè)觀鎖、悲觀鎖等概念,并結(jié)合實(shí)例形式分析了php+redis實(shí)現(xiàn)悲觀鎖相關(guān)操作技巧,需要的朋友可以參考下2018-06-06
PHP使用swoole編寫(xiě)簡(jiǎn)單的echo服務(wù)器示例
這篇文章主要介紹了PHP使用swoole編寫(xiě)簡(jiǎn)單的echo服務(wù)器,結(jié)合實(shí)例形式分析了基于swoole的echo服務(wù)器客戶(hù)端與服務(wù)器端相關(guān)實(shí)現(xiàn)技巧及操作注意事項(xiàng),需要的朋友可以參考下2020-03-03

