iT邦幫忙

2026 iThome 鐵人賽

DAY 7
0
Software Development

收到自己的紅色炸彈!婚期就是 Deadline:前端一人用 AI 規格流水線,30 天出貨婚禮 SaaS系列 第 7

Day 07 別讓 AI 寫出 Bug!從台灣婚宴「10+1」領域知識,看 Flow 層如何煉成業務護欄

  • 分享至 

  • xImage
  •  

❯❯ flow.md 實戰:六條不變量,和台灣婚宴的「10+1」領域知識
Day 07 拿座位分配,整段走一遍

📍 流水線位置|入口 → 【flow】 → 型別 → mock → 測試 → UI → vibe → 上線(實戰)

流水線位置|入口 → 【flow】 → 型別 → mock → 測試 → UI → vibe → 上線(實戰)
在整個婚禮系統中,座位分配(Seating)無疑屬於業務規則複雜度極高的高難度模組。它的難點在於狀態繁複、邊界條件多,且充滿動態變更的特性。從每桌的標準席位設定、兒童椅的彈性加設,到手動排座的調整,以及任何異動引發的座位狀態連動,無一不考驗著系統的穩定度。

這種「規則密度極高、邊界條件極多」的複雜場景,正好是用來驗證 Flow 層(spec/e2e-flows/)能否真正發揮「業務護欄」功用的絕佳試金石。

這一篇,我們就直接打開實體檔案 spec/e2e-flows/04-seating.flow.md,來一場深度解剖。


邊界界定:Flow 文件涵蓋範疇

檔案的開頭,開宗明義地劃清了這份 Flow 的責任邊界:它一口氣涵蓋了多達六個 .feature 規格檔案,從桌次的新增、更新與移除,到場地佈局設定,再到賓客的入座與取消入座,都需要精確對應至前端的場地平面圖視圖(Layout View)。

將「規格與測試流程」的對照關係明確定義於檔頭,能確保未來一旦出現業務邏輯異常時,團隊能在第一時間進行精確的責任溯源,不再需要盲目猜測。


業務不變量(Business Invariants):將領域知識轉化為系統護欄

04-seating.flow.md 的 Business Invariants:六條不變量,標亮的是文中討論的兩條
04-seating.flow.md 中,我們從原始規格中精確萃取出了六條關鍵的業務不變量(Business Invariants),節錄如下(完整條文見上方截圖):

1. 桌次增刪修:
管理員能在平面圖新增、更新或移除桌次(包含名稱、座位數與座標)。

2. 破壞性操作防禦:
桌次上若仍有賓客入座,系統嚴禁直接移除該桌。

3. 場地佈局設定:
管理員能設定場地佈局(如舞台位置與大小)。

4. 座位指派與展開:
管理員能將賓客(含同行者與兒童椅嬰兒)安排至桌次或取消入座;一個賓客組會依人數展開為多個席位。

5. 容量計算規則:
容量嚴格以「人頭」計算,正常席不可超過 capacity(兒童椅為額外加位,不佔正常席);正常席已滿或賓客已有座位時,不可重複安排。

6. 資訊可讀性:
桌次識別欄位(tableName)與正常席容量(capacity)必須能被使用者清晰讀取。

其中在這六條規範中,第 2 條與第 5 條更是最具代表性的關鍵邊界約束:

  • 第 2 條:「桌次上仍有賓客入座時不可移除」:
    這條規範旨在確保資料完整性,防止誤操作導致關聯賓客的座位無預警清空。值得注意的是,Flow 層並未死板地約束 UI 要長怎樣:不論前端是做成按鈕禁用(Disabled)、跳出確認 Modal,還是直接隱藏刪除按鈕都可以;Flow 層鎖定的核心底線在於:系統層級必須 100% 攔截這類破壞性操作。

第 2 條 破壞性操作防禦」狀態攔截示意圖

  • 第 5 條:「容量以人頭計:正常席人頭不可超過 capacity,兒童椅額外加位、不佔正常席」:
    第 5 條 座位規劃畫面:某桌次 10 個正常席剛好坐滿,另有 1 個兒童椅席位額外加位

    此規則直接反映了台灣婚宴的實務領域知識(Domain Know-how)。傳統婚宴桌席多以 10 人為標準容量,若賓客攜帶嬰幼兒,實務上會採額外加設兒童椅的「10+1」模式。

如果沒有把這項邊界條件明確寫進規格,通用 LLM 極容易寫出 guests.length <= capacity 這種過度簡化的判斷邏輯,把不佔正常席的兒童椅算進標準容量裡,導致明明沒滿座的桌次被系統誤判為爆滿。唯有將這類隱性的領域知識鍛造成明確的 Specification,入座流程的容量計算才能獲得真正的工程約束。

※註:這條容量約束後來在「調降座位數」的邊界邊緣曾爆出邏輯漏洞,後續我們已透過 Issue #90 補齊 HTTP 409 衝突守門機制,這也再次印證了護欄演進的重要性。
Issue #90

領域邏輯從來不會憑空變成防禦程式碼。Specification 最核心的工程價值,就是把這些沉澱在專家腦中的「隱性領域知識」,轉譯成系統可嚴格執行的硬性約束。


驗證流程與 UI 解耦

以「成功新增桌次」的場景為例,Flow 文件中的驗證流程始終保持著高階抽象。它的操作步驟大致為:「進入座位頁面 ➔ 觸發新增桌次 ➔ 填寫名稱『主桌』、容量 10 與座標位置 ➔ 提交」。全程完全不綁定具體的 DOM 結構或介面細節,例如:按鈕顏色或是 Modal 視窗的開啟方式。

它的斷言策略精準鎖定在兩個層級:

  1. API 層(API Spy):
    嚴格斷言發往 POST /api/v1/weddings/wedding-001/tables 的 HTTP 請求 Payload 必須精確包含名稱、容量與座標參數。

  2. UI 語意層:
    僅斷言 DOM 樹中成功渲染出包含名稱「主桌」且容量標示為 10 的實體節點。

這種設計帶來了極為顯著的工程效益。在後續的迭代過程中,座位配置頁面經歷了多次 UI 重構,包含引入場地底圖繪製、升級佈局工具,以及補充行動端觸控操作支援。儘管介面互動層進行了翻天覆地的重構,但基於業務不變量撰寫的主規格測試套件全程保持通過。原因就在於「不再凍結」段落早就為我們劃清了安全邊界:「位置設定方式(拖放畫布 / 數字輸入)」屬於允許自由重構的視覺與互動範疇。


流水線下游的資料傳遞

流水線下游的資料傳遞
事實上,flow.md 絕非寫完就晾在那裡的靜態文件,而是貫穿整條自動化流水線的核心結構化原料

  • Verification 中定義的 API 路徑與 Payload 規範:將作為下一步驟(Day 10)自動生成強型別合約與 Client 端的權威基準。
  • Business Invariants 段落:則會順流而下,成為 Day 14 中凍結層 E2E 測試套件的自動化斷言依據。

同一份業務邏輯真理(SSoT),會沿著這條自動化管線,在不同階段演化出相對應的工程實作。但這一切的前提是:這份「真理」本身必須是對的。

搞定 Flow 層之後,下一篇要碰一個尷尬的問題:flow.md 定義的規格範圍,如果哪天發現它自己沒用、根本不該存在,那這份當初說好的『凍結』,到底還算不算數?

📎 本篇證據spec/e2e-flows/04-seating.flow.md(包含六條 Business Invariants 與各場景「不再凍結」段落之實體文字)


上一篇
Day 06 先榨出「怎麼改都不能破」的那層
下一篇
Day 08 規格說了算,但 UI 沒人用怎麼辦?拆解 5 架構層級的 Specification 正式覆寫實錄
系列文
收到自己的紅色炸彈!婚期就是 Deadline:前端一人用 AI 規格流水線,30 天出貨婚禮 SaaS8
圖片
  熱門推薦
圖片
{{ item.channelVendor }} | {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言