iT邦幫忙

2026 iThome 鐵人賽

DAY 10
0
Software Development

AI 時代的 TDD:讓 AI 寫 Code,但不要讓它決定品質系列 第 10

Day 10:Refactor 階段——AI 最容易跳過的一步,沒有安全網的「順手重構」

  • 分享至 

  • xImage
  •  

前言

「反正測試都綠燈了,AI 順手把旁邊那個函式也改乾淨一點,應該沒差吧?」

這句話聽起來像是效率的展現——都已經打開這個檔案了,看到旁邊有一段程式碼寫得不太好,順手一起改掉,感覺是在做對的事。但「順手」這兩個字,恰好是 Refactor 階段最危險的入口。

Red-Green-Refactor 的第三步之所以能安全進行,前提是有一件事成立:你正在改動的每一行程式碼,都受到測試的保護。 這個前提在 AI 協作情境下,經常悄悄被打破,而且打破的方式很難被察覺——因為表面上看起來,測試還是全部綠燈。

今日目標

  • 理解 Refactor 階段真正依賴的前提是什麼,而不只是「有沒有測試」
  • 看清楚「順手重構」這個行為,為什麼會在不知不覺間破壞這個前提
  • 學會辨識一次改動裡,哪些部分屬於被要求的範圍,哪些是額外夾帶的
  • 建立「重構範圍要跟測試覆蓋範圍對齊」的具體檢查習慣

Refactor 依賴的不是「有測試」,是「這段程式碼有測試」

Refactor 階段能安心進行,核心邏輯是:如果重構過程中不小心改壞了行為,測試會立刻告訴你。這句話成立的關鍵在於「你正在改動的這段程式碼」有沒有被測試涵蓋,而不是「這個檔案裡有沒有測試」。一個檔案可以有十幾個測試案例,但如果這次改動剛好動到其中沒有被任何測試打到的那幾行,測試套件全綠這件事完全不能證明什麼。

問題是,AI 在完成 Green 階段之後,很容易把「重構」的範圍自然而然地擴大。它被要求修好一個函式,過程中看到旁邊另一個函式的實作方式不夠一致、變數命名可以更清楚、有一段邏輯可以抽出來共用——這些觀察本身通常是對的,但「觀察到可以改善」跟「現在有安全網可以改」是兩件不同的事。這次任務的測試,是針對被要求修改的那個函式寫的,不代表旁邊那個函式也在同一張安全網底下。

為什麼這種夾帶很難被發現

如果順手改動的部分直接改壞了什麼,測試通常會抓到,這種情況反而不危險,因為它會立刻現形。真正危險的是另一種情況:順手改動的部分表面上沒有改變行為,只是換了一種寫法——例如把一段迴圈改寫成陣列方法鏈、把一個條件判斷的順序調整了、把某個中間變數省略掉直接內聯。這類改動如果原本就沒有測試涵蓋,測試自然也不會有任何反應,因為根本沒有東西在監看這段程式碼的行為有沒有變。

風險在於,這類「看起來只是換寫法」的改動,經常隱藏著不容易一眼看出的邊界情況差異——例如換了迴圈寫法之後,對空陣列或 null 的處理方式跟原本不一樣了。這種差異可能要到很久之後、某個邊界輸入真的出現時才會爆出來,而且到時候完全無法從「這次改動有沒有通過測試」回推出問題根源,因為當初根本沒有測試在觀察這段程式碼。

對照範例

❌ 順手重構,範圍沒對齊測試覆蓋
任務:修正 calculateDiscount() 的門檻判斷邏輯(有測試涵蓋)
AI 的實際改動:
  1. 修正 calculateDiscount() 的判斷邏輯 ← 有測試保護
  2. 順手把旁邊的 formatCurrency() 從 for 迴圈改寫成 reduce ← 沒有測試涵蓋
  3. 順手把 validateInput() 的參數順序調整成跟 calculateDiscount() 一致 ← 沒有測試涵蓋
→ 測試全綠不代表第 2、3 項改動沒有引入行為差異,
  只代表沒有任何東西在檢查它們

✅ 重構範圍對齊測試覆蓋,其餘部分留到下一輪
任務:修正 calculateDiscount() 的門檻判斷邏輯
AI 的實際改動:
  1. 修正 calculateDiscount() 的判斷邏輯 ← 有測試保護
  回報:「注意到 formatCurrency()、validateInput() 也有可以改善的地方,
        但目前沒有測試涵蓋,這次不動,如果要一併處理,
        建議先補測試再重構。」
→ 改動範圍等於安全網範圍,額外的觀察誠實回報、
  而不是直接動手

重構安不安全,不是看有沒有測試,是看你正在動的這幾行,有沒有被測試真正涵蓋到。

這跟系列前面幾天的關係

這個系列前面幾天談過的假陽性測試、硬編碼預期值,講的都是「測試本身有沒有問題」;今天談的是另一個維度——就算測試本身寫得沒問題,改動範圍跟測試覆蓋範圍對不齊,一樣會讓「測試綠燈」這件事失去意義。這兩個維度合起來,才是判斷一次改動安不安全的完整條件。

實務上比較穩妥的做法,是要求 AI 明確區分「這次任務要求的改動」跟「過程中觀察到但沒被要求的額外調整」,後者一律先回報、不直接動手,除非你確認過那部分也有測試覆蓋,或者你願意先花一輪補測試再處理。

今日思考題

回想你上一次讓 AI 重構一段程式碼:那次的改動範圍,跟原本被要求修改的部分完全一致嗎?如果 AI 順手多改了什麼,你有回頭確認過那部分有沒有測試涵蓋嗎?

今日重點回顧

  • Refactor 階段的安全感,來自「正在改動的程式碼」有沒有被測試涵蓋,不是「檔案裡有沒有測試」
  • AI 完成 Green 階段後容易「順手」擴大重構範圍,把沒有測試涵蓋的部分也一起改了
  • 最危險的順手重構,是那種表面上沒改變行為、實際上悄悄改變邊界情況處理方式的改法,因為測試不會有任何反應
  • 具體做法:要求 AI 把「被要求的改動」跟「額外觀察到的改善」分開回報,後者先不動手

明日預告

明天要把這幾天談到的 Red、Green、Refactor 各自的風險收攏起來,看怎麼設計一套流程,逼 AI 老老實實走「先紅、後綠、再重構」的順序,而不是三步一次到位。


上一篇
Day 09:案例——AI 為了讓測試綠燈,硬編碼了預期值
系列文
AI 時代的 TDD:讓 AI 寫 Code,但不要讓它決定品質10
圖片
  熱門推薦
圖片
{{ item.channelVendor }} | {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言