第 2 / 11 部 待錄

務實的方法上-好設計的四根支柱

《The Pragmatic Programmer 務實的程式設計師》Podcast 準備稿:務實的方法(上)好設計的四根支柱

書名: 務實的程式設計師 The Pragmatic Programmer(Your Journey to Mastery, 20th Anniversary Edition) 作者: David Thomas & Andrew Hunt 系列: 啃一本大書(恩普拉氏) 公開標題建議: 啃一本大書|The Pragmatic Programmer.ETC、DRY、正交性、可逆性:好設計的四根支柱 (2/11) 涵蓋範圍: 第2章 務實的方法(上)Topic 8-11:優秀設計的精髓、DRY、正交性、可逆性

背景速覽

第二章把第一章的「態度」落地成「方法」——這些方法幾乎適用於軟體開發的所有層面,近乎不證自明,卻很少被當成獨立主題記錄。本集處理前半段、也是全書的設計核心地基:從 Topic 8「優秀設計的精髓」這個總綱出發,串起 DRY、正交性、可逆性三大原則。作者明說「一切都從 Topic 8 展開」,所以這集等於是在講「什麼叫好設計」這個大哉問的務實版答案。

一句話重點

好設計只有一條標準——ETC(Easier To Change,更容易修改);DRY(不重複知識)、正交性(消除不相關事物間的影響)、可逆性(沒有最終決定)都只是 ETC 的三個特例,因為它們都在讓你的程式碼面對「變化」時更不脆弱。

值得討論的重點

1. ETC:所有設計原則的最大公因數

Tip 14「Good Design Is Easier to Change Than Bad Design」。作者大膽宣稱:所有你聽過的設計原則,本質上都是 ETC 的特例。 為什麼解耦好?因為改一處不會牽動別處,比較好改。為什麼單一職責好?因為需求變了只動一個地方。為什麼好命名重要?因為讀得懂才改得動。ETC 與其說是規則,不如說是一種價值——寫每一段 code 時自問一句:「我這樣寫,未來容不容易改?」如果答不出來,至少留個筆記。這把「好設計」從玄學變成一個可以隨時自問的具體問題。

2. DRY 不是「別複製貼上」,而是「別重複知識」

這是全書最常被誤解的原則。Tip 15「DRY—系統中每一項知識都應有單一、明確、權威的表述」。重點是知識與意圖的重複,不是程式碼字面的重複——這只是冰山一角。書裡舉了關鍵的反例:兩個驗證函式(驗證年齡 0-130、驗證數量 0-130)程式碼一模一樣,但它們驗證的是兩件不同的事,只是恰好規則相同——那是巧合,不是重複,硬要合併反而製造耦合(哪天數量上限改了你就麻煩了)。DRY 也涵蓋資料(Line 類別同時存 start、end、length 就重複了,length 該用算的)、文件(註解和 code 講同一件事,遲早脫節)、以及開發者之間(兩人各寫一套同功能,最難偵測——解法是溝通與 Tip 16「讓重用變得容易」)。

3. 正交性:直升機為什麼那麼難開

Tip 17「消除不相關事物之間的影響」。正交是從幾何借來的詞——兩件事正交,代表改其中一個不影響另一個。書裡用直升機當反例:四個操縱桿每一個都有副作用,降低左手桿機鼻會下沉並向左螺旋,你得同時補償其他三個——這就是非正交,所以難開。正交系統有兩大好處:提高生產力(修改局部化、元件可重用、M 件事 × N 件事 = M×N 種組合)與降低風險(壞掉的程式碼被隔離、系統不脆弱、好測試、不被廠商綁死)。一個漂亮的自測:「如果我大幅改某個功能背後的需求,會影響幾個模組?」正交系統的答案應該是「一個」。維持正交的技巧:寫「害羞」的程式碼(迪米特法則)、避免全域資料、避免長得很像的函式。

4. 可逆性:別把任何決定當成最終決定

Tip 18「There Are No Final Decisions」、Tip 19「Forgo Following Fads」。作者反對「關鍵決策不可逆」的工程文化——你今天選的資料庫、雲端供應商、第三方 API,未來都可能要換。可逆性就是 ETC 的時間版本:讓架構、部署、第三方整合都保持彈性。具體做法是把「會變的決定」藏在抽象後面(例如不要讓資料庫品牌的知識洩漏到整個 codebase),這樣換掉它時衝擊面最小。這條直接連到第五章「彎曲或弄壞」(EP6)——可逆性是「為什麼」,第五章是「怎麼做」。

注意事項

⚠️ DRY 最容易被矯枉過正成「任何看起來像的兩段 code 都要抽成共用函式」。請務必把「巧合的相同」和「知識的重複」這條線講清楚——過早抽象(premature abstraction)製造的耦合,常常比一點點重複更傷。有句業界格言可以引:「重複遠比錯誤的抽象便宜(duplication is far cheaper than the wrong abstraction)」(Sandi Metz)。

⚠️ 正交性的「害羞程式碼/避免全域資料」別講成「全域常數也不行」。問題在於會變的共享狀態造成的隱性耦合,唯讀的設定常數不是這個意思。並行章(EP7)的「共享狀態就是不正確狀態」是這條的極端版,可預告。

專家補充

💡 ETC 是二十週年版才新增的概念,1999 初版沒有。它其實是作者在二十年教學後,替整本書找到的「統一場論」——把 DRY、正交性、解耦全部收攏在一句話下。這個演進本身就很有意思:可以講「一本經典如何在二十年後找到自己更深的核心」。

💡 正交性與 DRY 是一對:DRY 管「重複」(同一知識別出現兩次),正交性管「依賴」(不相關的東西別互相牽動)。作者明說兩者結合能讓系統更靈活、更好除錯。這對概念後來在 John Ousterhout《A Philosophy of Software Design》被重新表述為「深模組/淺模組」與「資訊隱藏」——正交性大致就是高內聚低耦合的另一種講法。

💡 「直升機難開」這個隱喻特別好用,因為它讓抽象的「耦合」有了肉體感。可以延伸:很多人覺得某些 legacy 系統「動哪都會炸」,那不是因為人笨,是因為系統非正交——改 A 像降直升機的左手桿,整台機身都在反應。

討論問題

🎙️ 開場鉤子:「如果有人問你『什麼叫好設計』,你會怎麼回答?這集作者給了一個短到你會嚇一跳的答案——好設計就是比較好改的設計。就這樣。」

🎙️ 自問自答:「DRY 到底在 DRY 什麼?」——不是 DRY 程式碼字面,是 DRY 知識。兩段一模一樣的 code 可能完全不違反 DRY(因為是巧合),而兩段長得不一樣的 code 反而可能重複了同一個業務規則。

🎙️ 帶走的一題:「挑一段你最近寫的 code,問自己:如果它背後的需求大改一次,會波及幾個檔案?如果答案不是『一個』,你剛找到一個正交性的破口。」

更大範圍關聯

  • 與三經典互文:DRY 與正交性直接呼應《Clean Code》的命名與單一職責、《Refactoring》的「消除重複」是核心動機之一。本書提出原則,Fowler 的《Refactoring》提供把違反原則的 code 改回來的具體手法——兩本可當「原則書 + 操作手冊」配著讀。
  • 與《A Philosophy of Software Design》對話:Ousterhout 把「複雜度」定義為「依賴 + 模糊」,正交性處理的正是「依賴」這一半。是本季最好的對照組,可在後段集數正式登場。
  • ETC 的哲學親戚:ETC 與 Kent Beck 的「Make the change easy, then make the easy change」是同一個直覺;也與《Tidy First?》的小步整理相通。
  • 可逆性與架構潮流:「無最終決定」預示了後來的「延遲決策(defer decisions)」與 Clean Architecture 的「把框架/資料庫當細節」——都是讓重大決定可逆。

錄製建議

  • 建議時長:約 22-24 分鐘。配比:ETC 當總綱開場約 5 分(這是這集的鉤子)、DRY 約 7 分(例子多、最易誤解,是主菜)、正交性約 7 分(直升機好講)、可逆性約 4 分(當橋接到 EP6 的引子)。
  • 討論策略:把 ETC 當整集的線——講完 DRY、正交、可逆後,回扣一句「看吧,三個都是 ETC 的特例」收尾,結構感最強。DRY 段務必演「巧合相同 vs 知識重複」的對照,這是聽眾最容易帶錯回家的觀念。
  • 提醒聽眾這四個觀念是全書設計篇的地基,後面講解耦、繼承稅、並行時都會回來——先把地基打牢。