《A Philosophy of Software Design 軟體設計的哲學》Podcast 準備稿:複雜性的本質與徵兆
書名: 軟體設計的哲學 A Philosophy of Software Design 作者: John Ousterhout 系列: 旗艦評書(恩普拉氏) 公開標題建議: 評書|A Philosophy of Software Design.複雜性才是真正的敵人 (1/11) 涵蓋範圍: 緒論 + 第1章 複雜性的本質 + 第2章 程式能跑還不夠(戰術 vs 戰略)
背景速覽
這是「旗艦評書.軟體設計的哲學」整季的起手集。作者 John Ousterhout 不是業界顧問,而是史丹佛教授(也是 Tcl 語言、Raft 共識演算法的作者),這本書的內容根基於他開的一門「軟體設計」課——學生交作業、他做設計審查、把反覆出現的毛病提煉成原則。所以這本書的調性跟 Uncle Bob 的《Clean Code》很不一樣:它不給你一條一條的規則清單,而是給你一個統一的世界觀——軟體設計從頭到尾只在對抗一件事:複雜性。這一集先把這個世界觀立起來,再講「為什麼光是讓程式能跑,遠遠不夠」。
一句話重點
軟體開發的根本瓶頸不是硬體、不是演算法,而是我們能不能在腦中裝下自己正在打造的系統;而複雜性正是那個讓系統「裝不下」的東西,它不會一次爆發,而是一點一點偷偷累積——所以對抗它要靠的不是英雄式重構,而是戰略型的心態:每次都多投資一點點,讓設計持續變好。
值得討論的重點
1. 複雜性的定義:跟「規模」「功能多寡」無關,只跟「難不難搞」有關
Ousterhout 對複雜性下了一個很務實、也很狠的定義:複雜性就是任何讓系統難以理解或難以修改的東西。注意這個定義刻意把「規模」踢出去了——一個一百萬行、但好維護的系統不算複雜;一個三百行、但每次改都要繞地球一圈的小工具,反而極其複雜。而且他補了一刀:複雜性是讀者說了算,不是作者。你覺得自己的 code 很單純,但同事看了一頭霧水,那它就是複雜的。這條一講出來,很多人的自我感覺就會被戳破。
2. 複雜性的三個徵兆:變更放大、認知負擔、未知的未知
這是本書最實用的診斷工具,建議一條一條演:
- 變更放大:一個小改動卻要動很多地方(網站每一頁都寫死橫幅顏色,要改色得改一千頁)。
- 認知負擔:要完成一件事,你得先把多少東西塞進腦袋(C 函式回傳指標、呼叫端得記得自己 free,忘了就洩漏)。Ousterhout 在這裡特別點名:不要用「行數」衡量複雜性——有時候多寫幾行、但認知負擔更低,反而更簡單。
- 未知的未知:你根本不知道「要改哪裡」「需要知道什麼才能改對」。這是三者裡最致命的,因為前兩者你至少知道要努力的方向,未知的未知連方向都沒有——通常要等 bug 炸了才知道。好設計的反面目標就是讓系統「顯而易見」(obvious),這條會貫穿整季。
3. 複雜性的兩個成因:依賴(dependencies)+ 模糊(obscurity)
這是整本書的中央方程式,務必講清楚、後面每一集都會回扣:複雜性 = 依賴 + 模糊。
- 依賴:一段 code 沒辦法獨立理解或修改,得連著別的一起動。依賴不可能消滅(每寫一個 class 就引入了依賴),目標是減少數量,並讓剩下的依賴明顯、好管理。
- 模糊:重要資訊不顯而易見(變數叫
time卻不知單位、不一致的命名)。Ousterhout 點出不一致是模糊的主要來源,而且「需要大量文件才解釋得清的設計,本身就是紅旗」。
把這條方程式記牢,這季每講一個技巧,你都可以問:它是在砍依賴,還是在除模糊?
4. 戰術型 vs 戰略型:本書的態度核心
複雜性是逐步累積的——不是一次大失誤,是幾百個「這次只多加一點點沒關係」堆出來的。對應的兩種心態:
- 戰術型程式設計:目標是「讓它能動」,趕快交差。每次都合理化一點點妥協,累積成義大利麵。Ousterhout 講了一個很傳神的角色——「戰術型龍捲風」:產量驚人、管理層眼中的英雄,但身後留下一地殘骸給別人收。
- 戰略型程式設計:承認「程式能跑還不夠」,主要目標是做出好設計、它剛好也能跑。做法是持續做小投資(總開發時間的 10–20%),短期慢一點,幾個月內回本,之後永遠比戰術型快。
注意事項
⚠️ 別把「10–20% 投資」當成精算數字。Ousterhout 自己標註那張回報曲線是「定性示意,非實證測量」。這本書整體偏哲學、偏個人經驗,不是實證研究——它的說服力來自「你心裡也這麼覺得」,不是來自數據。講的時候誠實一點,反而更有公信力。
⚠️ 「複雜性由讀者定義」這條雖然犀利,但別推到極端變成「只要有人看不懂就是我的錯」。有時候是領域本身難(密碼學、分散式共識),那不是設計複雜,是本質複雜。要區分「不必要的複雜性」(這是要消滅的)和「本質的複雜性」(這是要封裝的)。
專家補充
💡 這本書最大的賣點,就是它是《Clean Code》的正面對照組,而這條對撞線從第一集就要埋下去。Uncle Bob 教你「函式要小、類別要小、單一職責」;Ousterhout 接下來會直接質疑這套會製造「淺模組」。但有趣的是——兩人在「複雜性是大敵」這個大前提上完全同意,吵的是「該用什麼戰術對付它」。第一集先把這個架好:這季不是來踩 Uncle Bob 的,是來看「兩位大師對同一個敵人開出不同藥方」。
💡 「依賴 + 模糊」這個拆法,其實跟學界講的 coupling(耦合)與 cohesion(內聚)是同一件事的白話版,但 Ousterhout 故意不用學術詞,因為他要的是「能在 code review 當場喊出來」的詞彙。這也是本書的方法論:把抽象原則變成可以指著螢幕說「這裡有 red flag」的東西。
💡 Ousterhout 是少數同時站在「學界」和「真正寫過大系統」兩邊的作者(Tcl、Raft 都是他的)。所以這本書既有教授的系統性,又躲開了純學術的空泛。可以對聽眾說:這是「一個寫過真東西的教授」的設計筆記。
討論問題
🎙️ 開場鉤子:「你有沒有接過一份 code,光是搞懂『要改哪裡』就花了一下午——還不是改錯、是根本找不到該改的地方?那種痛,Ousterhout 給它取了個名字,叫『未知的未知』,而且他說這是所有複雜性裡最要命的一種。」
🎙️ 自問自答:「『戰術型龍捲風』在你公司是誰?」——拋給聽眾想一想:那個 sprint 永遠衝最快、被老闆當英雄的人,三年後留下的 codebase 是什麼樣子?再反問:那收拾殘局、看起來比較慢的人,是不是其實才是真英雄?
🎙️ 帶走的一題:「下次你想說『這次先這樣、之後再重構』的時候,停三秒問自己一句:我是在投資,還是在借高利貸?」
更大範圍關聯
- 本季的對照組就是《Clean Code》:整套 Reading Uncle Bob 系列(見 [軟體工程領域切分藍圖])是這本書最好的陪讀,兩邊可以一集一集對著聽。本季會反覆回扣藍圖 §5 主題「Clean 到底乾不乾淨」——也就是「小函式、小類別」到底是良藥還是另一種病。
- 軟工三經典的延伸:《Clean Code》+《Refactoring》(Fowler)+《The Pragmatic Programmer》是工匠三經典;Ousterhout 這本可視為「站在更高一層看設計」的補充——前三本給戰術,這本給戰略。
- 思想血緣:「軟體最大的限制是人腦能理解的程度」這個母題,可上溯 Fred Brooks《人月神話》的「概念完整性」與「本質複雜性 vs 偶然複雜性」——Ousterhout 的「本質 vs 不必要的複雜性」就是這條線的當代回聲。
錄製建議
- 建議時長:約 22–25 分鐘。配比:緒論+複雜性定義約 6 分、三徵兆+兩成因約 10 分(這是本集骨幹,例子多、好演)、戰術 vs 戰略約 8 分。
- 討論策略:開場用「找不到該改哪裡」的痛感拉共鳴;中段把「三徵兆+兩成因」當成一套診斷工具交給聽眾,強調這是整季都會用到的詞彙;結尾用「投資 vs 高利貸」的比喻收束戰術/戰略之爭。
- 這是整季起手,記得花 30–60 秒介紹「旗艦評書」要幹嘛、Ousterhout 是誰、以及最關鍵的一句定錨:這季全程跟《Clean Code》對照著聽,看兩位大師怎麼對付同一個敵人。