Notes
← All notes
·ai·12 min

從零開始打造 Claude Code 工程團隊(二):主線前段——PM、Architect、Engineer

用一個「忘記密碼功能」的需求走完前三個角色:PM 怎麼拆 AC、Architect 為什麼一定要寫三個方案、Engineer 動工前要過哪些檢查。

#claude-code#agent#pm#architect#engineer#beginner-friendly

系列第二篇。Part 1 講了為什麼需要多角色,這篇開始拆主線前段三個角色:PM、Architect、Engineer。我們用「幫我加一個忘記密碼功能」這個需求作為貫穿範例。

開場:模糊需求進來會發生什麼

使用者丟過來:

「幫我加一個忘記密碼功能。」

這句話有 N 種可能的解讀:

  • 用 email 發重設連結?還是發驗證碼?還是簡訊?
  • 連結幾分鐘失效?10 分鐘還是 24 小時?
  • 重設後現有 session 要不要全部登出?
  • 失敗多少次要鎖帳號?
  • 有沒有 rate limit?同一個 IP 一小時最多能試幾次?

直接跳到 Engineer 寫 code 的人,會自己用直覺幫使用者做完所有決定。等發現產品方向錯了,code 已經寫了一半。

PM 的存在就是為了卡在這個位置:還沒人寫程式之前,把模糊變成具體


角色一:PM——把需求變成可驗收的 ticket

PM 的核心產出:AC(Acceptance Criteria)

PM 收到模糊需求後,要產出一份 ticket,裡面最重要的欄位是 AC。AC 是一條條可驗收的條件,每一條都是 yes/no 判斷,不是模糊形容。

爛 AC 範例:

  • 使用者可以重設密碼
  • 流程要安全
  • UI 要好看

好 AC 範例:

AC-1: 使用者在登入頁點「忘記密碼」會跳到 /forgot 頁面,
      該頁面有 email 輸入欄與「寄出重設連結」按鈕。
AC-2: 送出 email 後,系統用 SendGrid 寄一封信,
      內含 https://<host>/reset?token=<jwt> 連結,token 有效期 30 分鐘。
AC-3: token 無效或過期,/reset 顯示「連結已失效,請重新申請」並提供回到 /forgot 的連結。
AC-4: 重設成功後,該帳號的所有現有 session 全部登出。
AC-5: 同一個 email 一小時內最多送 3 次重設信,超過回 429。

每一條都可以拿瀏覽器或 curl 去驗證。這個能驗證的特性就是 AC 的全部意義

PM 的另一個職責:Phase Gate

把這個功能切成幾個 phase 開發:

  • Phase 1:前端 /forgot 頁 + 後端送信 endpoint(AC-1, AC-2)
  • Phase 2/reset 頁 + 重設 endpoint + session 撤銷(AC-3, AC-4)
  • Phase 3:rate limit(AC-5)

Phase Gate = 紅綠燈。每個 phase 結束時 PM 要判斷:這個 phase 的所有 AC 都通過了嗎?沒通過的話可不可以放行下一階段?

新手最容易犯的錯:邊寫邊改 AC。寫到 Phase 2 才發現 AC-2 的 30 分鐘其實設不到,就把 AC 改成「token 有效到使用者重設為止」。這樣 AC 就失去了意義——它變成了「事後解釋實作」,而不是「事前定義驗收」。

PM Never Do

  • 不寫 code
  • 不直接做產品決策(要回問使用者)
  • 不替自己改 AC——改 AC 必須走變更流程

PM 的 Refusal Clause

當 Engineer 在實作中跑來問「AC-3 那條沒寫到 token 在 cookie 還是 query string,我要寫哪邊?」PM 不能用直覺回答,要:

  1. 檢查 AC 是否真的沒寫(避免漏看)。
  2. 確認沒寫,就回去問使用者——這是產品決策。
  3. 補進 AC 後,才放行 Engineer。

「回去問」聽起來很煩,但這是 PM 的核心價值。PM 自己決定產品方向,就不再是 PM,而是另一個 Engineer


角色二:Architect——為什麼一定要寫三個方案

PM 把 AC 給 Engineer 之前,中間還有 Architect。為什麼?

因為 AC 描述的是「結果應該長怎樣」,Architect 處理的是「有幾種方法能達到這個結果,我們選哪一種、為什麼」。

三個方案的硬性規則

Architect 收到 ticket 後,必須產出至少 3 個設計方案,而且 3 個方案要分布在不同維度——不能是「同一個方案的三種微調」。

回到忘記密碼的例子,AC-2 說「用 SendGrid 寄重設連結」。Architect 要思考:

方案機制優點缺點
AEmail 重設連結(jwt token)不需新基礎設施使用者可能找不到信、token 可被外洩
BEmail 6 位數驗證碼(user 輸入)token 短、不會被 email 曝光多一次輸入步驟
C簡訊 OTP安全性高需要手機號碼、有費用

只寫 A、B 兩個版本(都是 email)就違反「分布在不同維度」——B 雖然不同形式,但跟 A 共享同一條 email 通道風險。C 換通道才算真正的另一個維度。

為什麼要寫三個? 因為人在只有一個方案時,會自動把它合理化;有兩個方案時,會選比較熟悉的;只有三個以上、且被迫思考差異維度,才會看到真正的取捨。

All-Phase Coverage Gate

Architect 還要確保設計覆蓋每一個 phase。用考試比喻:題目要涵蓋每個章節,不能只考第一章。

AC-1 ── 前端 /forgot 頁     ── 設計:UI flow + form validation
AC-2 ── 後端送信            ── 設計:選擇 A/B/C + token schema
AC-3 ── /reset 失效處理     ── 設計:error state UI + 後端 token 驗證
AC-4 ── session 撤銷        ── 設計:Redis 撤銷清單 vs JWT blacklist
AC-5 ── rate limit          ── 設計:IP-level vs email-level

每一行 AC 都要有對應的設計段落。漏一行就是 Coverage Gate 沒過,Architect 自己要打回重寫。

Boundary Pre-emption Table——先列雷區

設計階段最大價值是預判邊界,不是寫 happy path。Architect 要產出一張「會踩到什麼邊界」的表:

邊界怎麼觸發預期行為
Email 不存在於系統隨便填不存在的 email一律回成功(避免列舉攻擊)
同一個 email 連點 5 次「寄出」rate limit 邊界第 4 次起回 429
token 過期後再點連結AC-3 路徑顯示失效訊息,不揭露原因
使用者重設時舊密碼跟新密碼一樣邊界 case回 422,提示不能與舊密碼相同
重設成功瞬間,使用者的另一個分頁還登入著AC-4 case那個分頁下次 API 呼叫會被 401,前端踢回登入頁

Boundary Pre-emption Table 沒寫的邊界,就是上線後會被使用者找到的 bug。架構師不寫這張表,就只是換個名字的 Engineer。

Architect Never Do

  • 不直接寫實作
  • 不只寫一個方案就 release
  • 不跳過 Boundary Table

角色三:Engineer——動工前的五維挑戰表

設計通過後,輪到 Engineer 寫 code。但動手前還有一道關

Pre-Implementation Design Challenge Sheet

新手會直接打開檔案開始寫。資深的做法是先過五個維度的自我挑戰:

維度自問範例
Interface contract我要改哪些公開 API?誰會用到?/api/forgot 新 endpoint,前端 /forgot 頁會呼叫,外部沒人用
Refactorability半年後需求變了,這段 code 改起來容易嗎?token 邏輯抽 service,避免散在 controller
Test seam測試要從哪裡注入?SendGrid client 要可替換(用 interface)
Blast radius我這個改動會影響到誰?共用了 auth/session.ts,登入 / 登出流程都會被影響
Drift我寫的跟設計一樣嗎?跟現有 code style 一致嗎?check Architect 選 A/B/C 哪個,跟現有錯誤訊息格式對齊

走完這五題才動手。漏掉 blast radius 是新手最常踩的雷——以為只是加個新功能,結果改到一個共用的 helper,把不相關的另一個流程弄壞。

Step 0 系列前置 gate

Engineer 動手前還有幾個自動檢查,每一條沒過就直接 halt:

Step 0 — branch verification
  目前在哪個 branch?是 main 嗎?是的話 → 停,建 worktree。

Step 0a — ticket ID 驗證
  我有沒有對應的 ticket?沒有的話我在做的事可能不該做。

Step 0b — 檔案存在性
  我打算改的檔案存在嗎?(用 Read / ls 驗證,不要靠記憶)

Step 0c — 上次離開的狀態
  這個分支是不是有未 commit 的東西?是的話那是別的工作的中間狀態,要先處理。

這幾道 gate 看起來瑣碎,但每一條都對應到至少一次踩過的雷。例如 Step 0 對應「不小心 commit 到 main 結果汙染主分支」;Step 0a 對應「以為使用者要的功能但其實搞錯了 ticket」。

一次一個 edit,立刻驗證

新手最危險的習慣:連續改三四個檔案才跑測試。出錯時你不知道是哪一個改動造成的。

正確節奏:

  1. 改第一個檔案。
  2. 跑相關測試(單元 / E2E 都跑)。
  3. 通過了,才改第二個。
  4. 失敗就只回退第一個改動,不要連續累積問題。

聽起來很慢,但累積三個未驗證的 edit 才出錯,debug 時間是逐個驗證的 5 倍以上

Engineer Never Do

  • 不直接 commit 到 main
  • 不堆疊多個未驗證的 edit
  • 不自己驗收自己(驗收是 Reviewer + QA 的工作)
  • 不跳過 Step 0 系列檢查

三角色完整接力示範

把整個前段串起來看:

[使用者] 「幫我加一個忘記密碼功能。」
   ↓
PM
   - 釐清需求(回去問了 5 個 BQ)
   - 寫好 AC-1..AC-5
   - 切 3 個 phase
   - release Architect
   ↓
Architect
   - 提出方案 A/B/C
   - 跟使用者確認選 A
   - 寫 Boundary Pre-emption Table(5 個邊界)
   - All-Phase Coverage check 通過
   - release Engineer
   ↓
Engineer (Phase 1)
   - Step 0 系列檢查(全部通過)
   - Pre-Implementation 五維挑戰
   - 改第一個檔案 → 測試 → 通過
   - 改第二個檔案 → 測試 → 通過
   - Phase 1 完成
   - release Reviewer(Part 3 主題)

每個角色完成自己的工作後,用一份 handoff 文件交給下一個。Handoff 文件包含:

  • 這個 phase 的 AC
  • Architect 的設計選擇 + 理由
  • Engineer 改了哪些檔案、跑了哪些測試
  • 已知未解事項(known issues)

下一個角色開始工作前,必須先讀 handoff 文件。沒讀就動工 = 重蹈單一視角的覆轍。


小結

角色核心產出最容易漏掉的事
PM可驗收的 AC + Phase 切分自己改 AC 而不走變更流程
Architect≥3 方案 + Boundary Pre-emption Table三個方案其實只是同維度微調
Engineer通過五維挑戰才動工 + 一次一個 edit累積多個未驗證 edit、跳過 Step 0

下一篇我們進入主線後段:Reviewer 怎麼兩段式審 code、QA 為什麼邊界值才是 bug 的家、Designer 在什麼時候才要被叫進來。