目錄
10.Switch Statements(switch驚悚現身)
11.Parallel Inheritance Hierarchies(平等繼承體系)
13.Speculative Generality(誇誇其談未來性)
17.Inappropriate Intimacy(狎暱關係)
18.Alternative Classes with Different Interfaces(異曲同工的類)
19.Incomplete Library Class(不完美的程序類庫)
1.Duplicated Code(重複的代碼)
假設你在一個以上的地點看到同樣的程序結構,那麼當可肯定:設法將它們合而爲一,程序會變得更好。
2.Long Method(過長方法)
針對過長的方法,我們需要進行分解,我們遵循這樣一條原則:每當感覺須要寫註釋來說明代碼的時候。我們就把須要說明的
東西寫進一個獨立的方法中,並以其意圖(而非實現手法)命名。我們可以對一組甚至短短一行代碼做這件事。哪怕替換後的方法
調用動作比方法自身還長,只要函數名稱能夠解釋其用途,我們就應該毫不猶豫地那麼做。關鍵不在於函數的長度,而在於函
數"做什麼"和"如何做"之間的語義距離。
3.Large Class(過大的類)
說明這個類做太多事情。其內往往就會出現太多instance變量。一旦如此。Duplicated Code也就接踵而至了。
和"太多實例變量"一樣,類內如果有太多代碼,也是代碼重複、混亂並最終走向死亡的源頭。最簡單的解決方案是把多餘的東
西消彌於類內部。如果有五個"百行函數",它們之中很多代碼都相同,那麼或許你可以把它們變成五個"十行函數"和十個提煉
出來的"雙行函數";還可以先確定客戶端如何使用它們,運用抽象接口爲每一種使用方式提煉一個接口。
4.Long Parameter List(過長參數列)
當一個方法有太長的參數時,會使得該參數列難以理解,太多參數會造成前後不一致、不易使用。可以將來自同一個對象的一
堆數據收集起來,並以該對象替換他們。如果某些數據缺乏合理的對象歸屬,可以製造一個對象參數。
5.Divergent Change(發散式變化)
我們希望軟件可以更容易被改動——畢竟軟件再怎麼說本來就該是[軟]的。一旦須要改動,我們希望可以找到系統的某一點,僅
僅在該處做改動。Divergent Change是指[一個class受多種變化的影響]。如果某個類經常因爲不同的原因在不同的方向上發
生變化,那麼此時將對象分成多個會更好,這麼一來每個對象就可以只因一種變化而需要修改。
6.Shotgun Surgery(霰彈式修改)
Shotgun Surgery類似Divergent Change。但恰恰相反。假設每遇到某種變化,你都必須在很多不同的class內做出很多小改動
以響應之。你所面臨的壞味道就是Shotgun Surgery。假設須要改動的代碼散佈四處。你不但非常難找到它們。也非常容易忘記
某個重要的改動。這種情況下你應該把所有需要修改的代碼放進同一個類,如果眼下沒有合適的類可以安置這些代碼,就創造
一個。
Shotgun Surgery是指[一種變化引發多個classes對應改動]。
7.Feature Envy(依戀情結)
我們會看到某個方法爲了計算某值,從另一個對象那兒調用差點兒一半以上取值方法。這樣最好是將當前對象的方法移動至另
外一個對象,如果一個方法調用了多個類的多個功能,那麼它究竟該被置於何處呢?我們的原則是:判斷那一個類擁有最多調
用方法,然後就把這個函數和那些數據擺在一起。
最根本的原則是:將總是一起變化的東西放在一塊兒。[數據和[引用這些數據]的行爲總是一起變化的。
8.Data Clumps(數據泥團)
數據項就像小孩子,喜歡成羣結隊地待在一塊兒。你經常能夠在非常多地方看到同樣的三或四個數據項:兩個類中相同的
字段、很多方法簽名中相同的參數。這些總是綁在一起出現的數據真應該放進屬於它們自己的對象中。
9.Primitive Obsession(基本類型偏執)
大多數編程環境都有兩種數據:結構類型讓你將數據組織成有意義的形式;基本類型則是構成結構型別的積木塊。
10.Switch Statements(switch驚悚現身)
面向對象程序的一個最明顯特徵就是:少用switch(或case)語句。從本質上說,switch語句的問題在於重複。大多數時候,一看
到switch語句,就應該考慮以多態來替換它,可以將switch語句提煉到一個獨立函數中,再將它搬移到需要多態性的那個類
裏。
11.Parallel Inheritance Hierarchies(平等繼承體系)
Parallel Inheritance Hierarchies事實上是Shotgun Surgery的特殊情況。在這樣的情況下。每當你爲某個class添加一個
subclass,必須也爲其它已實現的兄弟class對應添加一個subclass。消除這種重複性的一般策略是:讓一個繼承體系的實例引
用另一個繼承體系的實例。
12.Lazy Class(冗贅類)
你所創建的每個class,都得有人去理解它、維護它,這些工作都是要花錢的。假設一個class的所得不值其身份。它就應該消
失。
13.Speculative Generality(誇誇其談未來性)
這個令我們十分敏感的壞味道,命名者是Brian Foote。當有人說“噢,我想我們總有一天須要做這事”並因而企圖以各式各樣的
掛勾和特殊情況來處理一些非必要的事情,這樣的壞味道就出現了。
14.Temporary Field(令人迷惑的臨時字段)
有時你會看到這種對象:其內某個 instance 變量僅爲某種特定情勢而設。這種代碼讓人不易理解,由於你通常覺得對象在全部
時候都須要它的全部變量。在變量未被使用的情況下推測當初其設置目的,會讓你發瘋。可以單獨抽出一個類來存儲這些
instance 變量和這個變量相關的代碼。
15.Message Chains(過度耦合的消息鏈)
假設你看到用戶向一個對象索求還有一個對象,然後再向後者索求還有一個對象,然後再索求還有一個對象……這就是
Message Chain。實際代碼中你看到的可能是一長串getThis()或一長串暫時變量。採取這樣的方式,意味客戶將與查找過程中
的航行結構緊密耦合。針對這種情況可以先觀察消息鏈最終得到的對象是用來幹什麼的,看看是否可以把使用該對象的代碼提
煉到一個方法,再把這個方法推入消息鏈。如果這條鏈上的某個對象有多位客戶打算航行此航線的剩餘部分,就加一個函數來
做這件事。
16.Middle Man(中間轉手人)
人們可能過度運用delegation。你或許會看到某個class接口有一半的方法都託付給其他class,這樣就可能是過度運用。這時應
該讓方法和真正負責的對象打交道。
17.Inappropriate Intimacy(狎暱關係)
有時候你會看到兩個classes過於親熱,花費太多時間去探究彼此的private成分。假設這發生在兩個人之間。我們不必做衛道
之士;但對於classes,我們希望它們嚴守清規。繼承往往造成過度親熱,由於subclass對superclass的瞭解總是超過
superclass的主觀願望。假設你認爲該讓這個孩子獨自生活了,請運用Replace Inheritance with Delegation讓它離開繼承體
系。
18.Alternative Classes with Different Interfaces(異曲同工的類)
假設兩個方法做同一件事,卻有着不同的簽名式,針對這種case應該根據他們的用途重新命名。
19.Incomplete Library Class(不完美的程序類庫)
20.Data Class(純稚的數據類)
所謂Data Class是指:它們擁有一些字段,以及用於訪問這些字段的方法,除此之外一無長物。
21.Refused Bequest(被拒絕的遺贈)
Subclasses應該繼承superclass的方法和數據。但假設它們不想或不須要繼承,又該怎麼辦呢?它們得到全部禮物。卻僅僅從
中挑選幾樣來玩!按傳統說法,這就意味繼承體系設計錯誤。
22.Comments(過多的註釋)
別操心,我們並非說你不該寫註釋。從嗅覺上說,Comments不是一種壞味道;其實它們還是一種香味呢。我們之所以要在這
裏提到Comments,由於人們常把它當作除臭劑來使用。經常會有這種情況:你看到一段代碼有着長長的註釋。然後發現,這
些註釋之所以存在乃是由於代碼非常糟糕。這種情況的發生次數之多。實在令人驚訝。Comments能夠帶我們找到本章先前提
到的各種壞味道。