AI 都會寫程式了,我還要學什麼?——從「做得出來」到學會開發的 30 天

本系列文章・25/25

第 1 章|實作跑在理解前面

  1. Day 1|做得出來,卻完全改不動
  2. Day 2|當實作跑得比理解更快

第 2 章|第一個產品:從做功能,到開始理解工作

  1. Day 3|功能是從觀察和許願長出來的
  2. Day 4|如果所有事情都能交給 LINE 機器人就好了
  3. Day 5|做自己的系統,不代表什麼都要自己做
  4. Day 6|把反覆確認的工作交給系統之後
  5. Day 7|一句「平常都這樣做」,後面藏了多少事情?
  6. Day 8|沒有告訴 AI 的事
  7. Day 9|系統知道怎麼做,不代表使用者就該這樣做
  8. Day 10|我以為功能做完,產品就完成了
  9. Day 11|看到 n8n 時,我以為找到做預約系統的方法了

第 3 章|第二個專案:理解工作的能力開始變成工程判斷

  1. Day 12|原來我在做翻譯
  2. Day 13|聽他怎麼說,也看他怎麼做
  3. Day 14|我開始能從工作流程看見系統需要做什麼
  4. Day 15|我開始能從工作流程看見產品應該如何被使用
  5. Day 16|以終為始:思考產品功能
  6. Day 17|從「這個功能怎麼做」開始看懂系統怎麼分工
  7. Day 18|系統分工之後,怎麼讓不同部分一起工作
  8. Day 19|把「為什麼這樣決定」也留下來
  9. Day 20|從「我要這個功能」到「系統必須保證什麼」

第 4 章|AI 寫大量程式後,我怎麼理解、判斷與相信實作?

  1. Day 21|我幾乎不讀程式碼,那我是怎麼理解系統的?
  2. Day 22|從理解工程概念,到形成自己的判斷
  3. Day 23|我已經能沿著系統思考,卻還不能沿著程式碼追問題
  4. Day 24|我不逐行讀程式碼,那我要怎麼知道 AI 做對了?
  5. Day 25|用測試約束 AI 改程式目前閱讀

Day 25|用測試約束 AI 改程式

本篇目錄
  1. 測試留下的不是「這版程式沒問題」
  2. 後面每次修改,都要重新經過以前的測試
  3. 測試失敗,不一定代表程式寫錯
  4. 這對大量使用 Agent 的開發方式特別重要
  5. 測試約束的是已經被寫下來的東西

上一篇寫到,我現在不會只接受一句:

「AI 已經做完了。」

我會用不同層次的證據確認實作。

其中一層,就是測試。

TDD 本來就是我的開發流程之一,不是功能做完之後才另外補上去的驗收步驟。

但大量把實作交給 Coding Agent 之後,我更明顯感受到測試的一個作用:

程式可以一直改,但每一次修改,都要重新面對以前留下的期待。

測試留下的不是「這版程式沒問題」

我用 Spectra 規劃實作時,通常一開始就會要求採 TDD。

也就是先把這次預期成立的行為寫清楚,再讓實作去符合它。

這和功能完成後才補一批測試有一個很重要的差別。

如果測試是在程式已經寫完之後,才根據目前的行為補上,很容易只是把現況記錄成:

「現在的程式就是這樣跑。」

但我真正希望留下的是:

「這次我們確認它應該這樣運作。」

差別看起來很小,但後面的修改一多,就會變得很重要。

後面每次修改,都要重新經過以前的測試

我最常感受到測試作用的時候,不是第一次把功能做完。

而是幾天、幾週之後,又回來改同一段功能。

新的需求進來,Codex 修改原本的程式。

這時以前留下的測試也會重新跑。

如果原本確認過的行為被改壞,測試就會失敗。

這讓後面的修改不能只顧著把新的需求做出來。

它還要重新面對:

以前已經說好不能被破壞的東西,現在還成立嗎?

對我來說,這就是測試在 AI Coding 流程裡很重要的一層約束。

測試失敗,不一定代表程式寫錯

實際開發時,我也常遇到另一種情況。

功能需求真的改了。

Codex 把新的行為做出來,但原本測試裡的斷言還停在舊版本。

結果測試失敗,CI 也過不了。

這時候不能看到紅燈就直接說:

「程式壞了。」

還要先確認:

是新的修改破壞了原本應該維持的行為?

還是這次本來就要改變那個行為?

如果需求真的改了,舊測試也應該一起更新。

所以測試不是一條永遠不能動的規則。

它更像是把目前已經確認的期待保存下來。

當行為要改時,就必須一起面對:

我們是不是也正式改變了原本的期待?

這對大量使用 Agent 的開發方式特別重要

我平常很少逐行看 Codex 修改了哪些程式,也不會人工比對每一次 patch。

所以如果沒有其他約束,很容易只看到:

新功能最後動了。

需求表面上完成了。

但底下原本的行為有沒有被一起改掉,我不一定會立刻看見。

測試提供的不是完整答案。

但它至少讓修改不是完全沒有歷史。

以前已經被確認過的行為會留在那裡,後面的程式每次改動,都要重新跟它們對照。

這也讓我不需要只靠自己的記憶去想:

「這個地方以前是不是還有一個不能壞的條件?」

有些已經被寫進測試裡的期待,會自己重新出現。

測試約束的是已經被寫下來的東西

當然,這裡有一個很明顯的限制。

測試只能檢查:

已經有人想到,並且寫成測試的東西。

沒有想到的情況,不會因為 CI 全綠就自動得到保證。

規格本身如果漏掉重要情境,測試也可能很完整地驗證一個不完整的規格。

所以我不會把「測試全部通過」理解成:

這個功能已經全面正確。

它比較像是在回答:

那些已經被明確留下來的期待,現在還有沒有成立?

這也是為什麼測試之後,我的流程還不會結束。

因為即使已知行為都成立,還有另一個問題:

功能做對了,最後的實作方式也適合這套系統嗎?

返回系列總覽 →