Code Review:審什麼、什麼時候擋下來
依嚴重程度分層的審查順序、每一層的具體檢查項目、一份可以貼給 AI 的自審 prompt,以及什麼情況必須退回。
0. Review 在做什麼
不是在比個人喜好,不是在挑微優化,不是在炫技。
是在確認:架構一致、資料流可預測、抽象邊界正確、六個月後還維護得動。
如果一個改動讓短期速度變快、但讓系統變難理解,它應該被退回。
1. 審查順序(照嚴重度)
由上往下。上面的沒過,下面的不用看。
1. 資安 金鑰、XSS、權限
2. 資料正確性 資料流、狀態模型、race condition
3. 架構 分層、依賴方向、責任
4. 型別 any、斷言、API 型別
5. 無障礙 鍵盤、焦點、對比、語意
6. 設計系統 token、變體、設計頁
7. 效能 不必要的重繪、包大小
8. 可讀性 命名、註解、檔案長度
2. 每一層看什麼
資安(必擋)
- 有沒有金鑰進到會打包給前端的檔案?
-
{@html}/innerHTML的來源是不是可信的? - 外部來的 URL 有沒有檢查 scheme?
- 每個 API 端點有沒有驗證擁有權(不只是登入)?
- 錯誤訊息有沒有洩漏堆疊、路徑、SQL?
- 重導向參數有沒有驗證?
資料正確性(必擋)
- 資料是不是往下流、事件往上流?
- 有沒有同一份狀態存在兩個地方?
- 有沒有布林爆炸?(
isLoading+isError+data) - 非法狀態是不是「無法被表達」,而不是「我們保證不會發生」?
- 非同步操作有沒有處理競態?(快速切換兩次分頁,會不會顯示舊資料?)
- 有沒有 module-level 可變狀態出現在會 SSR 的檔案裡?
架構
- UI 元件有沒有 fetch?
- 領域邏輯有沒有漏進 UI 元件?
- 頁面有沒有商業規則?
- 有沒有循環依賴?
- 同一段邏輯是不是被複製了第三次?(第二次可以忍,第三次要抽)
型別
- 有沒有
any? - 有沒有為了消錯而用的
as? - API 回應有沒有型別,而且在邊界驗證過?
- 複雜狀態有沒有用 union?
型別標注不等於型別安全。response.json() as User 是騙自己 —— 執行期什麼都可能回來。
無障礙
- 鍵盤走得完嗎?
- focus 看得見嗎?
- 圖示按鈕有
aria-label嗎? - 顏色是不是唯一的資訊管道?
- 表單欄位有
<label>嗎? - 彈窗有沒有焦點鎖定與 Escape?
設計系統
- 有沒有寫死的顏色、字體、間距、圓角?
- 新的變體有沒有加到設計頁?
- 有沒有繞過設計系統做局部覆寫?
grep -rn "#[0-9a-fA-F]\{3,8\}" src/lib/modules/
grep -rnE "(margin|padding|gap): *[0-9]+px" src/lib/modules/
效能
-
useMemo/useCallback是有量測過才加的嗎?(沒有就拿掉) - 有沒有在 render 裡做昂貴計算?
- 新增的依賴有多大?(
npx bundle-phobia <pkg>) - 圖片有沒有尺寸與現代格式?
可讀性
- 檔案能用一句話描述嗎?
- 有沒有註解在翻譯程式碼?
- 命名有沒有無意義的縮寫?
3. 什麼時候必須退回
- 架構規則被違反且沒有寫明理由
- 狀態模型不清楚
- 繞過設計系統
- 型別安全被犧牲
- 有資安問題
「先合再說,之後再修」在這五項上不成立。 這五項的技術債是複利。
4. 怎麼給意見
✗ 這樣寫不好
✓ 這裡的 fetch 放在 UI 元件裡,這個元件就沒辦法在別的地方重用了。
建議搬到 services/order.ts,元件收整理好的資料當 props。
✗ 為什麼不用 X?
✓ 有考慮過 X 嗎?它的好處是 A,代價是 B。如果你已經評估過選了現在這個做法,
可以在註解裡寫一句理由,避免下一個人再問一次。
區分「必須改」與「可以討論」:
[必改] 這個 API key 會被打包進前端
[建議] 這個函式可以拆成兩個,但不影響正確性
[疑問] 這裡為什麼要 setTimeout 0?
5. 給 AI 的自審 prompt
請針對剛才的改動做一次 code review,照這個順序,逐項回答「有 / 沒有」,
有問題的直接修,並說明你改了什麼:
1. 資安:金鑰外洩、XSS、缺少權限檢查、錯誤訊息洩漏內部資訊
2. 資料流:狀態重複、布林爆炸、非法狀態可被表達、競態
3. 架構:UI 元件 fetch、領域邏輯漏進 UI、循環依賴、第三次複製
4. 型別:any、消錯用的 as、未驗證的 API 回應
5. 無障礙:鍵盤、focus、label、aria-label、顏色單一管道
6. 設計系統:寫死的顏色與間距、沒進設計頁的變體
7. 效能:沒量測就加的 memo、render 裡的昂貴計算
8. 可讀性:翻譯型註解、無意義縮寫、超過 250 行的元件
不確定的地方列出來問我,不要猜。
6. 通過的意思
這次改動之後,系統比之前更容易理解。
不是「沒有明顯錯誤」,是「更好懂了」。