
Day 11 把一個登入問題一路追到 Frontend state mapping,先回答了:
這次真正該改到哪裡?
但 Scope 正確,不代表功能就一定做對。
假設需求只有一句:
讓 ProxyAdmin 也可以幫別人點餐。
這句話放進真實系統後,立刻會多出一串產品決策:
如果這些問題沒有先回答,AI 還是可以很快做出一個「合理版本」。
只是合理,不等於符合這套系統真正的業務規則。
Acceptance Criteria 的價值,不是把需求寫得更正式,而是先決定什麼叫做做對。
Day 2 其實已經出現過 Acceptance Criteria。當時它主要用來從 Legacy 畫面反推需求;走到今天,角色、日期、截止時間與餘額都已經互相牽動,AC 開始多一個責任:在 AI 動手前,把行為契約固定下來。
Delegated ordering 最容易被誤解成:
多一個 target user 就好了。
畫面上可能真的只是多一個成員選擇器,但 Domain 至少同時在回答:
誰可以代點
+
哪一天可以代點
+
操作後誰的狀態被改變
這三件事如果各自由不同層自己猜,很容易得到一個很麻煩的結果:
每一段程式單獨看都合理,合起來卻不是同一套規則。
這次 repo 裡的測試就把角色差異寫得很具體。
ProxyAdmin:
Admin 則不同:對有效訂餐日期具備更高的操作能力,測試也明確涵蓋 cutoff 之後的 delegated ordering。
這已經不是一個按鈕要不要顯示的問題。
它是角色、日期、Calendar 與 Deadline 共同形成的規則。
我現在會把需求先改寫成可以直接判斷 PASS / FAIL 的句子。
例如 ProxyAdmin 的允許案例:
Given 使用者具備 ProxyAdmin 權限
And 指定日期是今天或未來
And 該日期已開團
And 尚未超過該日期 cutoff
When 替另一位可操作成員建立訂單
Then 系統接受操作
And 訂單歸屬於被代點成員
禁止案例則可以分開寫:
Given 使用者具備 ProxyAdmin 權限
And 指定日期是過去日期
When 嘗試建立 delegated order
Then 系統拒絕操作
And 不產生訂單
And 不改變任何餘額
以及:
Given 使用者具備 ProxyAdmin 權限
And 指定日期尚未開團
When 嘗試建立 delegated order
Then 系統拒絕操作
這裡刻意沒有寫:
因為 AC 描述的是外部可觀察的行為契約,不是 implementation plan。
只要這份 observable behavior 沒變,底層未來仍有重構空間。反過來,如果 AC 一開始就綁死檔案與函式,測試很容易只是在保護目前寫法,而不是保護真正的 Business Rule。
AI 很擅長先把主要路徑打通。
真實系統比較容易踩坑的,反而是邊界。
| 類型 | 代點餐例子 |
|---|---|
| Happy path | ProxyAdmin、今天/未來、已開團、cutoff 前 |
| Boundary | Admin 與 ProxyAdmin 對 cutoff 的權限不同 |
| Forbidden | 過去日期、未開團、角色不符 |
| State consistency | 訂單與餘額必須落在 target user,而不是 actor |
如果只驗 Happy path,很容易得到「功能已完成」的錯覺。
真正把規則寫清楚的,通常是第二、第三列。
例如測試裡甚至有一個很有意思的案例:
ProxyAdmin 可以讀取某個 target 的歷史 context,不代表它因此取得該日期的 mutation access。
也就是:
可以看
≠
可以改
這種規則如果沒有先進 AC,很容易只因為 UI 已經拿得到 target context,就不小心把 mutation 權限一起放大。
兩個功能表面都和「切換成別人」有關。
但語意完全不同。
View-As 的核心是:
用另一個人的視角查看系統
Delegated ordering 的核心則是:
由具備權限的人
代表另一個人
產生一筆會改變狀態的操作
前者偏向 read context。
後者會建立訂單、改變 target balance,還需要留下 actor / target 的責任關係。
如果只從 UI 長相出發,因為兩邊都有 member selector 就共用同一套權限,很容易把「看得到」和「可以代替他改資料」混成同一件事。
AC 的作用,就是在實作之前先把這種語意差異攤出來。
這也是 Vibe Coding 進入真實系統後,我越來越在意的一個落差。
早期功能單純時,一句自然語言需求常常就能得到很接近預期的結果。
系統變大後,同一句話背後可能已經綁著:
AI 可以幫忙把模糊需求整理成 AC,但最後仍需要人確認:
產碼速度可以交給 AI,加快產品決策並不代表產品決策本身也能外包。
第一輪是用案例類型找洞:
Happy path
Boundary
Forbidden
State consistency
它回答:
我是不是只想到「成功時會怎樣」?
第二輪再把需求壓成四個最小問題:
Who
誰可以做?
When
什麼日期/狀態下可以做?
Effect
成功後誰的哪些狀態必須改變?
Reject
哪些情況必須完全不產生副作用?

兩套看起來都像四格,但用途不同。
前一套用來找漏掉的案例;後一套用來寫最小行為契約。
這樣一句「讓 ProxyAdmin 也可以幫別人點餐」,才會從一個自然語言願望,變成 AI、測試與人都能判斷 PASS / FAIL 的工作。
下一步才是另一個問題:
當一條 AC 真的穿過 Frontend、API、Auth、Domain 與 Persistence 時,要在哪些地方看到證據,才算整條鏈都改對?
這不是純概念示範,而是一套持續開發中的便當訂購系統。文章著重「為什麼」,GitHub 保留實際程式碼、測試、文件與演進紀錄。
GitHub:https://github.com/henryfir456/bento-order-app