系统重构笔记
2019獨(dú)角獸企業(yè)重金招聘Python工程師標(biāo)準(zhǔn)>>>
重構(gòu)概念
在不改變軟件可觀察行為的前提下,對軟件內(nèi)部結(jié)構(gòu)的一種調(diào)整,提高其可理解性,降低修改成本。
重構(gòu)節(jié)奏
測試、小修改、測試、小修改......正是這種節(jié)奏讓重構(gòu)得以快速安全而安全的前行。
構(gòu)筑測試體系
如果想要重構(gòu),我們必須擁有一個良好的測試環(huán)境。編寫優(yōu)良的測試程序,可以極大的提升編程速度和代碼質(zhì)量,即使不進(jìn)行重構(gòu)也一樣如此。
每當(dāng)我們收到一個bug報告時,請先寫一個單元測試來暴露bug。
測試是一種風(fēng)險驅(qū)動的行為,測試的目的是希望找出現(xiàn)在或未來才可能出現(xiàn)的錯誤。 測試的要訣是:測試你最擔(dān)心出錯的部分。這樣你就能從測試工作中得到最大的利益。
“花費(fèi)合理的時間找出大多數(shù)的bug”好過“窮盡一生抓出所有bug”。
重新組織函數(shù)
-
重復(fù)代碼 重復(fù)代碼應(yīng)該考慮將其提煉到一個獨(dú)立的函數(shù)或類中。
-
過長函數(shù) 當(dāng)我們看見一個過長的函數(shù)或者需要一段注釋才能讓人理解其用途的代碼時,我們就需要將這段代碼放到一個獨(dú)立的函數(shù)中。 一個函數(shù)多長才算合適?在我看來長度不是問題,關(guān)鍵在于函數(shù)名稱和函數(shù)體之間的語義距離。如果提煉可以強(qiáng)化代碼清晰度,那就去做,就算函數(shù)名稱比提煉出來的代碼還要長也無所謂。
-
內(nèi)聯(lián)函數(shù) 有時候會遇到某些函數(shù),其內(nèi)部代碼和函數(shù)名稱同樣清晰易讀,我們就可以去掉這個函數(shù)直接使用其中代碼。
-
內(nèi)聯(lián)臨時變量 如果發(fā)現(xiàn)一個臨時變量只被一個簡單表示式賦值一次,并且妨礙了其他重構(gòu)手法,我們就應(yīng)該讓他內(nèi)聯(lián)化。 直接將變量聲明成final的,可以檢查變量是否真的是被賦值了一次。
-
以查詢來取代臨時變量
-
引入解釋性臨時變量 將復(fù)雜表達(dá)式的結(jié)果放到一個臨時變量,以變量名稱來解釋表達(dá)式用途。
-
分解臨時變量
在對象之間搬移特性
在對象設(shè)計(jì)過程中,決定把“責(zé)任”放在哪里是非常總要的。這曾經(jīng)讓我非常苦惱,但是現(xiàn)在我知道,在這種情況下,可以運(yùn)用重構(gòu),改變原有的設(shè)計(jì)。
-
搬移函數(shù) “搬移函數(shù)”是重構(gòu)理論的支柱。如果一個類有太多行為,如果一個類和另一個類高度耦合,我們就需要搬移函數(shù)。
-
搬移新的字段 隨著系統(tǒng)的發(fā)展,你會發(fā)現(xiàn)自己需要新的類,并將現(xiàn)有的工作拖到新的類中。如果發(fā)現(xiàn)對于一個字段,在其所駐類之外的另一個類中都有更多函數(shù)使用了它,我就會考慮搬移這個字段。
-
提煉類 一個類應(yīng)該是一個清晰的抽象,處理一些明確的責(zé)任。
簡化表達(dá)式
可以將一個復(fù)雜的條件邏輯分解成若干小塊。這樣可以使得分支邏輯和操作細(xì)節(jié)分離。
-
分解條件表達(dá)式 分解表達(dá)式可以突出條件邏輯,更清晰地表明每個分支的作用,并突出每個分支的原因。 做法:將分支語句提煉出來,構(gòu)成一個獨(dú)立的函數(shù)。
-
合并表達(dá)式 有時會發(fā)現(xiàn)一串的表達(dá)式檢查條件各不相同,但最終行為卻一致。如果這樣就需要使用“邏輯與”或“邏輯或”合并表達(dá)式。
-
合并重復(fù)的條件片段 當(dāng)所有分支都會執(zhí)行相同代碼時,就需要將這段代碼搬移到條件表達(dá)式之外了。這樣我們能更加清晰的知道,那些東西是隨著條件變化而變化的、那些是不變的。
-
移除控制標(biāo)記 控制標(biāo)記可以使用break或continue來代替,還可以使用return直接返回。
-
以衛(wèi)語句來取代嵌套表達(dá)式 可以讓代碼邏輯看起來更加的清晰。
-
以多態(tài)來取代條件表達(dá)式 多態(tài)的好處在于:如果你需要根據(jù)對象的不同類型來采取不同的行為,多態(tài)使你不必寫明顯的條件表達(dá)式。
簡化函數(shù)調(diào)用
- 改函數(shù)名 函數(shù)的名稱應(yīng)該準(zhǔn)確的表達(dá)它的用途。給函數(shù)命名有一個好的辦法:首先考慮應(yīng)該給函數(shù)寫上一句這樣的注釋,然后在想辦法將注釋變成函數(shù)名稱。
-
移除參數(shù) 參數(shù)代表著函數(shù)所需的信息,不同的參數(shù)值有不同的意義。如果不去掉多余的參數(shù),就會讓每一位調(diào)用者多費(fèi)一份心。
-
將查詢函數(shù)和修改函數(shù)分離 任何有返回值的函數(shù),都不因該有看到的副作用。
-
引入?yún)?shù)對象 為了縮短參數(shù)列,我們可以使用一個對象來包裝所有的參數(shù)。這樣可以降低理解和修改函數(shù)代碼的難度。
-
以異常來取代錯誤碼 如果調(diào)用者有責(zé)任在調(diào)用前檢查必要狀態(tài),就拋出非受控異常。
處理概括關(guān)系
-
劃分邊界 確定各個字段、方法應(yīng)該處于子類還是超類也是我們經(jīng)常需要注意的一個點(diǎn)。
-
提煉子類、超類和接口
-
折疊繼承體系 有時我們會發(fā)現(xiàn)某個子類并沒有帶來該有的價值時,我們就需要將子類的超類合并。
-
塑造模板函數(shù) 你有一些子類,其中相應(yīng)的某些函數(shù)以相同順序執(zhí)行類似的操作,但是各個操作細(xì)節(jié)上有所不同。將這些操作分別放進(jìn)獨(dú)立函數(shù)中,并保證他們有相同的簽名,于是原函數(shù)也變得相同了,然后將原函數(shù)移至超類。
-
以委托取代繼承 當(dāng)某個子類只使用接口中的一部分,或者不使用繼承而來的數(shù)據(jù)時,我們可以在子類新建一個字段用以保存超類:調(diào)整子類函數(shù),令他改而委托超類;然后去掉兩者間的繼承關(guān)系。
大型重構(gòu)
- 梳理并分解機(jī)場體系
- 將過程化設(shè)計(jì)轉(zhuǎn)化為對象設(shè)計(jì)
- 提煉繼承體系
重構(gòu)要點(diǎn)
參考
《重構(gòu)改善既有代碼設(shè)計(jì)》
為監(jiān)控而生的多級緩存框架 layering-cache這是我開源的一個多級緩存框架的實(shí)現(xiàn),如果有興趣可以看一下
轉(zhuǎn)載于:https://my.oschina.net/u/3748347/blog/2992764
總結(jié)
- 上一篇: Android端IM应用中的@人功能实现
- 下一篇: 系统相关的信息模块: import sy