iT邦幫忙

2026 iThome 鐵人賽

DAY 29
0
Vibe Coding

神隊友.swift:30 天 Vibe Coding 打造育兒 iOS App 系列 第 29 篇

[Day 29] Vibe Coding 總檢討:PROGRESS.md 記下的 26 條踩坑分五類,以及兩個 Agent 的分工結論

  • 分享至 

  • xImage
  •  

Day 29

文章同步發表在我的個人 Blog

Vibe Coding 總檢討:PROGRESS.md 記下的 26 條踩坑分五類,以及兩個 Agent 的分工結論

做了 28 天,AI 最常在哪裡寫錯?

昨天 Day 28 處理設定頁的語言選項。今天不寫新功能,回頭讀每一輪結束時記在 PROGRESS.md 的「踩到的坑」,整理 AI 實際出錯的地方,再回答 Day 1 開始就有的問題:兩個 Agent 分工,結論是什麼。

先講結果:每一輪的流程是七個步驟,寫在第 1 節。我在 PROGRESS.md 找到 26 條踩坑,分成環境與工具、iOS 與測試框架行為、Firestore 與規則、規格和既有規則衝突、改完沒有重新驗證五類。這 26 條大多是要實際跑過才知道的行為。兩個 Agent 的比較,我沒有數字可以給,原因寫在第 4 節。

1. 每一輪的流程,七個步驟

後面的踩坑都發生在這個流程裡,所以先把流程寫出來。這是 AGENTS.md 規定的做法,Claude Code 和 Codex 共用同一份:

  1. 取項目:從 BACKLOG.md 取目前里程碑第一個沒勾的項目,一輪只做一個。需求有疑義,寫進 docs/QUESTIONS.md 並跳過,不自己假設。
  2. 規格:功能比較大的,用 Spectra 建一個 change,包含 proposal、design、specs、tasks,做完 archive 回主規格。Day 28 的語言選項就是這樣做的。
  3. 先寫測試:測試名稱帶驗收條件編號,例如 test_AC_TOPIC_03_replyByOverdueNotifiesBoth。
  4. 實作:Claude Code 主要實作。標成 [codex] 的純邏輯項目交給 Codex,在獨立的 git worktree 做,合併前由 Claude Code 對照驗收條件讀 diff。
  5. 驗證:執行 ./scripts/verify.sh,最後一行要印出 VERIFY: PASS。畫面相關的項目,另外截 Light、Dark、ax3 三張圖審視。
  6. 審查:里程碑結束時,Codex 唯讀 review。P0、P1 要修,或寫明為什麼不修。誰寫的程式碼,就由另一個 Agent 審。
  7. 記錄:更新 PROGRESS.md,寫做了什麼、卡在哪、下一步,踩到的坑也記在這裡。連續兩輪同一個錯誤修不好,就寫進卡點,改做下一項。

第 7 步的記錄,就是下面 26 條踩坑的來源。

2. 26 條踩坑,分五類

分類是我自己讀完每一條之後分的,有主觀成分。條數是我在 PROGRESS.md 找得到的,不是完整清單。

類型 條數 例子
環境與工具 9 新增測試檔後沒重跑 xcodegen generate,UI 測試顯示執行 0 個也不報錯
iOS 與測試框架行為 7 iOS 26 的確認對話框是 popover,沒有取消按鈕,同一個按鈕在元素樹裡出現兩層
Firestore 與規則 6 Timestamp 和 Date 來回轉換的次微秒誤差,被規則當成改了 createdAt
規格和既有規則衝突 2 新集合 users/{uid} 開放後,既有規則測試會失敗
改完沒有重新驗證 2 上午「瑕疵修掉」後沒有重跑,晚上 6 個 UI 測試失敗

另外還有 Day 21 提過的四個缺口(打錯字的卡片不能改、App 圖示是空的等),那四個是「需求裡沒有寫到」,不在這 26 條裡。

3. 五類各看一個例子

環境與工具:新增一個測試檔之後,Xcode 專案不會自己多出那個檔案,因為專案檔是 XcodeGen 從 project.yml 產生的。不重跑 xcodegen generate,測試報告是執行 0 個、沒有錯誤。測試顯示沒有錯誤,不代表有跑到東西。

iOS 與測試框架行為:Section 上設 .accessibilityIdentifier,會蓋掉裡面子元素的 identifier,UI 測試找不到按鈕。處理方式是把 identifier 放在內容容器上。這種問題程式本身沒有錯,要用 UI 測試跑一次才看得到。

Firestore 與規則:規則裡寫 list[0:n] 檢查陣列只追加,n 是 0(空陣列第一次追加)的時候,合法的追加被拒絕。加上 before.size() == 0 || 的保護之後通過。

規格和既有規則衝突:規格寫新集合叫 users/{uid},但既有的規則測試把 users/uid-alice 當成「不該被開放的路徑」,開放之後那個測試會失敗。專案規定不能刪或弱化既有測試,所以集合改名 userHouseholds。AI 照規格寫會遇到衝突,是因為規格沒有對照既有測試。

改完沒有重新驗證:9/30 上午修掉幾個瑕疵之後,沒有再跑 ./scripts/verify.sh,晚上才發現 6 個 UI 測試失敗。Day 28 也有同一類:語言區段放在「提醒」之後,把版本列擠出畫面,3 個既有測試用版本列當載入依據,找不到。這次測試不能改,所以改 App,把語言區段移到版本列之後。

4. 兩個 Agent 的結論

計畫裡的分工是 Codex 規劃與審查、Claude Code 實作與寫作,並排了 Day 3、11、21、29 四個比較日,要同一個小任務兩邊各做一次,記錄時間、來回次數、錯誤類型。

實際上,比較日沒有做成實驗。Day 21 已經寫過:沒有記錄時間和用量,所以不比誰比較快,也不比誰比較省。這一篇也一樣。上面 26 條踩坑,記錄裡沒有標是哪一個 Agent 寫出來的,所以也不比誰錯得比較多。

能說的只有記錄裡有的事:

  • Codex 的 7 份審查沒有 P0、列出 27 條 P1,類型集中在時序與並行、功能缺口、規則與安全。
  • Codex 負責實作的 4 個項目,都是不依賴畫面的純邏輯。
  • 實際用了才發現的缺口,審查都沒有抓到,因為審查是對照 acceptance.md 讀的,沒寫進去的東西,兩邊都不會發現少了。

從這些記錄能寫的結論只有兩句:互相審查抓到的是設計、時序和規則的問題;需求沒寫到的缺口,是實際使用才發現的。

5. 每輪結束前的四個檢查

現在每一輪結束前,都照這四個檢查做:

  • 每輪結束前一定跑 ./scripts/verify.sh,並把最後一行 VERIFY: PASS 或 VERIFY: FAIL 印出來。
  • 既有測試不改。測試因為新功能失敗,改 App,不改測試。
  • 新增測試檔之後,重跑 xcodegen generate,再看測試數量對不對。
  • 完整驗證一次只跑一個,前面不放其他重的工作。同時跑兩個,Firebase Emulator 的 port 會被占用,或是記憶體不足,測試被系統中止。

6. 寫的過程中,要多留意的八件事

上面四個是每輪結束前做的。下面八件事是寫的過程中容易漏掉的,都來自 PROGRESS.md 的記錄,每一件後面接當時的處理方式。

  • 規則與舊資料:新欄位寫 null 或 [] 到沒有這個欄位的舊文件,Firestore 規則會看成欄位被改動,擋掉一般的確認與修改。處理方式是沒有值就不寫入,未完成用 FieldValue.delete()。規則改完,要拿舊格式的文件再測一次。
  • 時間型別:Timestamp 和 Date 來回轉換會有次微秒誤差,規則會當成 createdAt 被改。處理方式是統一取整到微秒。
  • 離線:Firestore 的 async setData 會等伺服器確認,離線時一直等不到。處理方式是改用 completion 版本。
  • 背景執行:codex exec 在背景會等 stdin,所以指令後面要加 </dev/null。兩個負責畫面的子 Agent 曾因串流逾時中斷,用 SendMessage 接續後完成。
  • 大字級:快速新增在最大字級(ax5)加上時間之後,日期與時間合一的選擇器比螢幕寬,整頁左側的字被截掉。這是測試抓到的 bug,一般字級看不出來,所以畫面要用最大字級跑一次。
  • 測試紅燈:先寫測試的階段,同一個 test target 只要有一個測試檔編譯不過,其他測試都跑不了。看到大量測試失敗,先確認是不是編譯錯誤。
  • 規格和程式不一致:實作時發現規格寫錯,兩邊都要改。Day 19 規格寫「只有 note 卡可完成」,但從首頁加上時間的卡片資料上是 event,會被排除,所以改成「只有每週重複的行程不支援」,規格文件同步修改。
  • 實機:第一次裝機不能用 generic/platform=iOS,要指定裝置並加 -allowProvisioningDeviceRegistration;Xcode 登入失效要重新登入;裝置要開啟開發者模式。免費的 Personal Team 簽章會到期,到期前要重裝。

7. 對照 SDLC:一開始就該有的控制

SDLC(Software Development Life Cycle,軟體開發生命週期)把開發分成需求、設計、實作、測試、審查、部署與維運。這 30 天,AI 讓實作那一段變快,其他階段沒有跟著變快。下表把記錄放進每個階段,最右欄是從缺口反推的做法:

階段 這 30 天做了什麼 記錄裡的缺口 一開始就要有
需求 Day 2、6 做投票頁,Day 13 結果讓第一版重做 第一版做完才發現自己沒在用;Day 21 的四個缺口是需求沒寫到 先用最小的方式驗證需求,驗收條件寫成有編號的條目
設計 Day 10 架構文件和 ADR(Architecture Decision Record,架構決策紀錄),Spectra 的 proposal、design、specs 規格寫 users/{uid},和既有規則測試衝突;Day 19 規格寫「只有 note 卡可完成」,實作時才發現不對 平台限制列成表;規格寫完先對照既有測試和規則;規格錯了,規格和程式一起改
實作 Claude Code 實作,Codex 做純邏輯,邊界寫在 AGENTS.md 新增測試檔沒重跑 xcodegen generate;背景指令等 stdin 禁止事項寫成文件;一輪一個項目;交給另一個 Agent 的工作限定在純函式或單一資料夾
測試 測試名稱帶驗收條件編號,另有規則測試、UI 測試、變異測試、verify.sh 空測試顯示通過;Day 24 的規則有 2 個條件拿掉後測試仍然全過 verify.sh 第一天就有,每輪印最後一行;懷疑測試守不守得住時,故意改壞一處,確認測試會失敗(Day 20)
審查 Codex 唯讀審查 7 份,列出 27 條 P1 審查對照 acceptance.md,沒寫到的缺口沒有人看得到 誰寫的程式碼,由另一個 Agent 審;審查之外,另有實際使用的回饋
部署與維運 Day 18 裝實機,Day 26 簽章到期重裝,Day 28 處理回饋 第一次裝實機在 Day 18 最早的里程碑就裝到實機;簽章到期日排進計畫;回饋有固定的分類流程

表格最右欄重複出現的是三件事:驗收條件有編號、驗證腳本自動執行、盡早用實機。

8. 目前的狀態

項目 結果
踩坑 26 條,分五類
兩個 Agent 的比較 沒有時間與來回次數的數字
每輪結束前的檢查 四項
寫的過程中要留意的事 八件
SDLC 對照 六個階段,每個階段一項缺口與對應做法

明天預告

Day 30 回顧這 30 天:投票結果和做出來的東西對照,以及接下來怎麼繼續使用。

參考資源

官方文件


上一篇
[Day 28] 收集回饋並修一個問題:兩則回饋怎麼分類、為什麼先改語言選項,以及下次啟動才生效的做法
系列文
神隊友.swift:30 天 Vibe Coding 打造育兒 iOS App 共 29 篇
圖片
  熱門推薦
圖片
{{ item.channelVendor }} | {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言