iT邦幫忙

2026 iThome 鐵人賽

DAY 14
0
Claude AI

奇幻塔防開發實錄:用 Claude 打造一款有靈魂的塔防遊戲系列 第 14 篇

Day 14:【週記】Day 8-13 回顧:worktree 平行開發真的有比較快嗎?數據公開與反思

  • 分享至 

  • xImage
  •  

claude_14

系列:奇幻塔防開發實錄:用 Claude 打造一款有靈魂的塔防遊戲
今日工具:git worktree + Claude Code(數據回顧)
今日進度:三筆平行開發實驗彙整、一份「何時該開 worktree」的決策準則

前言

第二週結束。後端從一個空目錄長成了:Clean Architecture 骨架(Day 8)、劇情狀態機(Day 10)、無畫面模擬器(Day 11)、REST API 與 DynamoDB 倉儲(Day 12–13),加上 Terraform 的 serverless 地基與單表的 GSI(Day 9、13)。這週我最想回答的問題只有一個——README 開頭就承諾過的——用 git worktree 開兩個 Claude Code session 平行開發,到底有沒有比較快?

Day 12 做了第一次實驗,Day 13 又做了兩次,其中一次是刻意設計的反例。三筆數據放在一起,答案比「有」或「沒有」更有意思:它快的時候很快,慢的時候不只慢,還會留下測試抓不到的錯。

一、三次實驗的原始數據

量測方式同 Day 12:序列估計用同規模任務的歷史實測推估(誤差約 ±15%),平行實測用碼表,從兩個 session 開始到合併完成、測試全綠;token 為 /cost 讀數的輸出 token;「切換」指我主動把注意力從一個終端機移到另一個的次數。

# 任務 A 任務 B 重疊檔案 序列估 平行實測 差異 切換 衝突
1(Day 12) 戰鬥結果驗證 usecase + handler 劇情 handler + mapError router.go 100 min 62 min −38% 11 1
2(Day 13 上午) DynamoDB 倉儲(item.go + save_repo.go)+ platform/dynamo.go Terraform 補 GSI1 + TTL + PITR 無 70 min 39 min −44% 6 0
3(Day 13 下午) router 加 middleware 鏈重構 auth 空殼 middleware(Day 27 前置) router.go、middleware/ 45 min 51 min +13% 14 3
合計 215 min 152 min −29% 31 4

輸出 token:三次平行合計 118k,序列估計 106k,多約 11%。

實驗 2 是最漂亮的案例:Go 與 HCL 兩種語言、兩個目錄、零交集,而且兩邊都有長等待(go test ./... 全跑、terraform init 下載 provider)。我幾乎是在兩個「等待」之間來回,6 次切換全都有意義。

實驗 3 是我刻意做的反例:兩個任務都在改 router.go 與 middleware/。結果不只慢了 13%,三次衝突裡有一次是「兩邊都把 middleware.Timeout 移到不同位置」,合併後 Timeout 被掛了兩次、順序還錯了,go test 沒抓到,是 curl 一個慢請求才發現。平行開發最貴的成本不是衝突本身,是衝突解錯了沒人知道。

二、什麼任務適合開 worktree

把三筆數據攤開,規律很清楚:

適合平行 不適合平行
兩個任務碰的檔案集合幾乎不相交(實驗 2) 兩邊都要改同一個「組裝點」(router.go、main.go)
每個任務都有長等待(跑測試、terraform init、bun install) 任務本身很短(< 20 分鐘),切換成本吃掉收益
需要不同環境(port、語言工具鏈、Terraform 的 provider 快取) 任務 B 依賴任務 A 的介面(B 會猜錯 A 的命名)
任務可以各自寫測試證明完成 完成判準是「整體行為對」,要兩邊合起來才能驗

把這兩欄接起來,其實是一棵深度只有三層的決策樹:

claude_14_diagram_01

實驗 1 的 router.go 衝突之所以可接受,是因為它是可預期的、機械式的衝突——兩邊各加一行路由,Claude 三秒解完,而且解錯了測試會抓到。實驗 3 的衝突是語意衝突,兩邊對「middleware 該怎麼排」有不同想法,這種才該避免。

我把這棵樹濃縮成三句話寫進根目錄 CLAUDE.md 的「worktree 開發須知」:一、開 worktree 前先列兩個任務會動的檔案,交集只能是組裝點;二、組裝點的修改留到合併後由一個 session 做;三、每個 worktree 的 session 結束前必須 go test ./... 全綠,並跑一次 make smoke。第三條是實驗 3 的血淚。

第一條聽起來像官僚,實際上只花兩分鐘:我讓兩個 session 各自先進 Plan mode 列出「會新增或修改的檔案」,把兩份清單並排看一眼就知道該不該開。實驗 3 我當時偷懶跳過這一步,代價是 51 分鐘加上一個沒被測試抓到的 Timeout。

三、隱形成本:注意力、token、心智模型

注意力:三次實驗總共 31 次切換。我在 Day 12 說「worktree 省的是等待、不是注意力」,這週更確定了——實驗 3 切了 14 次,超過某個門檻後我開始搞混哪個終端機是哪個分支,有一次差點在錯的 worktree 裡 git commit。claude --worktree 搭 --tmux 讓分頁名稱就是分支名,有幫助,但治標;真正的解法是任務夠獨立,讓切換次數自然降到個位數。

token:多 11% 是兩個 session 各讀一次 CLAUDE.md 與相關 domain 檔案的代價。Day 6 把 CLAUDE.md 拆成根+子目錄兩層在這裡回本了:backend/ 的 session 不會把前端規則也讀進去;實驗 2 的 Terraform session 更是完全不碰 Go 的規則。

心智模型:兩個 session 不共享記憶。實驗 1 任務 B 不知道任務 A 定義了 ErrInvalidReport,合併後 mapError 少一個 case 是我手動補的;實驗 3 兩邊對 middleware 順序的認知不同,根本原因也是這個。對策是把「這次任務會新增的公開名稱、會動的組裝點」先寫進任務描述,兩邊都看得到——這其實就是 Day 13 那張 REST 契約表的精神,只是尺度縮小到兩個分支之間。AI 同事跟人類同事一樣,需要開會。

跟第一週對照(兩週的數字都是那六天的,不含今天寫週記本身):第一週 12 個 Claude session、830 專注分鐘,全部序列;第二週 15 個 session、約 790 專注分鐘,其中 152 分鐘是平行的。做的事情明顯比第一週多,專注分鐘反而少——但我不敢把功勞全記在 worktree 上,第二週的任務本來就比較「有型」(有 ADR、有契約、有型別),Claude 猜錯的機率低很多,這可能才是主因。

還有一個沒放進表格、但我覺得最值得說的成本:worktree 讓「等待」消失,也讓「思考的空檔」消失。序列開發時,Claude 跑測試的三十秒是我重看設計、發現「這個名字取得不對」的時間;平行開發時那三十秒被另一個 session 填滿了。實驗 2 那 39 分鐘我一次都沒有停下來想架構,做完才發現 dynamo.NewSaveRepo 應該接受一個已經建好的 client,而不是自己在建構子裡 config.LoadDefaultConfig——那會讓每次 Lambda invoke 都重建一次連線。這個決定要到 Day 26 才會付出代價。

四、這週後端的其他收穫

  • 模擬器比畫面早出現是對的(Day 11)。v0 數值 0% 通關率這件事如果到 Day 15 才發現,我會花一天懷疑引擎而不是懷疑數字。
  • sentinel error + errors.Is(Day 10、12)讓 handler 的錯誤翻譯只有 12 行,之後加新錯誤只要在 mapError 加一個 case。
  • nil slice 跨 JSON 邊界會變 null(Day 13)。換成 DynamoDB 之後這個坑一模一樣:cleared 是空的時候,make + copy 出來的空 slice 才會序列化成 []。這種 bug 只有真實請求打得出來。
  • Plan mode 值得用在骨架上(Day 8)。事前改兩個決定,比事後改 14 個檔案便宜。
  • Terraform 我還沒 apply 過任何東西。這是刻意的:Day 16 CI/CD 建好前,我不想讓「本機 apply」變成習慣。

五、下週策略

第三週是前端:Vue 3 + Canvas 引擎(Day 15)、CI/CD(Day 16)、Pinia 狀態與升級樹(Day 17)、劇情介面(Day 18)、RWD(Day 19)、自訂 workflow 除錯(Day 20)。前五天我打算全部序列,因為引擎、狀態、介面是一條依賴鏈,不符合上面那張表的任何一列——硬開 worktree 只會重演實驗 3。唯一例外是 Day 16 的 CI/CD 跟 Day 15 的引擎沒有交集,如果進度允許會平行。worktree 正式再登場是 Day 26 效能優化:前端 SpatialGrid 與後端在本機 net/http 模式下的 pprof(PPROF=1 才會起 :6060)兩條線完全不相交,是教科書等級的平行案例——Lambda 上沒有原生 pprof 可以連,所有剖析都得在本機那一半做。

小結

worktree 有沒有比較快?任務獨立時省 38–44% 的 wall-clock,任務糾纏時反而慢 13%,而且會製造測試抓不到的語意衝突。 它省下的是等待時間,不是注意力;它需要的是事前把檔案集合與公開名稱講清楚,而這件事本身就是好的工程習慣——不管有沒有 AI。

補一句關於「週記放哪」:我沒有在倉庫裡開 docs/weekly/。週記就是這篇文章,倉庫再擺一份摘要只會多出一個永遠跟文章不同步的真相;只有那三條 worktree 規則需要進 CLAUDE.md,因為它會被 Claude 讀進去。下週見。

今日產出

  • [x] 三次 worktree 實驗彙整表與決策準則(本篇一、二節)
  • [x] 根目錄 CLAUDE.md 新增「worktree 開發須知」三條規則
  • [x] 第三週改回全序列的排程決定(本篇五節)

明日預告

Day 15:Vue 3 + Canvas:塔防戰場渲染引擎從零到一。


上一篇
Day 13:API 契約與單表設計:用 Claude Code 生成 RESTful 介面與 DynamoDB 存取模式
系列文
奇幻塔防開發實錄:用 Claude 打造一款有靈魂的塔防遊戲 共 14 篇
圖片
  熱門推薦
圖片
{{ item.channelVendor }} | {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言