《The Pragmatic Programmer 務實的程式設計師》Podcast 準備稿:務實的方法(下)曳光彈與估算
書名: 務實的程式設計師 The Pragmatic Programmer(Your Journey to Mastery, 20th Anniversary Edition) 作者: David Thomas & Andrew Hunt 系列: 啃一本大書(恩普拉氏) 公開標題建議: 啃一本大書|The Pragmatic Programmer.曳光彈、原型、領域語言與估算:把不確定性變成回饋 (3/11) 涵蓋範圍: 第2章 務實的方法(下)Topic 12-15:曳光彈、原型和便利貼、領域語言、評估
背景速覽
承接上一集的設計四支柱(ETC、DRY、正交、可逆),這集處理第二章後半——當你要把設計推進到真實世界時,怎麼對付「不確定性」。曳光彈、原型、領域語言、估算,四個 Topic 看似各自獨立,其實有一條共同主線:在你還不確定方向時,怎麼用最小成本拿到真實回饋,再來調整瞄準。 這集很實戰,談的是務實程式設計師「動手探路」的方法論。
一句話重點
面對模糊的需求和陌生的技術,不要先把規格寫到死再開一槍,而是用曳光彈打出一條能即時校正的端到端火光軌跡,用原型做用完即丟的探路,用領域語言讓程式碼說業務的話,並學會用迭代取代猜測來估算——核心都是「拿回饋,再調整」。
值得討論的重點
1. 曳光彈:建一條端到端、能即時校正的火光
Tip 20「Use Tracer Bullets to Find the Target」。曳光彈是混在彈匣裡會發光的子彈,士兵靠它在黑暗中即時看到「我打到哪」來校正瞄準。軟體版的曳光彈,就是先打通一條從需求到系統各層、最小但能跑的端到端骨架:第一顆曳光彈就是「建專案、加一個 hello world、確保能編譯能跑」,然後逐步往不確定、高風險的區域加骨架。它的五大好處很實用:使用者早期就看到東西在動(並貢獻回饋)、開發者有了可工作的結構(最可怕的空白頁被填滿)、有了每日整合的平台(不是大爆炸整合)、永遠有東西可 demo、進度感更真實。重點是它會校正——前幾發沒中目標很正常,因為 code 量小、慣性小,調起來快。
2. 曳光彈 vs 原型:一個留下來、一個丟掉
這是這集最該講清楚的對照。Tip 21「Prototype to Learn」。原型產生用完即丟的程式碼,目的是探索一個特定面向、回答一個風險問題(這個演算法行不行?這個 UI 流程順不順?),可以用便利貼、白板、甚至試算表做,不必是程式碼。曳光彈雖然精簡但是完整的,會成為最終系統骨架的一部分。 作者給的心智圖很漂亮:原型是「發射第一顆曳光彈之前的偵查與情報蒐集」。最危險的反模式是「把原型直接變成產品」——你以為在探路,結果探路用的鷹架被當成承重牆蓋了上去。所以做原型時,書裡建議貼張便利貼「我在做原型」提醒自己這是要丟的。
3. 領域語言:用問題的語言寫程式
Tip 22「Program Close to the Problem Domain」。引 Wittgenstein:「語言的界限就是世界的界限。」程式語言會影響你怎麼思考,而問題領域的語言也能暗示解法。務實程式設計師更進一步——真的用領域的詞彙、語法、語義來寫,這就是 DSL(領域特定語言)。分兩種:內部 DSL(嵌在宿主語言裡,如 Ruby 的 RSpec、Elixir 的 Phoenix Routes,免費繼承宿主語言能力,但受其語法限制)與外部 DSL(有自己的語法,如 Cucumber、Ansible 的 YAML,沒語法限制但你得寫解析器)。務實建議很重要:別花的工夫比省下的多——優先用現成的外部格式(YAML/JSON/CSV),不行才考慮內部 DSL,只有當「語言會被應用程式的使用者撰寫」時才值得做外部 DSL。
4. 估算:把「多久?」從猜測變成迭代
Tip 23「Estimate to Avoid Surprises」、Tip 24「Iterate the Schedule with the Code」。估算不是占卜,是建模。關鍵洞見:你用的單位會洩漏你的精確度——說「130 個工作天」別人期待很準,說「大約六個月」別人預期五到七個月之間。估算步驟:理解問題(範圍本身就是答案的一部分)→ 建模型 → 拆元件 → 給參數賦值(找出影響最大的參數集中火力)→ 算答案(複雜時多算幾次避險)→ 追蹤自己的估算準度。對專案時程,作者推崇兩招:PERT(每個任務給樂觀/最可能/悲觀三個值,源自北極星潛艇專案)與「吃大象」(透過增量開發,每次迭代結束根據真實經驗精煉時程——讓時程隨 code 迭代)。被臨時逼問估算時的標準答案:「我回頭再告訴你。」 咖啡機旁隨口給的估算會像咖啡一樣回來找你麻煩。
注意事項
⚠️ 曳光彈和「敏捷 MVP / walking skeleton」很像但別劃等號講。曳光彈強調的是「校正瞄準」這個回饋迴路與「端到端打通各層」,MVP 強調的是「最小可上市的價值」——重疊但側重不同。講的時候保留它的軍事隱喻味道,那是這本書的招牌。
⚠️ DSL 那段千萬要帶上「別花的工夫比省下的多」這條煞車。工程師聽到 DSL 容易興奮想自幹一套語言,但本書立場相當保守——絕大多數情況用現成 YAML/JSON 就夠了,自造外部 DSL 是少數。別讓聽眾聽完跑去寫 parser。
專家補充
💡 「Ready, Fire, Aim」(預備、開火、瞄準)這個刻意顛倒順序的格言,是曳光彈精神的濃縮——傳統是 Ready-Aim-Fire(瞄準到完美才開火),務實程式設計師是先打一發看看、再校正。這其實是整個敏捷/精實思想的縮影:用真實世界的回饋取代紙上的完美規劃。
💡 估算的「單位即精確度」洞見有個現代版:很多團隊改用「故事點數(story points)」而非「人天」估算,正是因為人天會誘導出虛假的精確感。但 Thomas & Hunt 更根本的主張是「讓時程隨 code 迭代」——這預示了 Scrum 的速度(velocity)概念:與其前期估到死,不如跑幾個迭代測出團隊的真實節奏。
💡 領域語言這條接得到 Eric Evans 的《Domain-Driven Design》——「無所不在的語言(ubiquitous language)」就是讓團隊與業務用同一套詞彙,而 DSL 是把這套語言推進到程式碼本身。兩本可互文:DDD 講「為什麼要說業務的話」,本書講「怎麼把業務的話變成可執行的程式碼」。
討論問題
🎙️ 開場鉤子:「需求很模糊、技術很陌生、做完之前世界還會變——這種專案你怎麼開第一槍?這集的答案是:別瞄太久,先打一發會發光的子彈,看它飛去哪再修。」
🎙️ 自問自答:「曳光彈和原型差在哪?」——一句話:原型是探路用的、做完要丟;曳光彈是骨架、會留在最終系統裡。最危險的事就是把原型當曳光彈,讓臨時鷹架變成承重牆。
🎙️ 帶走的一題:「下次有人在走廊隨口問你『這個大概要做多久?』,試著回一句『我回頭再告訴你』,然後真的走一遍估算步驟。比較看看跟你脫口而出的數字差多少。」
更大範圍關聯
- 與敏捷/精實:曳光彈、迭代估算、增量開發都是作者敏捷宣言背景的直接體現。本集其實是「敏捷方法的個人實作版」,到第八章「敏捷的本質」(EP10)會升級成方法論層級的討論。
- 與三經典:本集偏方法論,與《Refactoring》《Clean Code》的「程式碼層級」較少直接重疊,但曳光彈骨架建好後,後續往骨架上長肉的過程正是重構的舞台。
- DSL 的脈絡:接 Martin Fowler 的《Domain-Specific Languages》專書、Eric Evans 的 DDD;領域語言也呼應本書第八章「需求坑」——說業務的話,才聽得懂業務真正要什麼。
- 估算的思想史:PERT 源自 1950 年代北極星潛艇專案,是專案管理的古典工具;本書把它從大型國防專案縮放到日常開發,並用「迭代精煉」這個敏捷補丁修正了古典估算的僵硬。
錄製建議
- 建議時長:約 22-24 分鐘。配比:曳光彈約 7 分(招牌隱喻,主菜)、曳光彈 vs 原型對照約 4 分(關鍵釐清)、領域語言約 5 分、估算約 7 分(實戰價值高、PERT 和「我回頭再告訴你」都好講)。
- 討論策略:用一條「對付不確定性」的主線把四個 Topic 串起來,避免聽起來像四個無關的小節。曳光彈與原型一定要做對照演示。估算段落以「單位即精確度」和「我回頭再告訴你」這兩個可立即套用的點收尾,實用感最強。
- 這集收掉第二章,可在結尾預告:接下來離開「方法」進入「工具」(EP4 基本工具),從哲學、方法走向務實程式設計師的手上傢伙。