---
schemaVersion: 1
slug: gp-211-20260523-google-code-review-guidelines
ticketId: GP-211
lang: zh-tw
title: Google 的程式碼審查規範：不要追求完美，要守住程式碼健康
summary: Google Engineering Practices 的程式碼審查指南，把審查標準從個人口味拉回長期程式碼健康：不追求完美，但每個 CL 都要讓系統比昨天更容易維護。
originalDate: 2026-05-23
translatedDate: 2026-05-24
source: Google Engineering Practices（via X）
sourceUrl: https://google.github.io/eng-practices/review/
author: null
authorshipNote: null
canonicalUrl: https://gu-log.vercel.app/posts/gp-211-20260523-google-code-review-guidelines
status: published
replacementTicketId: null
replacementUrl: null
---

# Google 的程式碼審查規範：不要追求完美，要守住程式碼健康

> **來源:** [Google Engineering Practices（via X）](https://google.github.io/eng-practices/review/)

程式碼審查最怕兩種極端。

一種是橡皮圖章：測試綠了就批准，技術債像浴室霉斑一樣慢慢長出來。另一種是完美主義門神：每個偏好都變成阻擋條件，最後大家看到審查通知就想裝死。

Google Engineering Practices 給的核心標準很乾脆：**程式碼審查的目的，是讓整個系統的程式碼健康隨時間變好。**

不是讓審查者證明自己比較懂，也不是把每個 `CL` 打磨成完美寶石。`CL` 是「變更列表」，意思是一個自洽、正在送審或準備送進版本控制的變更。只要一個 `CL` 明確改善整體程式碼健康，通常就該傾向批准，即使它還不完美。

> **Mogu 真心話：**
>
> 這篇是從一則 X 貼文延伸整理；正文依據是 Google Engineering Practices 的程式碼審查文件。`google/eng-practices` 儲存庫已封存、現在唯讀，所以不要把它當 2026 新文件。它比較像老派工程手冊：工具會變，AI 寫程式碼的比例會變，但「不要讓程式碼庫每天爛一點」還沒被任何框架淘汰。

## 標準：健康勝過完美

Google 的審查標準在拉一條線：一邊是進度，一邊是品質。

如果任何變更都進不去，程式碼庫不會變好，工程師也會學到「不要主動改善系統」。但如果每個「這次先這樣」都放過，程式碼庫會被一堆小捷徑磨壞。

所以核心句是：當一個 `CL` 明確改善系統的整體程式碼健康，審查者應該傾向批准，即使它不是完美。

這不是降低標準，而是把標準從「我喜不喜歡」移到「系統會不會更好維護」。如果只是小修小補，可以標 `Nit:`，讓作者知道那不是阻擋合併的硬要求。

> **Mogu 想補充：**
>
> 程式碼審查最常壞在這裡：把「我比較喜歡」包裝成「這才是工程品質」。九層塔要放鹹酥雞左邊還右邊，是口味；會不會讓未來維護者痛苦，才是工程問題。(¬‿¬)

過了這條線，審查就不再是找碴遊戲。下一個問題變成：一個審查者打開 `CL` 時，到底要先看哪裡，才不會把時間花在最不重要的地方？

---

## 審查者該看什麼

Google 的清單看起來很普通：設計、功能、複雜度、測試、命名、註解、風格、文件。真正的問題只有一個：這個變更會讓未來理解與維護更便宜，還是更貴？

這裡開始，審查者要從門神變成導遊。門神只會站在入口喊不准過；導遊要知道哪條路會走到懸崖，哪條路只是地板顏色不好看。

**設計**先看。這個功能該不該存在？該不該放在這個系統？和既有架構接得起來嗎？如果方向錯了，要早講，不要等作者在錯誤設計上又疊三個 `CL`。

**功能**不只問「作者有沒有做出想做的事」，也要問「這件事對使用者好不好」。使用者包含真正的終端使用者，也包含未來要除錯、修改、呼叫這段程式碼的工程師。UI 變更可能需要展示；並行程式碼則要特別小心死結與競態條件。

**複雜度**很直接：如果下一個工程師很難快速理解，通常就太複雜。過度工程化也是複雜度：現在只要一扇門，卻先設計智慧門禁、多租戶門把策略和可插拔鉸鏈介面。

**測試**也要被審查。測試壞掉時會不會真的失敗？斷言是否聚焦？測試本身會不會變成沒人敢碰的迷宮？

**命名與註解**則是可讀性的基本功。名字要清楚，註解多半解釋「為什麼」，不要重複程式碼正在做什麼。如果程式碼本身看不懂，優先簡化程式碼，不要用註解替混亂貼 OK 繃。

**文件**也不能忘。只要 `CL` 改變建置、測試、發布、API 使用方式或使用者互動，README 與相關文件就該同步更新。

清單本身不難，難的是順序。若第一眼就被變數名稱吸走，審查者很容易在錯的地方用力，像看房子先嫌窗簾顏色，最後才發現地基裂開。

---

## 審查順序：先看方向，再看細節

大 `CL` 不要從第一個檔案第一行開始硬啃。比較好的順序是：先看整體，再看主設計，最後掃細節。

第一步，看 `CL` 描述與整體變更。這個變更本身合理嗎？如果團隊正在移除舊系統，新的 `CL` 卻繼續替舊系統加功能，應該立刻說方向不對，並給替代建議。

第二步，先看最重要的部分。通常幾個檔案就承載主要設計。若設計有問題，先把意見送出去；作者可能已經準備在上面接下一個 `CL`。

第三步，才看剩下的檔案。有時先看測試更快，因為測試會說明這個變更想保證什麼行為。

> **Mogu 真心話：**
>
> 先挑錯字、最後才發現整個設計不該存在，這種審查很勤奮，但像在沉船上擦玻璃。玻璃真的亮了，船也真的還在沉。

方向抓對以後，審查還有另一個敵人：時間。太快會變橡皮圖章，太慢會把整隊卡成停車場。Google 的速度規範，就是在處理這個很煩但很真實的拉扯。

---

## 速度：不是催，是不要卡住整隊

Google 對速度的重點是團隊吞吐量。最佳化目標不是某個工程師寫程式碼的速度，而是整個團隊能不能一起往前走。

審查太慢會讓功能與修 bug 卡住，也會讓大家討厭審查流程。很多「審查太嚴」的抱怨，其實可以靠「回得更快」緩和：同樣要求補測試，三小時後講和三天後講，情緒成本差很多。

一個工作天是回應審查通知的最長時間。這不代表工程師每三分鐘要切一次脈絡；正在深度工作時，可以等自然斷點再看。重點是不要讓作者不知道現在到底卡在哪裡。

`LGTM` 是「看起來沒問題」的縮寫，也就是「看起來沒問題」。Google 也允許 `LGTM` 並附意見：只要程式碼已達審查標準，剩下只是非阻擋項，審查者可以批准並留下小意見。跨時區時，這可以少卡一整天。

慢審查還會傷害程式碼健康，因為團隊壓力會逼人放較差的 `CL` 進去。gu-log 之前寫過的 [AI agent 複雜度棘輪](https://gu-log.vercel.app/posts/gp-198-20260512-garrytan-ai-agent-complexity-ratchet/) 也是同一類警訊：流程一慢，暫時妥協就會變成永久地形。

速度問題解掉一半，剩下那一半更敏感：話要怎麼講。審查意見如果寫得像判決書，技術問題很快就會變成尊嚴問題。

---

## 意見：講程式碼，不講人

好的審查意見要清楚、友善、解釋理由。最重要的是：批評程式碼，不批評作者。

壞寫法像：「為什麼用執行緒？明明並行沒有好處。」好寫法是：「這裡的並行模型增加複雜度，但看不出效能收益；單執行緒會比較簡單。」

兩句技術意思接近，但第一句像審判人，第二句在討論設計。人一旦進入防禦狀態，審查就會從工程討論變成面子戰。

嚴重程度也要標清楚。`Nit:` 是小修；`Optional:` 或 `Consider:` 是建議；`FYI:` 是未來可參考。沒有標清楚時，作者很容易把所有意見都當阻擋項。

如果審查者看不懂程式碼，通常應該要求把程式碼改清楚，而不是只在審查工具裡補一段解釋。未來讀程式碼的人看不到那段留言。

真正的考驗通常不在第一則意見，而在作者回來說「不同意」的那一刻。那一刻，審查者要守住品質，也要先放下勝負。

---

## 反駁與衝突：不要讓 CL 卡死

作者反駁審查意見很正常。第一步不是審查者硬起來，而是先確認作者是不是對的。作者更靠近那段程式碼，也可能掌握更多脈絡。

如果作者說得通，就放下那個議題。如果作者不對，審查者要補上更好的理由，說明為什麼這個修改值得額外工作。

「之後再清」是最危險的反駁之一。經驗上，除非清理立刻接著發生，越晚越不可能發生。不是工程師懶，而是大家永遠有下一件事。

如果 `CL` 引入新的複雜度，通常就該在送出前處理，除非是真的緊急狀況。若只是暴露既有問題，至少要開 issue 或 TODO，讓問題不要消失在空氣裡。

吵到解不開時，應該改成面對面或視訊討論，然後把結論記回 `CL`。仍無法解決，就升級給技術負責人、維護者或工程主管。重點是：不要讓 `CL` 因為兩個人談不攏而永遠卡著。

到這裡，審查者的責任很清楚了。但一個順的審查不是審查者單方面表演。作者也在決定這場對話會像修車，還是像考古。

---

## 作者端：好 CL 是替審查者省腦力

這套規範也教作者怎麼讓審查更順。好的 `CL` 不是把所有東西塞進一個大包裹，丟到審查者桌上說「麻煩看一下」。那比較像把整個廚房的抽屜倒在地上，然後請人幫忙找一支湯匙。

第一，寫好 `CL` 描述。它會變成版本控制歷史的一部分，未來可能被很多人讀到。好的描述要回答兩件事：做了什麼，以及為什麼做。

壞描述像「Fix bug」「Fix build」「Phase 1」。這不是簡潔，是沒有資訊量。未來工程師看到只會開始考古。

第二，寫小 `CL`。小 `CL` 比較快被審查、比較容易看仔細、比較不容易引入 bug，也比較容易合併和回滾。

「小」不是單純行數，而是自洽：只處理一件事，包含相關測試，送出後系統仍然能正常運作。Google 給的務實尺度是：100 行通常合理，1000 行通常太大；審查者可以只因為 `CL` 太大就要求拆分。

收到意見後，作者也不要把批評當成人身攻擊。真正的修法通常是把程式碼改清楚；只有程式碼和註解都不需要改時，才用審查工具回覆解釋。

最後，還有一個幾乎每個團隊都會濫用的逃生門：緊急狀況。這個詞一旦變寬，前面所有健康、速度、友善、拆小 `CL` 的規範都會被一句「今天真的要上」撞飛。

---

## 緊急狀況不是「今天想上」

Google 對緊急狀況定義很窄：小變更，而且是在處理重大上線阻塞、正式環境中嚴重影響使用者的 bug、緊急法律問題或重大安全漏洞。

只有這種情況，審查流程才應該把速度放到最優先，品質標準也暫時集中在正確性：這個變更是否真的解決緊急狀況。事件結束後，仍然要補完整審查。

不算緊急狀況的例子包括：想這週上線而不是下週、週五下班前想合併、主管因為軟期限說今天一定要進、審查者在別的時區睡覺。

這段之所以重要，是因為每個技術債故事都很少從「今天開始破壞系統」開始。它通常從一句很合理的話開始：這次先讓過，之後再補。講久了，橡皮圖章和完美主義門神都會回來，只是換了制服。

---

## 結語

這份指南繞了一圈，最後又回到開頭那兩個極端：橡皮圖章會讓程式碼庫慢慢發霉，完美主義門神會讓改善永遠進不了門。

`LGTM`、`CL`、`Nit:` 這些術語都只是工具。真正的工程倫理是：每一次審查都在決定程式碼庫明天會更好，還是更難救。

嚴格不是目的，速度也不是目的。嚴格要服務程式碼健康，速度要服務團隊流動。意見要讓人能改，描述要讓未來能懂。

最好的程式碼審查不是把 `CL` 磨成完美寶石，而是讓系統每天比昨天更容易理解、更容易維護。橡皮圖章太鬆，門神太硬；真正好的審查，是知道什麼時候放行，也知道什麼時候站住。
