《重構(gòu)》第三章學習筆記
我們必須培養(yǎng)自己的判斷力,來決定在什么時候進行重構(gòu)。
1.1 Duplicate Code(重復代碼)
如果你在一個以上地點看到相同的程序結(jié)構(gòu),那么將他們合而為一會更好。
1.2 Long Method(過長函數(shù))
擁有短函數(shù)的對象會活得比較好,比較長。
間接層所能帶來的全部益處:解釋能力(可讀性),共享能力(重用性),選擇能力(?)。
現(xiàn)在OO 語言基本解決了函數(shù)調(diào)用所產(chǎn)生的開銷。
“ 你應該更積極進去的分解函數(shù)。我們遵循這樣一條原則:每當感覺需要以注釋來說明點什么的時候,我們就把需要說明的東西寫進一個函數(shù)中,并以其用途(而非實現(xiàn)手法)命名。我們可以對一組甚至短短一行代碼(擁有復雜邏輯,難以理解)做這件事。哪怕替換后的函數(shù)調(diào)用動作比函數(shù)自身還長,只要函數(shù)名稱能夠解釋其用途,我們也該毫不猶豫的這么做。關(guān)鍵不在于函數(shù)的長度,而在于“做什么”和“如何做”之間的語義距離。 ”
“如何確定該提煉哪一段代碼?一個很好的技巧是:尋找注釋。它們通常是指出“代碼用途和實現(xiàn)手法間的語義距離”的信號。如果代碼需要用注釋來說明其用途,那么就要考慮把這段代碼提煉成獨立的函數(shù),并且用注釋來為此函數(shù)命名?!?
復雜條件式和循環(huán)液常常是提煉的信號。
1.3 Large Class(過大類)
如果想利用單一的class 做太多的事情,其內(nèi)往往會出現(xiàn)太多的 instance 變量。
如果class 中擁有太多的代碼,也是“代碼重復、混亂、死亡”的絕佳滋生點。
1.4 Long Parameter List(過長的參數(shù)列表)
過長的產(chǎn)生導致程序難以理解。
1.5 Divergent Change(發(fā)散式變化)
“ 一個class 受多個外界變化的影響 ”,則把這多個變化封裝成一個新的類。即“ 將總是一起變化的東西放在一起 ”
針對外界某一變化所有相應的修改,都應該只發(fā)生在單一的class 中,而這個 class 的所有內(nèi)容都應該反映該外界變化??偟乃枷刖褪?,封裝變化。這個地方和設(shè)計模式的想法是一致的。
1.6 Shotgun Surgery(散彈式修改)
和發(fā)散式變化不同,每次遇到變化,都要在多個class 中進行小的修改以響應之。他們分散在多處,很容易出錯。
這里的主要思想是集中變化。
散彈式修改指的是,“ 一種變化引發(fā)多個class 的修改 ”,發(fā)散式變化指的是“ 一個class 受多個外界變化的影響 ”。
這兩種情況下,通過重構(gòu), 使“外界變化”和“待修改類”呈一對一關(guān)系 的理想境地。
1.7 Feature Envy(依戀情節(jié))
某個函數(shù)對其他類的數(shù)據(jù)的興趣,高過對host class 的興趣。即對其他的類的數(shù)據(jù)的依賴十分大。
1.8 Data Clumps(數(shù)據(jù)泥團)
數(shù)據(jù)泥團指的是總是綁定在一起出現(xiàn)的數(shù)據(jù)。
一個好的評斷方法:刪除眾多數(shù)據(jù)中的一項數(shù)據(jù),其他數(shù)據(jù)是否是因而失去了意義?如果他們不再有意義:你應該為他們產(chǎn)生一個新的對象。
形成新的對象后,可以根據(jù)Feature Envy 將一些操作移至此對象中。
1.9 Primitive Obsession(基本型別偏執(zhí))
建立多個很小,但是很靈活的對象。
1.10 Switch Statements( switch 驚悚現(xiàn)身)
使用面向?qū)ο缶幊?,要少用switch 和 case 語句。而是用多態(tài)來替換它。
1.11 Parallel Inheritance Hierarchies(平行繼承體系)
每當你為一個class 增加一個 subclass 的時候,必須為另一個 class 增加一個 subclass 。一般這兩個 class 的前綴相同。
1.12 Lazy Class(冗贅類)
類顯得多余,沒有價值。
1.13 Speculative Generality(夸夸其談未來性)
這個往往是過度設(shè)計的結(jié)果:對某種變化的應對,而這種變化沒有發(fā)生。
1.14 Temporary Field(令人迷惑的暫時值域)
變量只在特定的情形下有效,而并不是所有的情況下有效。很多情況下,這些值域應該不屬于此class ,而應該單獨的提取成新的類。
1.15 Message Chains(過度耦合的消息鏈)
用戶向一個對象索取另一個對象,然后在向后者索求另一個對象,然后在索求另一個對象——客戶與查找過程的航行結(jié)構(gòu)緊密耦合。
1.16 Middle Man(中間轉(zhuǎn)手人)
對象的基本特征之一就是封裝——對外部世界隱藏實現(xiàn)細節(jié)——封裝往往伴隨委托。委托的過度運行,就導致了Middle Man 。
1.17 Inappropriate Intimacy (親密關(guān)系)
兩個class 之間的關(guān)系過于親密。比如,花大量的時間探究彼此的 private 成分。
1.18 Alternative Classes with Different Interface(異曲同工的類)
類名不同,但是功能相似。
1.19 Incomplete Library Class(不完美的程序類庫)
基礎(chǔ)類庫無法滿足實際的需求。
1.20 Data Class(純稚的數(shù)據(jù)類)
它們擁有一些值域,以及用于訪問(讀寫)這些值域的函數(shù),除此之外一無長物。
1.21 Refused Bequest(被拒絕的遺贈)
子類不像繼承父類的函數(shù)和數(shù)據(jù),這往往是繼承體系的錯誤。
如果子類復用父類的行為,但又不愿支持父類的接口,這種情況下Refused Bequest 的壞味道會很強烈。
1.22 Comments(過多的注釋)
注釋其實是一種香味,更多的情況下它被用作除臭劑:即代碼中出現(xiàn)壞味道(設(shè)計糟糕的代碼),然后用注釋“除臭”。這個時候我們應該對這些壞味道的代碼進行重構(gòu),然后,你會發(fā)現(xiàn)注釋變成了多余的。
當你感覺需要注釋,請先嘗試重構(gòu),試著讓所有的注釋都變得多余——代碼本身就是自注釋的。
注釋可以用來記述“為什么做某事”、“打算做某事”、“無十足把握的區(qū)域”,而不必記錄“怎么做”。
posted @ 2009-10-12 20:15 常高偉 閱讀(793) | 評論 (0) | 編輯 收藏