iT邦幫忙

2026 iThome 鐵人賽

DAY 5
0
Claude AI

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

Day 05:Vue 3 + Go:技術選型的取捨,為什麼前後端分離是這場戰役的兵法

  • 分享至 

  • xImage
  •  

claude_05

系列:奇幻塔防開發實錄:用 Claude 打造一款有靈魂的塔防遊戲
今日工具:claude.ai 對話 / ADR
今日進度:四個技術決策寫成三份 ADR,外加一份 IaC 決策的 ADR,前後端邊界畫定

前言

前四天把「做什麼」定清楚了:世界觀、四塔五敵、三條命運之路。今天回答「用什麼做」。技術選型最怕兩件事:一是選自己熟的而不是適合的,二是選完就忘了為什麼——三週後遇到問題時,只記得「當初好像有考慮過」,卻想不起來當初的判斷依據。

所以今天的產出不是選項清單,而是ADR(Architecture Decision Record)——把背景、選項、決定、後果寫下來。30 天後回頭看,才知道當初是聰明還是僥倖;更重要的是,Claude Code 之後讀 docs/adr/ 就能理解「為什麼引擎層不能 import Vue」這類規則的來由,而不是只被告知規則本身。

一、讓 claude.ai 當反方,而不是當顧問

Day 1 學到的教訓:直接要方案會得到一份不屬於自己的架構。所以這次我先寫下我的傾向,再請 Claude 反駁

Prompt(給 claude.ai)
「我打算用 Vue 3 + Canvas 做前端、Go 做後端、REST 溝通、AWS 部署。請針對每一項各給我兩個『你應該選另一個』的最強理由,附上這個專案(30 天、單人、塔防、有劇情存檔)的具體情境。不要和稀泥,我要真正會讓我改變主意的論點。」

它給的反方論點有幾個確實打中我:

決策 我的傾向 最強反方論點 我的回應
前端框架 Vue 3 React 的 Canvas 生態(react-konva 等)更成熟 引擎層我要與框架無關,框架只管 HUD 與對話框,生態差異影響小
後端語言 Go Node 可與前端共用 TypeScript 型別,30 天內少寫一套 型別由 data/*.json 契約統一,不靠語言;Go 的 goroutine 對 Day 11 的平行模擬有實質幫助
渲染 Canvas 2D WebGL(PixiJS)在 200+ 敵人時效能好很多 我的規模上限約 150 敵人,Canvas 2D 夠用;效能問題留到 Day 26 用空間格與物件池解
通訊 REST WebSocket 讓後端能即時驗證戰鬥、防作弊 單人遊戲,作弊只傷自己;戰鬥在前端跑、結果回報後端做粗略合理性檢查即可

基礎建設這邊還有一個沒列在表裡的決策:Terraform 還是 AWS CDK?反方論點是 CDK 用 TypeScript 寫、能與前端共用語言。我選 Terraform 的理由是它的 plan 輸出是可讀的純文字,Day 9 起我打算讓 Claude 解釋每一次 plan 的變更;而且 HCL 的宣告式風格讓 Claude Code 生成的模組更容易逐行審查。這寫在 docs/adr/0005-iac.md,「後果」段我也老實補了三句:選了 serverless 架構之後,terraform plan 要處理的資源數從原本 ECS/RDS/ALB 那套的幾十個掉到十幾個;沒有任何一項資源是按小時固定計費的(Fargate、RDS 都是);region 選在 ap-east-2(台北)是個 opt-in region,apply 之前得先在帳號層級手動啟用——這件事寫進 ADR,Day 9 就不會忘記先去開。

真正差點讓我改變主意的是 Node 的「共用型別」論點。單人開發最怕的就是同一件事寫兩遍,而前後端都要讀 data/*.json,型別確實會重複。最後沒改的原因是:這個系列的主題是 Claude 工作流,Go 的 Clean Architecture 分層清楚、編譯期錯誤多,讓 Claude Code 產生的程式碼更容易被驗證——編譯不過就是不過,不會有「跑起來才發現型別錯」的驚喜。這是選型時我最看重的「可驗證性」,也是 Day 1 原則五的延伸。

至於型別重複的問題,我的解法是接受它,但用驗證守住:Day 8 的載入器會在啟動時解析並交叉檢查 data/ 裡每一個 JSON,解析不了就拒絕啟動,Day 16 的 CI 也會跑同一段。

二、前後端分離的邊界:戰鬥在前端,命運在後端

「前後端分離」大家都會說,關鍵是分在哪裡。我畫的線是:

  • 前端(Vue 3 + Canvas):戰鬥完整在瀏覽器執行——波次、目標選取、投射物、傷害,全部是純 TypeScript 引擎,不依賴網路。理由:60 FPS 的戰鬥不能等 API 回應,手機網路抖一下就掉幀是不可接受的;而且引擎不依賴網路,離線也能玩到戰鬥。
  • 後端(Go):劇情狀態機、存檔、戰鬥結果驗證。理由:三條路線的判定必須有唯一權威,不能讓前端各自解讀 graph.json,否則改一次規則要改兩處;結果驗證(例如「5 波打完剩 17 命」是否合理、「這個關卡是不是玩家目前該打的」)雖然粗略,但能擋掉最無腦的竄改。

這條邊界畫成圖會更清楚,也是明天 monorepo 決策的理由:

claude_05_diagram_01

這條線的直接後果是:data/ 裡的遊戲資料前後端都要讀。Go 讀它做模擬與驗證,Vue 讀它做渲染。Day 6 的 monorepo 決策就是被這件事推著走的——資料只能有一份,兩個 repo 就得同步兩份。

另一個後果是 API 會很少:劇情狀態機的推進、存檔的讀寫、戰鬥結果的回報,加起來不到十支端點。這對 30 天的專案是好消息。

三、ADR 範本與第三份 ADR

範本存在 docs/adr/TEMPLATE.md,刻意只有五段,不然沒人會寫:

# ADR-XXXX:<決策標題>

**狀態**:提議中 | 已採納 | 已取代(by ADR-YYYY)
**日期**:YYYY-MM-DD

## 背景
(我們面對什麼問題?有哪些限制:時間、人力、技術?)

## 選項
(列出 2–4 個,各一句話優缺點)

## 決定
(選了哪個,決定性的理由是什麼)

## 後果
(好的、壞的、需要之後補救的)

三份 ADR:0001-frontend.md(Vue 3)、0002-backend.md(Go)、0003-rendering.md(Canvas 2D)。貼第三份,因為它是後面最常被回頭查的:

# ADR-0003:戰場渲染採用 Canvas 2D,引擎層與框架解耦

**狀態**:已採納
**日期**:2026-09-05

## 背景
塔防戰場需要同時繪製路徑、4–8 座塔、最多約 150 個敵人與數十個投射物,
目標 60 FPS,且必須在手機瀏覽器可玩(Day 19)。單人開發、30 天。

## 選項
1. DOM + CSS transform:開發最快,但 100+ 元素時重排成本高,手機明顯掉幀。
2. Canvas 2D:API 簡單、無依賴、可控;需自行管理繪製順序與命中判定。
3. WebGL(PixiJS):效能最好;多一個依賴、學習成本高,對 150 個以下的規模是過度設計。

## 決定
採用 Canvas 2D。引擎放在 `frontend/src/engine/`,純 TypeScript、不 import Vue,
以型別化事件(`events.ts`)對外溝通;Vue 只負責 HUD、塔選單、對話框。
畫布邏輯尺寸固定 960×540,RWD 由 CSS 等比縮放(`useViewport.ts`)。

## 後果
+ 引擎可用 vitest 單元測試,不需要瀏覽器。
+ 未來若要換 WebGL,只需替換 `Renderer.ts`。
− 命中判定、空間查詢都要自己寫(Day 20 的碰撞 bug、Day 26 的空間格由此而來)。
− 文字與 UI 若畫在 Canvas 上不利無障礙,因此 HUD 全部用 DOM。

寫到「後果」那段時我停了很久。「命中判定要自己寫」——當時只覺得是小事,Day 20 會證明它不是。但我不後悔把它寫下來:正因為 ADR 裡有這一行,Day 20 除錯時我很快就知道問題出在自己寫的判定邏輯,而不是懷疑框架。

四、Claude 在選型裡的角色

我想誠實記錄一件事:Claude 沒有幫我「做決定」,它幫我做的是把反方論點講到最強。四個決策我一個都沒改,但每一份 ADR 的「後果」段落都是被反方逼出來的——例如「未來若要換 WebGL 只需替換 Renderer.ts」這條,就是因為 WebGL 的效能論點讓我意識到要預留退路;「HUD 全部用 DOM」則是反方提到無障礙後才加的。

這跟 Day 1 的做法一致:Claude 負責讓思考更完整,方向必須是你的。 如果你只有一個人做專案,找不到人 code review 你的架構,「請 Claude 當反方」是我目前找到最划算的替代方案——它不會客氣,也不會因為你是同事就放水。唯一要注意的是:反方論點會一直有,你得自己決定何時停——我給自己的規則是每個決策最多兩輪,第二輪還沒被說服就定案,否則選型會變成無限迴圈。

小結

今天沒有程式碼,有四份 ADR 與一條前後端邊界。四個核心決策:Vue 3、Go、Canvas 2D、REST,加上 Terraform 這個基礎建設決策,全部都有可被檢驗的理由與被記錄的代價。可複製的要點:選型時先寫下自己的傾向,再請 Claude 反駁,最後把反方論點轉成 ADR 的「後果」——這樣的 ADR 才不是事後追認,而是真正在決策當下留下的證據。明天要處理今天留下的問題:data/ 前後端共讀,repo 該長什麼樣?以及更重要的——怎麼讓 Claude Code 記住這五天的所有決定?

今日產出

  • [x] docs/adr/TEMPLATE.md
  • [x] docs/adr/0001-frontend.md0002-backend.md0003-rendering.md0005-iac.md
  • [x] 前後端邊界定義(戰鬥在前端、劇情/存檔/驗證在後端)

明日預告

Day 06:Monorepo 還是分離倉?專案架構決策與 Claude Code 的專案記憶(CLAUDE.md)設定。


上一篇
Day 04:三條命運之路:多重劇情分支的敘事架構設計(決策樹 × 資料驅動劇情)
下一篇
Day 06:Monorepo 還是分離倉?專案架構決策與 Claude Code 的專案記憶(CLAUDE.md)設定
系列文
奇幻塔防開發實錄:用 Claude 打造一款有靈魂的塔防遊戲6
圖片
  熱門推薦
圖片
{{ item.channelVendor }} | {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言