《Clean Code》Podcast 準備稿:邊界・單元測試・類別
書名: 無瑕的程式碼 Clean Code(A Handbook of Agile Software Craftsmanship) 作者: Robert C. Martin(Uncle Bob) 系列: Reading Uncle Bob(恩普拉氏) 公開標題建議: Reading Uncle Bob|Clean Code.邊界、測試與類別:把第三方關在門外,把職責收乾淨 (4/7) 涵蓋範圍: 第8章 邊界 + 第9章 單元測試 + 第10章 類別
背景速覽
這集從「程式碼內部」走向「程式碼與外界的關係」:邊界(怎麼跟第三方函式庫相處)、單元測試(怎麼寫整潔的測試)、類別(怎麼把職責收乾淨)。三章都在講「控制依賴與複雜度」,是從「寫好一個函式」進化到「組織一個模組」的關鍵。
一句話重點
對外,要用封裝把第三方關在邊界、別讓它的細節滲進核心;對內,要靠整潔的單元測試(FIRST)當安全網,才敢重構;而類別要短小、單一職責、高凝聚——能不能用簡單名字命名,就是它有沒有做太多事的測謊器。
值得討論的重點
1.(邊界)用封裝與「學習式測試」馴服第三方
- 學習式測試(Learning Tests):與其讀第三方文件,不如寫測試去驗證你對它的理解。額外好處:第三方升版時,跑這些測試立刻知道有沒有被改壞(等於回歸測試)。
- 封裝邊界:別把
java.util.Map之類的第三方物件傳遍系統;包成自己的類別(如Sensors.getById()),只暴露業務需要的介面。這樣第三方介面變了,只改一處。 - 心法:依賴你能控制的(自己的 code)多於你不能控制的(外部 API)。
2.(單元測試)整潔測試的關鍵是「可讀性」+ FIRST
- 測試 code 和產品 code 一樣重要——髒測試比沒測試更糟(會變成維護負擔)。
- 結構:Build-Operate-Check(即 Arrange-Act-Assert)。
- FIRST:Fast(快)、Independent(獨立)、Repeatable(可重複)、Self-Validating(只有 pass/fail)、Timely(即時,TDD)。
- 一個測試只測一個概念:別把「新增→修改→刪除」串在一個測試裡,失敗了不知道是哪段壞。
- 價值:有了高覆蓋的整潔測試,你才有勇氣重構。
3.(類別)短小、單一職責、高凝聚
- 類別的第一規則是短小、第二規則是「更短小」——但衡量單位是職責不是行數。
- 命名測謊器:如果名字得叫
Processor/Manager/Super,或描述功能要用「而且/或者」,它就做太多了。 - 高凝聚:方法應頻繁使用類別的實體變數;若某些變數只被少數方法用→該拆出一個新類別。
- 為變更而設計:靠介面/抽象隔離具體細節(OCP、DIP),順帶讓單元測試能用 mock。
注意事項
⚠️ 「測試 code 和產品 code 一樣重要」是真的,但別讓聽眾以為要追求 100% 覆蓋率的數字。 覆蓋率是工具不是目標——測對的東西(邊界、關鍵邏輯)比覆蓋率數字重要。Uncle Bob 後面 EP7 也說「覆蓋率工具是找『沒測到的 code』最快的方法」,定位是診斷工具。
⚠️ 「一個測試一個斷言/一個概念」常被誤讀成「一個測試只能有一個 assert」。 Uncle Bob 講的是「一個概念」(可以有多個 assert 驗證同一件事)。別讓聽眾為了湊「單一 assert」把測試切得很碎。
⚠️ 類別章的 SRP(單一職責)是 SOLID 的 S,但「單一職責」其實出了名地難定義——「一個修改的理由」這句話很多人講不清。可以誠實說:SRP 是方向感、不是精確公式;現實中靠經驗與「這個類別會因為哪些原因被改」來判斷。
專家補充
💡 「學習式測試」是個被低估的好習慣,值得用力推:它把「讀文件(被動、易忘)」變成「寫可執行的測試(主動、會留下回歸保護)」。現代版就是你在 repo 裡留一個 spike/ 或 examples/ 測試,順便當活文件——呼應系列藍圖裡的《Living Documentation》《Specification by Example》。
💡 FIRST 的 Fast 是最常被違反、後果最痛的一條:測試一慢,工程師就不跑,安全網就形同虛設。可連到一個實務鐵律——單元測試該是毫秒級的;碰 DB/網路/檔案的那叫整合測試,要分開跑。
💡 類別章的「高凝聚→該拆類別」其實是 SOLID 的入口。SOLID 五原則(SRP/OCP/LSP/ISP/DIP)正是 Uncle Bob 提出的,而《Clean Architecture》(Reading Uncle Bob 下一本)整本就在講這個。這集可預告:類別這章是通往《Clean Architecture》的橋。
討論問題
🎙️ 開場鉤子:「你的專案有多少地方直接 import 了某個第三方 library?哪天它出大版本更新、或被廢棄了——你要改幾個檔案?這就是『邊界』要解的問題。」
🎙️ 自問自答:「沒有測試,你敢大改一個跑了三年的模組嗎?」——點出測試的真正價值不是抓 bug,是給你重構的勇氣。
🎙️ 帶走的一題:「找一個你專案裡名字有 Manager/Util/Helper 的類別,問自己:它到底有幾個『會被修改的理由』?能不能拆成兩個各司其職的類別?」
更大範圍關聯
- 通往 Clean Architecture:類別章的 SRP/OCP/DIP 是 SOLID 的入口,下一本《Clean Architecture》全面展開。
- 測試一脈:FIRST → Kent Beck《TDD》(系列藍圖大書)、《Working Effectively with Legacy Code》(怎麼替沒測試的舊 code 補網)。
- 活文件:學習式測試接《Specification by Example》《Living Documentation》《BDD in Action》。
- 邊界與依賴:封裝第三方接《Pragmatic Programmer》的「正交性」與六邊形架構(Ports & Adapters)。
錄製建議
- 建議時長:約 20 分鐘。三章各約 6–7 分。
- 討論策略:三章用「控制依賴與複雜度」串起來——對外(邊界)、對未來(測試安全網)、對內(類別職責)。開場用「第三方升版你要改幾個檔」這個切身痛點切入;測試章把重點放在「勇氣」這個情感賣點而非教條;類別章用「Manager/Util 測謊器」收尾,並預告下一本《Clean Architecture》。
- 單人主講時,FIRST 五個字母逐一展開好記好講;類別的「命名測謊器」是聽眾最容易立刻拿去檢查自家 code 的工具。