《Code Complete 軟體建構之道》Podcast 準備稿:軟體建構中的設計
書名: 軟體建構之道 Code Complete(A Practical Handbook of Software Construction, 2nd Edition) 作者: Steve McConnell 系列: 啃一本大書(恩普拉氏) 公開標題建議: 啃一本大書|Code Complete.設計的第一性原理:管理複雜度 (2/15) 涵蓋範圍: 第5章 軟體建構中的設計
背景速覽
第5章是全書最長、也最核心的一章,它單獨成集。如果說整本書有一條「最高指導原則」,那就是這章丟出的那句話:軟體的首要技術任務是管理複雜度。前一集講了動手前的準備,這集就進到「設計」——把需求連到編碼的那座橋。McConnell 在這章把「設計」從一個玄學名詞,拆解成一套可操作的概念、特性與啟發式方法。
一句話重點
設計的本質是一場對抗複雜度的戰爭,而對抗複雜度的核心武器是「簡單性」——透過抽象、封裝、資訊隱藏、鬆散耦合這些工具,讓你在任何時刻都只需要在腦中裝下系統的一小部分;設計沒有標準答案,它是個迭代的、啟發式的、會犯錯的過程。
值得討論的重點
1. 設計為什麼這麼難——它是個「棘手問題」
McConnell 開門見山列了設計的幾個本質特性,最有畫面的是「棘手問題 Wicked Problem」:你必須先「解決」一次問題,才能真正定義它;然後再解一次,才能得到可行方案。經典案例是塔科馬海峽吊橋——工程師直到橋被風吹塌了,才知道原來要考慮空氣動力學。設計還是非確定性的(同個問題三個人會給三種都合理的設計)、湧現的(好設計不會憑空跳出,而是透過審查、討論、寫 code 慢慢長出來)、啟發式的(沒有保證成功的固定步驟)。這一段最大的價值是幫聽眾卸下罪惡感:你設計時一團亂、走死胡同、改了又改,這不是你笨,這是設計的本質。
2. 全書最高指導原則:管理複雜度
這是整本書的心臟。Fred Brooks 區分兩類困難:本質困難(軟體必須對應複雜的真實世界,這消不掉)和附帶困難(爛工具、爛語法造成的,大多已被解決)。McConnell 接著引 Dijkstra:沒有人的腦袋大到能裝下整個現代程式。所以對抗複雜度的策略是兩管齊下:最小化任何人同時要處理的本質複雜度,加上避免附帶複雜度不必要地增生。這條原則之所以重要,是因為後面所有的設計建議——鬆散耦合、高內聚、資訊隱藏、短常式——本質上都是它的推論。可以告訴聽眾:如果你只記得這本書一句話,記這句就夠了。
3. 對抗複雜度的工具箱:抽象、封裝、資訊隱藏
McConnell 用一組漂亮的比喻串起三個概念。抽象是「你可以從高層看一個物件,忽略細節」——對應門把、門、房子三個層級的介面。封裝更強,它說「而且你不被允許去看細節」——你看到什麼就只有什麼。資訊隱藏(David Parnas 1972 提出)是核心中的核心:每個類別都有它對外隱藏的「秘密」(易變的商業規則、硬體相依、檔案格式)。McConnell 特別引了一段軟工史的認錯:Fred Brooks 在《人月神話》20 周年版承認「Parnas 是對的,我當年批評資訊隱藏是錯的」。最實用的一招是養成問「我該隱藏什麼?」的習慣——很多困難的設計問題在這個問題面前會自己鬆動。
4. 鬆散耦合與設計的啟發式方法
設計沒有演算法,只有啟發式(heuristic,「有時管用的經驗法則」)。McConnell 列了一長串,最關鍵的是耦合——衡量類別之間關係的緊密程度。他把耦合從鬆到緊排序:簡單資料參數耦合(基本型別透過參數傳,OK),接著是簡單物件耦合、物件參數耦合,最緊的是 語意耦合(最危險:模組 B 依賴模組 A 內部運作的知識,比如 A 偷偷改了全域資料,B 假設它改好了)。其他啟發式包括:找現實世界的物件、追求強內聚、為測試而設計、考慮用暴力法(「能跑的暴力解勝過跑不動的優雅解」)、畫圖。McConnell 反覆強調:別對任何單一方法論教條,把它們當工具箱裡的工具。
注意事項
⚠️ 「低到中等扇出,一個類別用超過約 7 個其他類別可能太複雜」「資料成員不超過 7±2 個」這類數字(源自心理學的 7±2 記憶塊)會在後面好幾章反覆出現。它是經驗法則不是物理定律——重點是「降低任何時刻要同時掌握的東西」這個精神,別讓聽眾把 7 當成硬上限。
⚠️ 這章的設計模式清單(Abstract Factory、Adapter、Observer、Singleton……)是 1994 年 GoF《Design Patterns》的標準目錄。McConnell 自己也警告兩個陷阱:為了套模式而扭曲程式碼、為了想用某模式而用它(而非因為它適合)。提醒聽眾:模式是用來溝通和降複雜度的詞彙,不是炫技的清單。
⚠️ 「繼承 vs 包含」這章只點到,下一集(第6章工作類別)會深講。這裡先埋一句:McConnell 對繼承是謹慎甚至偏保守的態度,因為繼承會增加複雜度,跟「管理複雜度」的首要使命有張力。
專家補充
💡 「管理複雜度是首要技術任務」這句話,可以說是 Code Complete 對軟體界最大的貢獻之一,後來被無數人引用。它跟 John Ousterhout 二十年後寫的《A Philosophy of Software Design》(2018)的核心主張「軟體設計的根本問題就是管理複雜度」幾乎一模一樣——Ousterhout 那本書某種程度是這個觀念的現代延伸版。如果你的聽眾讀過 Ousterhout,這是一個很棒的對照:同一個洞見,隔了 14 年又被重新發現、重新論證一遍,可見它有多根本。
💡 資訊隱藏這個概念,背後是 David Parnas 1972 年那篇〈On the Criteria to Be Used in Decomposing Systems into Modules〉——軟工史上被引用最多的論文之一。它的革命性在於:模組怎麼切,不該照「執行的步驟」切,而該照「會一起改變的秘密」切。這個思想直接催生了後來的物件導向、微服務的「依領域邊界切分」。講這段可以讓節目很有縱深。
💡 「設計是迭代的,第一次夠好時不要停,第二次幾乎總是更好」這條,呼應了軟體界一句名言(出自 Brooks《人月神話》):「Plan to throw one away; you will, anyhow」——準備好丟掉第一版,反正你遲早會丟。這跟敏捷的「擁抱迭代」是同源的智慧。
討論問題
🎙️ 開場鉤子:「如果這本一千多頁的書只能留一句話,McConnell 自己會留哪句?答案是——軟體的首要技術任務,是管理複雜度。這集我們就來拆,這句話到底在說什麼。」
🎙️ 自問自答:「為什麼『簡單』這麼難?」——因為簡單不是少寫 code,而是主動把複雜度藏起來、切開來。抽象、封裝、資訊隱藏,三個工具都在做同一件事:讓你一次只需要想一小塊。
🎙️ 帶走的一題:「下次設計一個類別時,先問一個問題——這個類別的『秘密』是什麼?它對外想隱藏掉哪些會變的東西?光是回答這個問題,你的介面就會變乾淨一半。」
更大範圍關聯
- 軟工思想史的核心交會點:這章把 Brooks(本質 vs 附帶困難)、Dijkstra(腦容量有限)、Parnas(資訊隱藏)三位巨人的思想織在一起,是理解整個軟體設計思潮的好切入點。
- 對照組:John Ousterhout《A Philosophy of Software Design》是「管理複雜度」的現代重述,也對「深模組 vs 淺模組」有更細的論證,可作為這集的延伸閱讀推薦。
- 與本系列其他書:「資訊隱藏」「鬆散耦合」直接通到 Uncle Bob 的 SOLID(尤其依賴反轉、單一職責),可參照 [軟體工程領域切分藍圖] 把 Code Complete 和 Clean Architecture 接起來。
- 承先啟後:本集是全書的設計總綱,接下來 EP3(類別與常式)、EP7-8(陳述式)都是這套「管理複雜度」原則在不同尺度上的落地。
錄製建議
- 建議時長:約 25-30 分鐘。這是全書最厚的一章,值得給足時間。配比:設計為何難(棘手問題)5 分;管理複雜度(最高原則)8 分;抽象/封裝/資訊隱藏三件套 10 分;耦合與啟發式方法 7 分。
- 討論策略:開場直接把「管理複雜度」這句最高原則亮出來當鉤子,告訴聽眾這是全書的鑰匙。中段用「門把/門/房子」講抽象、用「秘密」講資訊隱藏,這兩個比喻最好懂。耦合那段用「語意耦合最陰險」當高潮——舉「B 偷偷依賴 A 改了全域資料」的例子,聽眾會冒冷汗。結尾把「我該隱藏什麼?」這個提問送給聽眾當隨身工具。
- 這集是整季的「思想骨幹集」,講透了後面會省力很多,值得多備一點料。