Feathers 給遺留碼一個刺耳但實用的定義:沒有測試的程式碼,就是遺留碼。不管它多新、多漂亮,只要你不能改一行就馬上知道有沒有壞,你就是在「編輯並祈禱」。這一頁講的是這個兩難的形狀——為什麼保留既有行為這麼難,以及為什麼「不敢改」本身會把系統推向更壞的地方。
🧠 Why It's a Problem
遺留碼的痛不在於「舊」,而在於改它的時候沒有回饋。Feathers 把所有變更歸成四個理由,但真正決定難度的不是理由,而是它動到了哪個維度:
- 新增功能:改結構、加新行為。
- 修復 Bug:改結構、改既有行為。
- 重構:只改結構,行為不動。
- 優化:只改資源使用,行為不動。
四種變更裡,唯一橫跨全部的挑戰是同一件事——保留既有行為。使用者信任的是行為;你加一個他們喜歡的行為叫功能,你動壞一個他們依賴的行為就叫 bug。而幾乎沒有一次改動能保證「只加不動」:即使只是介面多一顆按鈕,渲染都會有微妙差異。
IMPORTANT
從技術角度看,重要的區分不是「功能 vs. bug」,而是 新增行為 vs. 改變既有行為。前者相對安全,後者是所有風險的來源——而你通常沒辦法完全避開後者。
⚖️ 兩種工作方式:編輯並祈禱 vs. 覆蓋並修改
面對一次改動,你其實在兩種姿態裡選一個:
Edit and Pray — 編輯並祈禱(多數團隊的預設)
1. 小心翼翼研究要改的地方
2. 動手改
3. 把相關路徑點一遍、跑一跑
4. 覺得「應該沒問題」→ 送出問題:步驟 3 的「跑一跑」是靠人肉、靠運氣。你祈禱自己想到了所有會被波及的地方。改動越大、系統越糾纏,這個祈禱越不可靠——而你完全不知道自己漏了什麼。
Cover and Modify — 覆蓋並修改(有網子的改法)
1. 先用測試「蓋住」要改的區域(安全網)
2. 在網子保護下動手改
3. 測試立刻告訴你有沒有踩到既有行為
4. 綠燈 → 送出;紅燈 → 你當場就知道踩到哪差別不在「更勤勞」,而在回饋的來源:不是你的信心,是測試的差異。這就是為什麼 Feathers 說——沒測試的碼是遺留碼,因為它只能用祈禱的方式改。
WARNING
投入更多人力審查不能替代測試覆蓋。再多雙眼睛盯著 diff,也回答不了「我有沒有弄壞別的東西」——只有能重跑的測試回饋能。
🔁 恐懼迴圈:不敢改如何讓系統更爛
大多數團隊用「最小化改動、沒壞別修」來管理風險。這個保守策略看似安全,其實在複利式地累積代價:
- 程式碼膨脹:為了不碰結構,寧可把新邏輯塞進既有函式,於是它越長越難懂。
- 技能生鏽:拆大類別、打破依賴這些手藝,不練就退化,於是更不敢動。
- 恐懼蔓延:越不敢改 → 碼越爛 → 越不敢改。這個迴圈只有在團隊學會「先鋪網再改」的技術後才會反轉。
TIP
「Pay now or pay later」——寫測試現在要花時間,但不寫的利息會隨每次改動累積。而且變更會聚集:今天這塊碼你改到了,很快會再改到。先在這塊鋪網,幾乎總是划算。
🔑 Takeaways
- 遺留碼 = 沒有測試的程式碼;定義跟年紀、美醜無關,跟「改了能不能馬上知道對錯」有關。
- 四種變更(功能/bug/重構/優化)共同的最大挑戰都是保留既有行為。
- 別再「編輯並祈禱」;改用「覆蓋並修改」——先鋪測試網,讓回饋來自差異而非信心。
- 更多人力審查 無法 取代測試覆蓋。
- 保守不改會觸發恐懼迴圈,讓系統越來越難動;打破它的起點是先找到能下手鋪網的地方——也就是 接縫 與 特徵測試。
No notes yet — jot your takeaways or Q&A here.