iT邦幫忙

2026 iThome 鐵人賽

DAY 4
0
Vibe Coding

Vibe 完之後:30 天給 AI 蓋的小商店裝上護欄系列 第 4

Day 4|腦子裡的架構規矩,怎麼變成會讓建置失敗的檢查?

  • 分享至 

  • xImage
  •  

Day 4|腦子裡的架構規矩,怎麼變成會讓建置失敗的檢查?

Day 3 把一條看似合理的稅率規則寫成紅燈:程式與既有測試都接受表外地區 XX 的稅額是 0,卻沒有證據說明這就是產品政策。今天再往前一步,不只挑一個邊界條件,而是把「誰不准依賴誰」這類架構規矩,寫成可以讓建置失敗的檢查。

這些檢查仍回頭對照開賽前的基準實驗(專案內叫 day0,不計入鐵人賽正式發文)。當時有三條只存在腦中的規矩:結帳不能直接進入點數模組的內部、同一把冪等鍵重送訂單只能留一筆,以及測試不能只有名稱而沒有斷言。程式與 AI 都不會自動知道它們,除非把規矩交給機器執行。

從概念到實驗:書提供方向,程式與資料是我自己量的

這篇借用 Peter Isberg 的 《Vibe Coding Architecture at Scale》(Packt,第一版,2026)第 2b 章,尤其第 2b.4 節的觀點:若一條原則不能讓建置失敗,代理遲早可能越過它。第 2b.1 節也引用 Richards 與 Ford(2020):架構處處是取捨,決策背後的 why 往往比 how 更重要。

原書只提供概念,不提供 vibe-order 的程式碼、檢查或本篇資料。這個迷你電商、三支檢查與下列執行結果,都是本系列自建實驗的產物。

三條規矩,三種檢查

不是所有規矩都能用同一種工具驗證。

  • 「結帳不能直通點數模組內部」是匯入路徑問題。我用 ESLint 的 no-restricted-imports 限制路徑樣式。
  • 「同一把鑰匙打兩次只能留一筆訂單」要真的呼叫 POST /orders,所以用 Vitest 合約測試。
  • 「測試必須有斷言」先以腳本掃描 it() 區塊,找可能的空殼測試。

今天產出 eslint-rules/no-checkout-internal-import.jspackages/orders/__tests__/idempotency.contract.test.tsscripts/diagnose/assert-quality-lint.mjs。這不是一張「架構已完全守住」的證明書;它們各自只涵蓋一種可觀察的違規形狀。

第一次紅燈,先暴露檢查沒有對準現場

預定組合是 npm run lint && npx vitest run idempotency.contract,再加 npm run diagnose:shallow-tests。預期至少兩支檢查會在 day0 版本先亮紅燈,結果前兩次紅燈其實都在說:檢查骨架還沒理解專案。

第一支執行 npm run lint 時,ESLint 不認得 TypeScript 的 import type

packages/checkout/src/index.ts
  7:13  error  Parsing error: Unexpected token {
✖ 1 problem (1 error, 0 warnings)

結束碼是 1,但這不是「結帳衝進點數後場」的違規。加上 @typescript-eslint/parser ^8.70.0 後,只掃結帳模組,結束碼變為 0,也沒有 no-restricted-imports 命中。結帳使用的是 ../../loyalty/src 的窗口,而不是列出的 internal/ 路徑。這也呼應 Day 1 量到的結果:沒有直接衝進後場的依賴。

第二支的骨架 payload 先用了 sku,伺服器回應 500,但測試預期 201,整次耗時 2.99s。這同樣不是冪等規則失效,而是基準實驗的貨架欄位叫 productId,商品是 coffee。改成 productId: "coffee" 後,測試通過:同一個 Idempotency-Key 送兩次,回到同一筆 id;該則測試 223ms,整次 1.40s。訂單模組的產品程式沒有修改。

第三支空殼測試掃描則掃到 2 個檔案、命中 0,結束碼 0。這兩個檔案是 Day 3 稅率測試與今天的合約測試;packages/day0.test.ts 不在 __tests__/,所以不在它的掃描範圍。這盞綠燈只能表示該啟發式在目前目錄沒有命中,不能推論專案沒有空殼測試。

口頭規則能自動化到哪裡?

三支檢查都能跑,卻都沒有抓到 day0 的目標違規。這不是它們沒有價值,而是一次必要的界線確認:檢查一只擋列出的路徑樣式;合約測試只確認一個 API 行為;空殼掃描也受目錄與語法啟發式限制。

還有一條規矩,我刻意沒有假裝能自動化:「改動前要說明為什麼選這個方案。」程式碼裡讀不到決策理由,因此沒有硬湊第四支腳本。架構檢查能把部分「怎麼做」釘住,無法取代人對取捨與理由的判斷。

反方觀點:規矩是不是反而拖慢了開發?

有可能。若 ESLint 規則列出的路徑根本不存在,或掃描腳本只看 __tests__/,很容易製造「已有護欄」的錯覺;太寬的限制也可能把合理的協作一起擋掉。另一個現實是,第一次裝檢查的成本不低:今天第一次安裝 ESLint v9.39.5,npm 也提示該版本已不再支援。

所以判準不該是「多一支工具就更安全」,而是規矩是否對得上目前程式的形狀、失敗時能否指出可處理的原因。今天兩次先紅後綠,正是把檢查對準 TypeScript 語法與 productId 欄位,不是修掉產品缺陷,也不是發現 AI 已違反那三條規矩。

這次證明了什麼,沒有證明什麼?

這次可以證明:口頭規則能被拆成可執行的檢查,而且檢查本身也必須拿真實專案資料校正。不能證明這三支工具能攔住未來所有架構違規,更不能因為目前沒有命中,就宣告 vibe-order 已經安全。

書中第 2b.2 節提到 2017 年 AWS S3 誤操作,用來提醒未被明確寫下的特性,常在出錯後才被發現。我不拿那個案例推導本專案風險或損失;它只是解釋為什麼今天要把一部分規矩寫成機器可執行的條件。

來源與 AI 使用揭露

概念來源:Peter Isberg,《Vibe Coding Architecture at Scale》(Packt,第一版,2026),第 2b 章第 2b.1 與 2b.4 節;出版社的書籍介紹與書目資料可供核對。AWS S3 僅為原書第 2b.2 節案例,本文未引用損失數字。

AI 使用揭露:三支檢查依寫作卡接上;ESLint parser 與合約 payload 的調整,是為了對準 day0 的語法與欄位,不是修改產品缺陷。文中的指令輸出與耗時為實際執行結果。vibe-order、測試、掃描腳本與報告皆為本系列自建實驗,不是原書附帶範例。

下一篇預告

明天把 Day 1 到 Day 4 裝出的檢查全部計時,區分各自回饋要等多久,也檢查它們究竟接進了會擋人的關卡,還是仍只是要靠人記得手動執行的腳本。


上一篇
Day 3|測試全綠,為什麼未列地區的稅卻是 0?
下一篇
Day 5|規矩回嘴要多久,量完才知道會不會被拔掉
系列文
Vibe 完之後:30 天給 AI 蓋的小商店裝上護欄5
圖片
  熱門推薦
圖片
{{ item.channelVendor }} | {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言