本節對應原書第 7 章「The Smell Ecosystem」,從「單一壞味道」視角拉到「設計生態系」的整體觀。
設計是一個生態系#
設計是由「設計決策」構成的——而壞味道與設計決策共存於同一個生態系中。
幾個現象:
- 壞味道由設計決策催生——一個或多個決策的組合便足以引入它。
- 壞味道反過來引發新的設計決策(為了修復/規避)。
- 壞味道之間互動:彼此放大、共生、或扮演前導角色。
7.1 脈絡(context)的角色#
「就像吃藥會有副作用——每個設計決策也都帶著好處與代價。好處有時大過代價,有時恰恰相反。」
關鍵問題:同樣的設計決策套到兩個不同設計上,影響會一樣嗎?多半不會——這就是脈絡的力量。
Q1:能不能為了更大目的而有意接受壞味道?#
會。本書幾乎每個壞味道章節的「實務考量」都列出這類例子——例如:
- 為了 API 相容性,引入 Class Adapter 樣式 → 接受 Broken Hierarchy。
- Java Collections API 為了避免類別爆炸 → 接受 Rebellious Hierarchy。
- 為了序列化的便利 → 接受 Multipath Hierarchy。
Q2:同一段設計片段,到底是哪一種壞味道會不會取決於脈絡?#
會。書中以兩個 GUI 編輯器(DefinitionEditor、ObservationEditor)說明:
- 若兩者沒有共同父類別 → 是 Duplicate Abstraction。重構:抽出
CommonEditor。 - 若兩者已有共同父類別
Editor但共通邏輯未上提 → 是 Unfactored Hierarchy。重構:將共通邏輯 pull-up。 - 若兩者根本不需要分開 → 是 Unnecessary Abstraction。重構:合併為單一 Editor 類別。

Figure 7.1: Printer Definition Editor 使用者介面

Figure 7.2: Observation Editor 使用者介面
同樣的程式片段,可能對應到三種完全不同的壞味道與重構方向。不看脈絡就動手,極可能引入新的壞味道。
7.2 壞味道的交互作用#
7.2.1 壞味道從不孤立出現#
書中列出三組常見的「同時出現」:
- 複雜階層通常同時擁有 Deep Hierarchy、Wide Hierarchy、Multipath Hierarchy、Cyclic Hierarchy。
java.util的 Calendar / Date / TimeZone / GregorianCalendar 之間同時擁有 Hub-like Modularization、Cyclically-Dependent Modularization、Cyclic Hierarchy。- 「abusive centralization of control」反樣式同時觸發 Multifaceted Abstraction、Broken Modularization、Insufficient Modularization。

Figure 7.3: java.util 函式庫中的型別所出現的壞味道
壞味道彼此放大#
例:Deep Hierarchy + 根附近的 Insufficient Modularization。
javax.swing.ColorChooserDialog的階層本身就過深;偏偏靠近根部的java.awt.Component又是 Insufficient Modularization(332 個方法、Cyclomatic complexity 1143)。- 葉子要覆寫某方法時,必須沿整條繼承鏈追溯語意——其中還夾著一個巨大難解的中介類別。
- 兩個壞味道結合,理解難度遠超過單獨任一個。

Figure 7.4: ColorChooserDialog 的繼承階層
壞味道共生(co-occurring)#
Insufficient Modularization 與 Multifaceted Abstraction 經常雙向共生:
- 多重責任 → 介面與實作往往同時膨脹。
- 介面實作膨脹 → 通常責任也已混雜。
實務啟示:偵測 Insufficient Modularization(工具容易找)就順勢標記 Multifaceted Abstraction 候選。
壞味道作為前導(precursor)#
例:Broken Modularization → 引發 Deficient Encapsulation。
- 資料留在 A 類別、操作該資料的方法被擺到 B 類別。
- 為了讓 B 能存取 A 的資料,A 的欄位被改為 public → Deficient Encapsulation。
- 同樣推理也可能導出 Leaky Encapsulation。
處理連鎖式壞味道時,要找到根源壞味道(root smell)。修好根源,下游的壞味道往往跟著消失。但根源常隱形,必須從可見的壞味道一層層追溯。
7.2.2 壞味道指向更深層的問題#
「壞味道往往是冰山一角——背後可能藏著架構級的問題。」
書中舉例:
java.awt中許多 Cyclically-Dependent Modularization 跨子套件——這已經是架構級的循環依賴,需要大規模重構。

Figure 7.5: java.awt 套件層級的 Cyclically-Dependent Modularization 壞味道
- 大量 Broken Hierarchy → 暗示「為實作重用而濫用繼承」是團隊文化問題。
- 大量 Imperative Abstraction → 暗示「函式分解」(程序式思維)已滲透整個專案。
軼事:分層架構的隱性違規#
一個三層架構(Presentation / Business / Data)規定上層可呼叫下層,反之不行。但 Cyclically-Dependent Modularization 分析顯示 Data 層竟有大量對 Presentation 層的引用——架構分層被默默地破壞了。
教訓:從表面壞味道追到底,往往會發現架構腐蝕。
不要止於找到單一壞味道。用它當線索去挖更深的設計問題——這往往帶來最大的整體收益。