Code Review(程式碼審查)是保證程式碼品質最有效的手段之一。本章深入探討 Google 的 Code Review 實踐經驗,以及如何在團隊中建立有效的審查文化。
Code Review 的價值#
從團隊協作的角度來看,凡是長期維護、多人參與、程式碼量較大的專案,與品質相關的議題(可讀性、可維護性等)都至關重要。
為什麼許多公司不重視 Code Review#
表面原因: 項目工期緊,沒時間做 Code Review
根本原因: 缺少技術文化傳承
- 即便是大公司的工程師,如果內部沒有良好的 Code Review 實踐,跳槽後也不會在新團隊推行
- 沒有經歷過 Code Review 的人,很難意識到它的重要性
- 需要有經驗的人來帶領
很多人不認可、不推行 Code Review,最直接的原因是沒有經歷過 Code Review,沒有有經驗的人來帶。
從排斥到認可#
新人對 Code Review 的心態轉變
剛進入 Google 時,第一次提交不足百行的程式碼,就被 Leader Review 出了 n 多問題,大部分都非常細節:
- 變數命名不夠達意
- 注釋不夠規範
- 多了一個空行
- 少了一個空格
當時心裡想:「我是來造火箭的,為什麼成天糾結於這些拧螺絲的事情呢?」
後來的體會:
- 來來回回經過多次 Code Review 後,程式碼品質整體提高很多
- 被 Review 出的問題越來越少
- 切身體會到 Code Review 的好處
- 從排斥變得認可
Google 的 Code Review 實踐#
基本概念#
| 術語 | 說明 |
|---|---|
| CL (Change List) | 每次提交的程式碼片段,相當於 GitHub 的 PR |
| Owner | 技術 Leader 或項目負責人 |
| Readability | 證書,表示具有寫出可讀程式碼、符合編碼規範程式碼的能力 |
提交流程#
每個 CL 都需要至少:
- 一個 Owner Approve
- 一個具有 Readability 的同事 Approve
才能提交到程式碼倉庫中。
Readability 認證#
Readability 會細化到每種程式設計語言(如 Java Readability、C++ Readability)。
申請流程:
- 提交至少包含 100 行程式碼、稍微有點複雜的 CL
- 評審委員會指派資深工程師 Review
- 根據修改建議修改程式碼
- 來來回回幾次後,獲得 Readability 認證
即使沒有 Readability,你對同事程式碼的 Review 本身也是有價值的。並非只有 Readability 的人才能 Review 別人的程式碼。
Review 的原則與技巧#
Review 考慮的面向#
雖然沒有統一的 Check list,但主要考察以下方面:
- 程式碼結構 - 是否合理
- 可讀性 - 程式碼是否容易理解
- 正確性 - 業務是否正確
- 完整性 - 例外考慮是否全面
- Bug - 是否有隱藏的 bug
- 線程安全 - 是否安全
- 效能 - 是否滿足業務需求
- 規範 - 是否符合編碼規範
時間管理#
一般情況: 一個 CL 從提交到合併,約需一天時間
耗時較長的情況:
- 比較大的 CL
- 比較複雜的 CL
- 有較多爭議的 CL
- 新手的 CL
最佳實踐#
不提倡太大的 CL。 太大的 CL 對程式碼審查者是很大的負擔,Review 過程會很慢,導致程式碼遲遲提交不上去。
| 情況 | 建議 |
|---|---|
| 複雜的 CL | 寫好文檔,詳細描述前因後果、上下文背景 |
| 爭議多的 CL | 直接當面溝通,更有效率 |
| 新手的 CL | 多改幾次是每個新人都要經歷的過程 |
建設性反饋的藝術#
作為 Reviewer#
態度:
- 把 Code Review 當作一場與未來同事的技術討論
- 在討論過程中感受候選人(或同事)的技術實力
- 切忌像筆試一樣一問一答的單向溝通
技巧:
- 一語中的地提出設計中的缺陷
- 深入地與對方討論
- 給對方充分發揮的機會
如果面試官(或 Reviewer)能一語中的地提出設計中的缺陷,深入地去討論,不僅給對方充分發揮的機會,也會贏得對方對團隊技術的認可。
作為被 Review 者#
心態:
- 不要覺得問多了就是理解能力不夠
- 多問多溝通,面試官(或 Reviewer)不會反感
- 只是悶頭寫程式碼,可能會被認為不善溝通
回應流程:
- 首先明確需求(大部分需求都是籠統、模糊的)
- 通過挖掘、假設、取捨,搞清楚具體需求
- 從最簡單的設計和實現方案做起
- 再講如何基於設計模式進一步最佳化
審查判準與人機分工#
前面的「Review 考慮的面向」較為抽象。要讓新手 Reviewer 也能一致執行,需把它細化成「紅綠燈」判準,並把機械可檢查的部分交給工具。
可勾選的紅綠燈判準#
| 審視點 | 🟢 綠燈 | 🟡 黃燈(討論) | 🔴 紅燈(需修改) |
|---|---|---|---|
| 參數個數 | ≤ 3 | 4-5,考慮參數物件 | > 5,必須拆分 |
| 命名 | 名副其實、見名知意 | 略模糊、可接受 | 無動詞的方法、神秘縮寫 |
| 副作用 | 純查詢無副作用 | 有副作用但有文件 | getter 偷偷改狀態 |
| 抽象層級 | 一個函式只在一個層級 | 偶有混雜 | 高層邏輯混著低層細節 |
| 函式長度 | 一個螢幕內 | 略長但內聚 | 滾不完、多重職責 |
| 嵌套深度 | ≤ 2 層 | 3 層 | > 3 層 |
| 例外處理 | 邊界與異常都覆蓋 | 部分未覆蓋 | 吞例外、用例外控流程 |
紅綠燈不是硬性門檻,而是「該不該開口討論」的提示。黃燈代表「值得在 PR 留一句」,紅燈代表「合併前應處理」。
機械的交給機器,人專注高階#
凡是規則明確、可被程式判定的,都應交給靜態分析與 linter,不該耗費人的注意力。
flowchart LR
PR[提交 PR] --> AUTO[自動化關卡]
AUTO -->|格式/風格| CS[CheckStyle]
AUTO -->|潛在 bug| SB[SpotBugs]
AUTO -->|壞味道/規則| PMD[PMD]
AUTO -->|綜合品質門檻| SQ[SonarQube]
AUTO --> HUMAN[人工審查]
HUMAN -->|設計/風險/知識轉移| MERGE[合併]| 交給機器 | 交給人 |
|---|---|
| 程式碼格式、縮排、命名規則 | 設計取捨是否合理 |
| 未使用變數、空 catch、潛在 NPE | 抽象邊界切得對不對 |
| 圈複雜度、重複率、覆蓋率門檻 | 風險評估與安全隱患 |
| 風格一致性 | 隱性知識與經驗的傳承 |
把「拼螺絲」的檢查自動化後,人的審查才能聚焦在機器看不出來的地方:設計、風險、知識轉移。新人在這類討論中學到的,才是工具教不了的東西。
常見問題與解決#
Q1: 沒時間做 Code Review?#
解決方案:
- 把 Code Review 納入開發流程的必要環節
- 嚴格執行,不流於形式
- 領導層表明堅定的態度和立場
Q2: 新手程式碼問題太多?#
解決方案:
- 這是每個新人都要經歷的過程
- 多改幾次就好了
- 通過嚴格的 Review 快速提升新人程式碼品質
Q3: 爭議太多浪費時間?#
解決方案:
- 對於有爭議的 CL,直接當面溝通
- 避免在 Review 系統中來回留言
- 當面溝通效率更高
Q4: 如何推動 Code Review 文化?#
星星之火可以燎原。 當你成為領導,有了話語權和影響力後,推動在團隊、公司內進行 Code Review,甚至為 Code Review 在整個技術圈中發揚光大貢獻力量。
關鍵策略:
- 從有影響力的一線公司開始推動
- 有經驗的人帶領新人
- 讓團隊切身體會到 Code Review 的好處
- 嚴格執行,不讓 Code Review 流於形式
Code Review 檢查清單#
程式碼 Review 檢查項目
實踐建議#
從自己開始:即使團隊沒有 Code Review 文化,也可以主動請同事 Review 自己的程式碼
建立標準:制定團隊的編碼規範,讓 Review 有據可依
持續改進:定期回顧 Review 中發現的常見問題,轉化為團隊知識
工具支持:使用適當的 Review 工具(如 GitHub PR、Gerrit 等)提高效率
文化傳承:讓有經驗的人帶領新人,傳承 Code Review 的經驗和價值觀