代碼評審賦魅

先來看一個令無數技術Leader聞風喪膽的項目「死亡」三角,業務壓力引起代碼質量降低,代碼質量降低引起開發效率降低,開發效率降低又加劇了業務壓力,最終致使業務壓力山大,乃至項目爛尾。如何破解?方法有不少,像精簡業務需求、增長開發人手、升級技術架構等,不少時候須要多管齊下,但凡打掉這個「死亡」三角中的任何一角,就能終止這個惡性循環,甚至逆轉爲良性循環。html

代碼評審(Code Revew,簡稱CR)的首要打擊目標顯然是「爛代碼」。避免「爛代碼」的最好時機是寫代碼的時候,其次是代碼評審的時候。IBM 的 Orbit 項目有 50 萬行代碼,使用了 11 級的代碼檢查(其中包含代碼評審),結果是項目提早交付,而且只有一般預期錯誤的 1%。一份對 AT&T 的一個 200 多人組織的研究報告顯示,在引入代碼評審後,生產率提升了 14%,缺陷減小了 90%。那到底什麼是代碼評審?如何進行代碼評審?繼續往下看。git

1 CR 祛魅

我我的認爲代碼有這幾種級別:1)可編譯,2)可運行,3)可測試,4)可讀,5)可維護,6)可重用。經過自動化測試的代碼只能達到第3)級,而經過CODE REVIEW的代碼少會在第4)級甚至更高。

—— 陳皓程序員

下面 8 條有關 CR 的闡述,你以爲哪些是正確的?github

  1. 搞形式主義,存粹是浪費時間
  2. CR 是保證程序正確性的手段
  3. CR 是保證代碼規範的手段
  4. CR 是 Leader 的事,跟我不要緊
  5. 我只看指給個人 CR,其餘 CR 跟我不要緊
  6. 沒有時間 CR,直接 Merge
  7. CR 必須一行不落從頭看到尾
  8. CR 必須一次完成

———————————————————————————————— 請仔細思考 60 秒shell

3...2...1...時間到,你的答案是幾條?很抱歉,在我看來,沒有一條是正確的。一、四、五、6 是送分題,顯然都是錯誤的。7 是眉毛鬍子一把抓,CR 就像讀書,不是全部的書都適合精度,也不是全部的代碼都須要評審。8 是任務心態,爲了 CR 而 CR,CR 的目的不是完成 CR,而在於提高代碼質量,你寫代碼時也不會一次完成全部功能。比較有爭議的是 2 和 3,誠然,正確性和代碼規範都是 CR 要關注的方面,但這並不意味着 CR 要保證正確性和代碼規範(CR 也無法保證),保證正確性的主要手段是測試(單元測試,集成測試,契約測試,功能測試,自動化測試等),而保證代碼規範主要依靠代碼規範檢查工具(像經常使用的 checkstyle 和 PMD)。編程

CR 究竟是什麼?依我所見,CR 本質上是一種討論,一種嚴肅的、專業的、異步的以文字形式呈現的討論,隨意性和情緒化是 CR 的大忌。什麼叫隨意性?未經審視的評論。什麼叫情緒化?因時而異,因人而異。高水平的 CR 首先要忘掉本身。架構

2 知:CR 的三重境界

技術水平決定了 CR 的下限,認知高度決定了 CR 的上限。因此說 CR 水平高不高,最終仍是看認知水平。認識 CR 有三重境界,分別是執行層、團隊層和文化層。框架

2.1 執行層:昨夜西風凋碧樹,獨上高樓,望盡天涯路

第一層爲執行層,顧名思義就是經過如何作來認識 CR。如下列舉 CR 時需重點關注的六個方面,並輔以相應的例子便於理解。異步

1)關注代碼規範。命名是第一位的,一個使人費解的命名背後每每隱藏着一個設計紕漏。其餘諸如空白字符、換行、註釋等問題,也會影響代碼的可讀性和可理解性。分佈式

2)避免重複代碼。編程法則第一條,Don't repeat yourself. 重複代碼是萬惡之首,重複代碼人人得而誅之!

3)下降圈複雜度。什麼是圈複雜度?簡單來講就是代碼中 if/case/for/while 出現的次數。圈複雜度越高,BUG 率越高。若是一個方法的圈複雜度達到 3 或者更高,那麼 CR 時就要多看兩眼。

4)關注性能問題。性能問題雖然不常見,可一旦暴雷每每就是大問題。CR 時看到循環,記得多留一個心眼。

5)關注分佈式事務。涉及遠程服務調用,或者跨庫更新的場景,都應考慮是否存在分佈式事務問題,以及適用何種處理方式,是依賴框架保證強一致性,仍是記錄異常數據保證最終一致性,抑或是直接忽略?

6)關注架構設計。代碼有代碼規範,架構有架構規範。面對一個新功能的 MR(Merge Request),除了檢查架構規範,還應推敲其架構設計,好比是否符合整潔架構三原則,無依賴環原則,穩定依賴原則,穩定抽象原則。

除了線上 CR,還有一種特殊的線下 CR 方法,就是跳過 MR,直接拉取代碼,進行總體 CR,將評審意見在代碼中標記爲 TODO 或者 FIXME,而後 @ 相關開發進行改進。這樣作最大的好處,就是避免受單個 MR 的影響,掉入只見樹木不見森林的陷阱。

2.2 團隊層:衣帶漸寬終不悔,爲伊消得人憔悴

接下來再看第二層,如何從團隊視角認識 CR。前面說了,CR 本質上是一種討論,培根說過「讀書令人完整,討論令人完備」,從我的到團隊,CR 分別意味着什麼?

  • 提高自我覺察能力:這是從我的視角來看,當你知道你寫的代碼會有另外一雙眼睛來審閱,那你寫代碼時就會保持一份警覺,放棄天知、地知、我知、你不知的幻想,認認真真寫好每一行代碼。
  • 創建良好開發節奏:這是從團隊視角來看,CR 是團隊的同步器,每一個人既是本身 MR 的做者,又是別人 MR 的評審者,從 MR 到 CR,再從 CR 到 MR,構成了每一個工做日最動聽的樂章。
  • 高頻次的團隊活動:這也是從團隊視角來看,CR 既然是討論,那麼就不只僅是一我的的事,而是一種團隊活動,一種高頻次、高質量、低成本的極具性價比的團隊活動。

2.3 文化層:衆裏尋他千百度,驀然回首,那人卻在,燈火闌珊處

最後是文化層,CR 既是傳幫帶文化的重要組成,又是工程師文化的平常體現。

  • 傳幫帶文化的重要組成:資深工程師 CR 初級工程師的代碼,能夠給予高頻次、高質量的指導;初級工程師 CR 資深工程師的代碼,能夠欣賞、學習高手如何把玩代碼,取其精華去其糟粕。
  • 工程師文化的平常體現:協做、高效、進取、影響力,這些在各大互聯網公司的工程師文化中頻頻出現的關鍵詞,無一不與 CR 緊密相連。不誇張的說,工程師文化香不香,就看 CR 作的好很差。

3 行:CR 高效之法

認識完 CR,咱們再來探討一下如何高效的進行 CR。在我看來,高效 CR 首先有賴於如下幾個客觀條件和主觀條件。

客觀上來看,和諧的工程師文化清晰的代碼規範是高效 CR 的兩塊基石。所謂和諧的工程師文化,就是說團隊對代碼秉持開放的心態,不藏着掖着,以寫好代碼爲榮,以寫壞代碼爲恥,持續關注代碼質量。而清晰的代碼規範,一方面提升了代碼的可讀性,另外一方面也統一了編碼風格,極大的減小了不一樣代碼風格對評審者注意力的干擾。

主觀上來看,對評審者而言,第一要端正態度,保持謙卑的心態,人非聖賢孰能無過,擇其善者而從之,其不善者而改之。第二要謹記評審的對象是代碼,而不是人,你寫下的每一條評審意見都應基於客觀事實和數據,作到有理有據,不帶我的情緒。

基於我多年 CR 的實操經驗,結合Google Code Review Developer Guide,我整理了一些高效 CR 的最佳實踐,供你參考:

  • 依據我的偏好天天固定幾個時間段專門用於 CR,個人習慣是出門前和下班前。CR 耗費的腦力絲絕不亞於編碼,甚至更高,CR 過程當中須要高度集中注意力。清醒的頭腦和無干擾的環境,是提出高質量的評審意見的祕訣。
  • 除了固定時間段,任務切換期間也是 CR 的好時機。
  • 每次 CR 儘可能控制在 15~30 分鐘之內,超過 30 分鐘應休息一會。
  • 收到 MR 以後,先判斷一下 MR 的性質,若是是 Bug Fix 類型的 MR,應儘快評審,若是是新功能 MR,則能夠等待下一個 CR 窗口。
  • 從收到 MR 到 CR 結束,最長不要超過 1 個工做日。
  • 開始 CR 以前先要搞清楚 MR 要解決的問題背景。
  • CR 就像讀書,先看目錄(改動的文件列表),再精讀重點章節(包含核心業務邏輯的代碼),最後掃讀剩餘章節。
  • 若是改動的文件數量較多,能夠打開 IDE,切換到源分支,方便在 CR 過程當中隨時打開相關代碼進行閱讀。
  • 評審覈心代碼時,若是發現嚴重問題,應馬上終止 CR,找 MR 提交者當面討論。
  • 若是 MR 提交者對評審意見提出異議,評審者應找提交者當面討論,避免在評論區互踢皮球。
  • 合併代碼以前應確保全部評審意見都被妥善處理。
  • 記得點贊。

4 小結

2019 年 Stack Overflow 的一份調查報告顯示,超過 7 成的程序員會把 CR 當作平常工做的一部分,近 1/3 的程序員每週在 CR 上花費 2~3 個小時,還有 1/3 的程序員每週花費 4~5 個小時。內心默默算一下,你是在拖後腿仍是領路者?若是你還沒作過 CR,那麼趕忙行動起來;若是你已經在 CR,很好,請繼續保持。一花一世界,一葉一菩提,碼中自有乾坤。CR,走起!

5 參考

相關文章
相關標籤/搜索