CodeReview 的經驗和原則

張家界國家森林公園(圖)

資深的程式設計師都知道 Code Review 可以對程式碼品質,程式碼規範,團隊程式碼能力提升帶來很大的提升,還有著名的技術專家「左耳朵耗子」也說過:

我認為沒有 Code Review 的公司都沒有必要呆(因為不做 Code Review 的公司一定是不尊重技術的)

  • 出自《程式設計師的練級攻略 – 修養篇》

國外很多技術公司都非常重視 Code Review 也都做的特別好,例如 Google,亞馬遜,但是中國很多公司在踐行 Code Review 的時候卻是步履蹣跚,步步艱難,選用的方法不對,最終導致事倍功半的結果,總結一下我見過的幾種情況:

  • 因為 Code Review 導致團隊成員之間相互指責,團隊凝聚力產生間隙
  • Code Review 形式化,沒有提升程式碼品質,減少 bug,反而降低開發效率
  • Code Review 確實產生了效果,但是因為流程太重,導致團隊效率降低

我們也在踐行 Code Review,探索的路上也遇到一些障礙和經驗,總結分享一下,如果你也遇到這些問題,或許可以花一點時間讀一讀這篇文章,說不定會有幫助。

Code Review 能帶來哪些好處,本文就不說了,大家都很熟悉了,本文主要簡單說一下 Code Review 有哪幾個基本的共識和原則:

  1. Code Review 高效的原則是用機器去做大部分的事情
  2. Code Review 的時機(天時地利人和)
  3. 推行 Code Review 的關鍵原則

Code Review 高效的原則是用機器去做大部分的事情

不同的語言的格式和風格都是比較固定的,例如我最熟悉的 Java 語言常見的風格有以下幾種規範:

  1. Order Java SE 的標準規範://www.oracle.com/technetwork/java/codeconvtoc-136057.html
  2. Google Java 開發規範: //google.github.io/styleguide/javaguide.html
  3. 阿里巴巴 Java 開發手冊://github.com/alibaba/p3c (中國常用)

還有我最近常用的 Ruby 語言,官方所推崇的幾種風格規範:

  1. Ruby Style Guide://github.com/rubocop-hq/ruby-style-guide
  2. Airbnb Ruby Style://github.com/airbnb/ruby

但凡是標準規範都是比較機械化的條條框框,應該交給機器去檢查(常用的工具由:P3C,Rubocop,SonarQube 等),機器靜態掃描效率不僅比人高出一個數量級,而且非常嚴謹,不容易出錯,甚至可以武斷的說:所有的自動化工具的本質,都是為了要減少對人的依賴性,因為人本身是具備很多種不確定性,所以並不適合做一些需要確定性並且反覆重複的事情

Code Review 的時機(天時地利人和)

在以往的工作經驗中,Code Review 越是靠左移,修改程式碼的成本越低,開發人員的修改意願也就越高,那什麼叫左移?

我們看一下軟體開發的流水線和個人認為最合理的 code review 時機:

常規的開發流水線

軟體工程的開發流水線(圖)

從流水線上來說,有些人會在臨近上線,在靠右的地方合併 master 的時候才進行 code review,這個時候修改成本就很高,因為程式碼已經測試過,如果因為 code review 有問題需要重新修改程式碼,那麼功能本身又要回歸測試,佔用的測試雙倍的時間,對於人力資源是雙倍的浪費,因為已經臨近上線,卻因為 code review 被打回,開發人員願意重構程式碼的意願也會很低,如果明明發現問題,又因為上線壓力,不打回不符合規範的程式碼,那麼久而久之大家失去對 code review 的敬畏心理,code review 也會慢慢變成形式化,應用發布流程而已,既不能提高程式碼品質,降低系統 Bug,也不能提升開發人員的水平,反而降低的開發團隊的效率,所以選擇在上線前進行 code review 不是一個好主意,所以從性價比上來說 code review 最好的時機應該是在 功能分支自測完成後,需要合併到 develop 分支申請提測前 通知項目組成員對增量的程式碼進行 code review。

所以,程式碼審查要高效的話,核心就是要追求快速回饋,越早發現程式碼問題修改的成本就越低,具體參考下圖:

極客時間-研發效率破局之道(圖)

這裡需要注意的是,程式碼在經過機器掃描後(這裡有一個技巧就是可以在 GitLab CI 加入自動的程式碼風格檢查,程式碼靜態掃描是一個高頻操作,一天可能會有幾十,甚至上百次的 Commit,如果接入 GitLab CI 實現自動化靜態掃描,大家不需要在自己本地執行靜態掃描,那麼效率也會大大的提升),項目組成員只需要把注意力放在 程式碼邏輯結構,功能設計的可維護,可擴展性 等機器不容易發現問題的地方上,然後就完成程式碼審查。因為程式碼還未提測,所以就算 Merge Request 不合格被打回後,因為還未提測,也不會佔用測試人員的資源,開發人員的修改意願也會更高,總體來說是可以達到高效和品質的要求

Code Review 要計入開發的工作量

很多團隊不做 code review 都有一個共同的原因是覺得浪費時間,結果導致糟糕的程式碼合併入庫,頻繁出現線上問題,然後開發人員疲於奔命的去修複線上事故 BUG,雖然短期來看功能是快速上線了,但是算上復工的時間,長期來看整體的交付周期還是被拉長了,整體還是低效的,而且糟糕的生產品質人很容易打擊開發人員的持續生產高品質程式碼的信心,所以將 code review 計入開發的工作量是重視長期利益的一種做法,也是 code review 能夠成功落地的重要前提,從團隊管理的角度來說,不計入工作量的事情就不會被重視,不被重視的話那麼 code review 最終在團隊只會被廢棄或者流於應付形式,並未發揮作用。也是很多團隊推行 code review 失敗的原因。

推行 Code Review 的關鍵原則

想要在審核程式碼的時候,避免團隊成員因為某些模糊不清的細節爭論不休的情況,那麼就要提前讓團隊建立對程式碼審核的原則和方法達成共識,我就曾經見過團隊的技術人員在程式碼審核的時候因為某個函數方法的實現方式爭吵不休,各自都認為自己的實現是正確的,那麼提前建立一下這種共識:

相互尊重原則

站在程式碼作者的角度:

  1. 審核人花費時間和精力閱讀他不熟悉的程式碼,並且幫忙指出程式碼中的問題來幫助程式碼作者提高,程式碼作者應該儘可能的為審核人提供配合和方便
  2. 程式碼作者提交高品質的程式碼,就是對審核人和審核團隊的最基本尊重(提交一堆亂如麻花的程式碼,沒有自測錯誤百出的程式碼是極度不負責任的表現)
  3. 最好要有清晰的 commit 歷史,讓人可以一目了然程式碼的提交內容,如果程式碼過度複雜,那麼就需要和審核人面對面溝通,才能足夠的高效

站在程式碼審查者的角度:

  1. 一定要懂得相互尊重,提出建議要懂得換位思考,考慮程式碼作者的感受,不要用主觀的批評或者情緒化的語氣指責團隊的同事
  2. 提出程式碼改進建議,必須是基於事實,或者明確的程式碼規範文檔,不可強行把個人喜好強加在對方身上(例如用不同的語法實現相同的功能 for/while )
  3. 不要鑽進程式碼的牛角尖和摳細節,人工審查更多的要把精力放在程式碼邏輯,功能設計等無法掃描的問題上
建立共識

站在團隊的角度:

  1. code review 的目標長期來看,收益是提升團隊的項目品質,減少團隊陷入反覆修復 bug 的困境中,讓團隊有機會去面對更多的挑戰
  2. code review 對個人和團隊而言都是成長的機會,放下不必要的自尊心,要用開放的包容的心態去接受不同的意見,取其精華

總結

以上就是我個人和團隊在 code review 中的實踐和總結,Code Review 關鍵還是要結合團隊的情況選擇合適的審查方式,如果團隊追求敏捷開發,快速迭代那麼集中式的程式碼審查會可能就不太適合你們當前的團隊,可能項目成員 1 對 1 的結對編程可以更加高效的完成程式碼審查,每個團隊的發展階段不同,適用的 GitFlow 開發流程也不同,反正沒有最好的工具,最有最合適的工具。