<?xml version="1.0" encoding="utf-8" standalone="yes"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom">
    <channel>
        <title>開發流程 on KnightLi的博客</title>
        <link>https://www.knightli.com/zh-tw/tags/%E9%96%8B%E7%99%BC%E6%B5%81%E7%A8%8B/</link>
        <description>Recent content in 開發流程 on KnightLi的博客</description>
        <generator>Hugo -- gohugo.io</generator>
        <language>zh-tw</language>
        <lastBuildDate>Tue, 05 May 2026 14:35:38 +0800</lastBuildDate><atom:link href="https://www.knightli.com/zh-tw/tags/%E9%96%8B%E7%99%BC%E6%B5%81%E7%A8%8B/index.xml" rel="self" type="application/rss+xml" /><item>
        <title>用測試和行為描述約束 AI 寫程式，少堆史山</title>
        <link>https://www.knightli.com/zh-tw/2026/05/05/ai-coding-tdd-bdd/</link>
        <pubDate>Tue, 05 May 2026 14:35:38 +0800</pubDate>
        
        <guid>https://www.knightli.com/zh-tw/2026/05/05/ai-coding-tdd-bdd/</guid>
        <description>&lt;p&gt;用 AI 寫程式時，最容易出現的體驗是：前期很快，後期很亂。功能剛開始能迅速搭起來，但專案一大、修改次數一多，就會出現一個 bug 改完又冒出三個 bug 的情況。&lt;/p&gt;
&lt;p&gt;這不完全是 AI 的問題。很多人寫程式也會這樣，只是 AI 寫得更快，問題暴露得也更快。要減少這種失控，關鍵不是讓 AI「更努力」，而是給它更清楚的邊界：先說明什麼結果算對，再讓它寫實作。&lt;/p&gt;
&lt;p&gt;TDD 和 BDD 就適合放到 AI 程式設計流程裡。TDD 負責把「對不對」變成自動測試，BDD 負責把「是不是我要的功能」變成人能看懂的行為描述。兩者結合，可以讓 AI 少猜、少自由發揮，也更容易被檢查。&lt;/p&gt;
&lt;h2 id=&#34;tdd-解決什麼問題&#34;&gt;TDD 解決什麼問題
&lt;/h2&gt;&lt;p&gt;TDD 是 Test Driven Development，也就是測試驅動開發。它的基本順序是：&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;先寫測試。&lt;/li&gt;
&lt;li&gt;執行測試，確認它現在失敗。&lt;/li&gt;
&lt;li&gt;再寫功能程式碼。&lt;/li&gt;
&lt;li&gt;持續修改實作，直到測試通過。&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;這和很多人習慣的做法相反。平時寫一個排序函式，直覺上會先寫函式，再隨便輸入幾個數字看看結果對不對。TDD 則要求先把預期寫成測試，例如輸入 &lt;code&gt;[3, 1, 2]&lt;/code&gt; 時應該得到 &lt;code&gt;[1, 2, 3]&lt;/code&gt;，輸入空陣列時應該回傳空陣列，輸入包含重複數字時結果也應該正確。&lt;/p&gt;
&lt;p&gt;這樣做的意義是：開發開始前，正確結果已經被定義清楚了。後面無論誰改程式碼，只要重新跑測試，就能知道有沒有破壞之前約定好的行為。&lt;/p&gt;
&lt;h2 id=&#34;為什麼-tdd-以前不容易堅持&#34;&gt;為什麼 TDD 以前不容易堅持
&lt;/h2&gt;&lt;p&gt;TDD 聽起來很美，但在真實專案裡並不容易長期執行。&lt;/p&gt;
&lt;p&gt;一是它反直覺。面對一個空檔案時，很多人更想先把功能寫出來，而不是先寫測試。尤其需求還不清楚時，測試案例也很難落筆。&lt;/p&gt;
&lt;p&gt;二是需求變化快。今天認真寫下的十幾個測試，明天需求一改，可能就要大面積重寫。短期看，它會讓開發節奏變慢。&lt;/p&gt;
&lt;p&gt;三是測試本身也需要成本。測試程式碼不是憑空出現的，過去它需要工程師自己寫、自己維護、自己解釋價值。對只看短期交付速度的團隊來說，這件事很容易被壓掉。&lt;/p&gt;
&lt;p&gt;但 AI 改變了這個成本結構。把需求轉成測試程式碼，恰好是 AI 很擅長的工作。讓 AI 根據測試去補實作，也比讓它對著一段模糊描述自由發揮可靠得多。&lt;/p&gt;
&lt;h2 id=&#34;ai-寫程式時怎麼用-tdd&#34;&gt;AI 寫程式時怎麼用 TDD
&lt;/h2&gt;&lt;p&gt;使用 AI 寫功能時，可以把提示方式從「幫我實作這個功能」改成下面這個順序：&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;讓 AI 先根據需求列出測試案例。&lt;/li&gt;
&lt;li&gt;要求每個測試案例都有中文說明。&lt;/li&gt;
&lt;li&gt;先 review 測試案例是否符合真實需求。&lt;/li&gt;
&lt;li&gt;確認測試後，再讓 AI 寫功能實作。&lt;/li&gt;
&lt;li&gt;要求 AI 執行測試，並根據失敗結果繼續修正。&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;這時，人主要 review 的不是一大段實作程式碼，而是測試是否說清楚了需求。測試案例通常更接近「輸入是什麼、輸出應該是什麼、邊界情況怎麼處理」，比直接讀實作邏輯輕鬆很多。&lt;/p&gt;
&lt;p&gt;例如可以這樣要求 AI：&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;div class=&#34;chroma&#34;&gt;
&lt;table class=&#34;lntable&#34;&gt;&lt;tr&gt;&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code&gt;&lt;span class=&#34;lnt&#34;&gt;1
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;2
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;3
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-text&#34; data-lang=&#34;text&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;先不要實作功能。
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;請根據下面的需求編寫測試案例，每個測試案例用中文註解說明覆蓋的業務規則。
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;測試確認後，再根據測試實作程式碼。
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;p&gt;這個流程能減少兩類常見問題：一類是 AI 寫著寫著偏題，另一類是後續修改時把舊功能改壞。&lt;/p&gt;
&lt;h2 id=&#34;tdd-還不夠&#34;&gt;TDD 還不夠
&lt;/h2&gt;&lt;p&gt;只有 TDD 仍然有兩個缺口。&lt;/p&gt;
&lt;p&gt;第一個缺口是：測試都通過，不等於產品真的符合預期。測試只能證明程式碼滿足了測試裡寫下的規則。如果測試本身沒有表達清楚使用者需求，程式碼仍然可能「正確地做錯事」。&lt;/p&gt;
&lt;p&gt;第二個缺口是：測試程式碼對非技術使用者仍然不友好。哪怕有中文註解，很多人還是不願意閱讀一堆單元測試。需求越偏產品體驗，越難直接從測試程式碼裡確認「這是不是我要的東西」。&lt;/p&gt;
&lt;p&gt;這時就需要 BDD。&lt;/p&gt;
&lt;h2 id=&#34;bdd-解決什麼問題&#34;&gt;BDD 解決什麼問題
&lt;/h2&gt;&lt;p&gt;BDD 是 Behavior Driven Development，也就是行為驅動開發。它關注的不是程式碼內部怎麼寫，而是系統在某個場景下應該表現出什麼行為。&lt;/p&gt;
&lt;p&gt;BDD 常用的描述方式是 Given / When / Then：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;Given&lt;/code&gt;：給定某個前置狀態。&lt;/li&gt;
&lt;li&gt;&lt;code&gt;When&lt;/code&gt;：當使用者或系統執行某個動作。&lt;/li&gt;
&lt;li&gt;&lt;code&gt;Then&lt;/code&gt;：應該得到某個結果。&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;例如一個帶吸血效果的遊戲角色，可以這樣描述：&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;div class=&#34;chroma&#34;&gt;
&lt;table class=&#34;lntable&#34;&gt;&lt;tr&gt;&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code&gt;&lt;span class=&#34;lnt&#34;&gt;1
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;2
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;3
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;4
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;5
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-text&#34; data-lang=&#34;text&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;Given 棋盤上有一個剩餘 1 點生命、攻擊力為 2、最大生命為 5 的吸血鬼
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;And 相鄰格子有一個剩餘 10 點生命的敵方單位
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;When 吸血鬼攻擊這個敵方單位
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;Then 敵方單位剩餘 8 點生命
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;And 吸血鬼恢復到 3 點生命
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;p&gt;這段話不是程式碼，但它比「攻擊敵人時恢復生命」精確得多。它說明了初始狀態、動作和結果，也暴露出後續需要補充的問題：如果敵人只剩 1 點血，吸血鬼按造成傷害恢復，還是按攻擊力恢復？如果吸血鬼已經滿血，溢出的治療怎麼處理？&lt;/p&gt;
&lt;p&gt;這些問題越早被問出來，AI 後面越不容易亂猜。&lt;/p&gt;
&lt;h2 id=&#34;為什麼-bdd-很適合-ai&#34;&gt;為什麼 BDD 很適合 AI
&lt;/h2&gt;&lt;p&gt;BDD 過去推行成本也不低。它要求產品、開發、測試用同一套行為描述溝通，而現實裡很多團隊並沒有這種協作習慣。&lt;/p&gt;
&lt;p&gt;但 AI 時代，BDD 的成本下降了。你只需要先寫一句粗略需求，例如：&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;div class=&#34;chroma&#34;&gt;
&lt;table class=&#34;lntable&#34;&gt;&lt;tr&gt;&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code&gt;&lt;span class=&#34;lnt&#34;&gt;1
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-text&#34; data-lang=&#34;text&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;吸血鬼攻擊敵人後，恢復與造成傷害等量的生命值。
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;p&gt;然後讓 AI 生成 Given / When / Then 場景。做得好的 AI 會主動補充邊界情況，並追問不明確的規則。你需要做的是確認這些行為描述，而不是直接讀實作程式碼。&lt;/p&gt;
&lt;p&gt;一旦行為描述確認清楚，再讓 AI 把它轉換成測試程式碼，最後根據測試實作功能，路徑就順了很多。&lt;/p&gt;
&lt;h2 id=&#34;一套更穩的-ai-程式設計流程&#34;&gt;一套更穩的 AI 程式設計流程
&lt;/h2&gt;&lt;p&gt;實際使用時，可以把 BDD 和 TDD 串起來：&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;先用自然語言寫需求。&lt;/li&gt;
&lt;li&gt;讓 AI 轉成 BDD 行為場景。&lt;/li&gt;
&lt;li&gt;人確認 Given / When / Then 是否符合預期。&lt;/li&gt;
&lt;li&gt;讓 AI 把行為場景轉換成自動測試。&lt;/li&gt;
&lt;li&gt;人快速 review 測試覆蓋範圍。&lt;/li&gt;
&lt;li&gt;讓 AI 實作功能。&lt;/li&gt;
&lt;li&gt;執行測試，失敗就讓 AI 根據錯誤繼續修正。&lt;/li&gt;
&lt;li&gt;最後再做一次人工驗收和程式碼 review。&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;這裡的關鍵是順序。不要一開始就讓 AI 寫完整實作，而是先讓它把需求變成可確認的行為，再變成可執行的測試。這樣 AI 的自由發揮空間會小很多。&lt;/p&gt;
&lt;p&gt;可以直接使用類似這樣的提示詞：&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;div class=&#34;chroma&#34;&gt;
&lt;table class=&#34;lntable&#34;&gt;&lt;tr&gt;&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code&gt;&lt;span class=&#34;lnt&#34;&gt;1
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;2
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;3
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;4
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;5
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;6
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;7
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-text&#34; data-lang=&#34;text&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;請按 BDD + TDD 的流程處理這個需求。
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;第一步：先把需求整理成 Given / When / Then 行為場景，不要寫程式碼。
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;第二步：列出你發現的不明確規則，並向我確認。
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;第三步：在行為場景確認後，再把它們轉換成測試案例。
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;第四步：測試確認後，再實作功能。
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;第五步：執行測試，根據失敗結果修復，直到測試通過。
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;p&gt;這類提示詞不複雜，但能明顯改變 AI 的工作方式。它會先收斂需求，再進入實作，而不是一上來就寫一堆看似完整、實際難以驗證的程式碼。&lt;/p&gt;
&lt;h2 id=&#34;適合優先使用的場景&#34;&gt;適合優先使用的場景
&lt;/h2&gt;&lt;p&gt;BDD + TDD 不一定適合所有任務。對於一次性腳本、臨時資料處理、小範圍樣式調整，完整流程可能太重。&lt;/p&gt;
&lt;p&gt;它更適合這些場景：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;業務規則多，容易理解錯。&lt;/li&gt;
&lt;li&gt;邊界條件多，後續還會持續修改。&lt;/li&gt;
&lt;li&gt;遊戲、計費、權限、狀態機、表單驗證等邏輯密集功能。&lt;/li&gt;
&lt;li&gt;需要多人協作確認需求。&lt;/li&gt;
&lt;li&gt;程式碼將長期維護，不只是一次性生成。&lt;/li&gt;
&lt;li&gt;已經出現「AI 越改越亂」的專案。&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;如果只是讓 AI 改一個按鈕文案，不必上完整流程。但如果要做一套角色技能系統、訂單狀態流轉、權限判斷、積分規則，先寫行為場景和測試會更划算。&lt;/p&gt;
&lt;h2 id=&#34;使用時注意什麼&#34;&gt;使用時注意什麼
&lt;/h2&gt;&lt;p&gt;第一，測試不是越多越好。測試應該覆蓋關鍵規則和高風險邊界，而不是把實作細節全部鎖死。否則需求稍微變化，測試就會變成維護負擔。&lt;/p&gt;
&lt;p&gt;第二，BDD 場景要寫具體。不要寫「系統應該正常工作」「體驗應該流暢」這類無法驗證的描述。要寫清楚給定什麼狀態、發生什麼動作、結果應該是什麼。&lt;/p&gt;
&lt;p&gt;第三，人仍然要 review。AI 可以生成測試和行為場景，但它不知道你真正想要的產品取捨。尤其是邊界規則，必須由人確認。&lt;/p&gt;
&lt;p&gt;第四，測試通過後還要實際執行功能。自動測試能兜住邏輯問題，但介面體驗、效能、互動細節、使用者感受仍然需要人工驗收。&lt;/p&gt;
&lt;h2 id=&#34;小結&#34;&gt;小結
&lt;/h2&gt;&lt;p&gt;AI 寫程式快，但快不等於穩。越是複雜需求，越不能只靠一句「幫我實作」。更好的方式是先把需求拆成可確認的行為，再把行為變成可執行的測試，最後讓 AI 按測試實作程式碼。&lt;/p&gt;
&lt;p&gt;TDD 讓 AI 知道什麼結果算對，BDD 讓人更容易確認這是不是自己想要的功能。兩者合起來，不是為了增加儀式感，而是為了減少 AI 的猜測空間，把「寫得快」變成「改得穩」。&lt;/p&gt;
</description>
        </item>
        
    </channel>
</rss>
