這篇不打算再講案例數字,想單純誠實地講一段自己的心路歷程。因為如果不誠實面對自己曾經站在哪一邊,這整個系列講的「Review 該審規則不是審程式碼」聽起來就只是一個事後諸葛的漂亮結論,而不是一個真的走過彎路才得到的立場。
在我還沒有認真實踐 Outside-In TDD 之前,我對「好的架構」有一種樸素的直覺:介面多一點、抽象層多一點,未來要換實作、要加功能的時候比較不會傷筋動骨。這種直覺不是憑空來的,它是被「將來需求會變」這個真實存在的風險餵養出來的。我確實遇過需求半年後真的變了、系統確實需要抽換一個第三方服務,那種時刻,「還好當初有留一層介面」的成就感是真實的。
問題是,這種成就感讓我對「預先多包一層」這件事,養成了一種不對稱的信任——我很擅長記得「哪一次多包一層救了我」,卻很少去清點「多包的那十層裡,有幾層從來沒被真的用上」。這正是這個系列案例裡過度設計版本呈現的樣子:92% 的程式碼是從未被呼叫過的死碼,但如果只看倖存的那 8%,會覺得每一層的存在都很合理。我曾經就是用這種倖存者偏差,替自己過去寫的防禦性程式碼辯護。
真正讓我開始懷疑「人眼 review 夠不夠」的,不是讀了哪一本書的哪一句話,而是反覆遇到同一種尷尬場景:review 別人(或後來 review AI 生成)的程式碼時,測試都是綠燈,架構圖看起來也完整,但我心裡總有一種說不出的不安,覺得「這東西是不是比它該有的樣子複雜」。這種不安沒有具體依據可以指出來,只能寫成「這裡感覺怪怪的,要不要簡化一下」這種很主觀的 review comment,而對方(不管是人還是 AI)常常可以合理反駁「這是為了未來擴充性」,而我拿不出更硬的論點去反駁回去。
真正讓這個模糊的不安變成具體立場,是動手做這個系列的案例之後——看著同一組測試,一個版本 3 個檔案,一個版本 745 個檔案,兩者都是綠燈。我第一次有了一個可以拿出來講的具體對照,而不只是「感覺怪怪的」。 這個經驗讓我確定:我過去那種說不清楚的不安,其實一直都是對的,只是我一直沒有找到把它變成可驗證規則的方法,只能停留在「憑經驗覺得不對」這個階段。
這裡要澄清一個容易被誤讀的地方:「相信可執行規則」聽起來像是「不再相信自己的判斷,改成完全依賴機器」,但我實際的轉折不是這樣。真正發生的事情是:我把過去那種「憑經驗覺得不對勁」的判斷,逼自己講清楚變成一條可以被檢查的規則(例如「改一個欄位不該動十個檔案」),而不是繼續停留在只有我自己心裡有數的直覺層次。這個轉折的核心不是拋棄判斷力,是拒絕讓判斷力停留在說不清楚的狀態。
回到系列主題句:AI 沒有發明過度設計,它只是讓過度設計的速度追上了你按下 Enter 的速度;Review 要跟得上,審的就不能再是程式碼本身,而是產生程式碼的規則。 這句話對我來說不只是一個給讀者的論點,也是我自己從「說不清楚的不安」走到「講得清楚的規則」這段路的濃縮。
你有沒有 review 程式碼時「感覺怪怪的,但講不出具體理由」的經驗?如果有,那個感覺後來有沒有被你轉化成一條可以檢查的規則,還是一直停留在只有你自己知道的直覺層次?
Day 27 要接著誠實面對一個反向質疑:把規則寫成可執行檢查,會不會只是把維護負擔從程式碼轉移到規則本身而已?
寫這篇最困難的地方,是要誠實承認自己以前的想法不是「錯得離譜」,而是「有部分道理,但被我用得太寬」。防禦性設計不是原罪,我現在依然會留必要的抽象層,差別是現在我會逼自己回答「這一層有沒有被任何測試逼出來」,答不出來就不留。這個習慣的養成,花的時間比我願意承認的還要久。