Code Review 失敗後總結的幾個實踐技巧

{"type":"doc","content":[{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"資深的程序員都知道 Code Review 可以對代碼質量,代碼規範,團隊代碼能力提升帶來很大的提升,還有著名的技術專家“左耳朵耗子”也說過:"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"blockquote","content":[{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"我認爲沒有 Code Review 的公司都沒有必要呆(因爲不做 Code Review 的公司一定是不尊重技術的)"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"- 出自《程序員的練級攻略 - 修養篇》"}]}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"國外很多技術公司都非常重視 Code Review 也都做的特別好,例如 Google,亞馬遜,但是國內很多公司在踐行 Code Review 的時候卻是步履蹣跚,步步艱難,選用的方法不對,最終導致事倍功半的結果,總結一下我見過的幾種情況:"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"bulletedlist","content":[{"type":"listitem","content":[{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"因爲 Code Review 導致團隊成員之間相互指責,團隊凝聚力產生間隙"}]}]},{"type":"listitem","content":[{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"Code Review 形式化,沒有提升代碼質量,減少 bug,反而降低開發效率"}]}]},{"type":"listitem","content":[{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"Code Review 確實產生了效果,但是因爲流程太重,導致團隊效率降低"}]}]}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"我們也在踐行 Code Review,探索的路上也遇到一些障礙和經驗,總結分享一下,如果你也遇到這些問題,或許可以花一點時間讀一讀這篇文章,說不定會有幫助。"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"Code Review 能帶來哪些好處,本文就不說了,大家都很熟悉了,本文主要簡單說一下 Code Review 有哪幾個基本的共識和原則:"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"numberedlist","attrs":{"start":"1","normalizeStart":1},"content":[{"type":"listitem","content":[{"type":"paragraph","attrs":{"indent":0,"number":1,"align":null,"origin":null},"content":[{"type":"text","text":"Code Review 高效的原則是用機器去做大部分的事情"}]}]},{"type":"listitem","content":[{"type":"paragraph","attrs":{"indent":0,"number":2,"align":null,"origin":null},"content":[{"type":"text","text":"Code Review 的時機(天時地利人和)"}]}]},{"type":"listitem","content":[{"type":"paragraph","attrs":{"indent":0,"number":3,"align":null,"origin":null},"content":[{"type":"text","text":"推行 Code Review 的關鍵原則"}]}]}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"heading","attrs":{"align":null,"level":3},"content":[{"type":"text","text":"Code Review 高效的原則是用機器去做大部分的事情"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"不同的語言的格式和風格都是比較固定的,例如我最熟悉的 Java 語言常見的風格有以下幾種規範:"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"numberedlist","attrs":{"start":"1","normalizeStart":1},"content":[{"type":"listitem","content":[{"type":"paragraph","attrs":{"indent":0,"number":1,"align":null,"origin":null},"content":[{"type":"link","attrs":{"href":"https://www.oracle.com/technetwork/java/codeconvtoc-136057.html","title":""},"content":[{"type":"text","text":"Order Java SE 的標準規範:https://www.oracle.com/technetwork/java/codeconvtoc-136057.html "}]}]}]},{"type":"listitem","content":[{"type":"paragraph","attrs":{"indent":0,"number":2,"align":null,"origin":null},"content":[{"type":"link","attrs":{"href":"https://google.github.io/styleguide/javaguide.html","title":""},"content":[{"type":"text","text":"Google Java 開發規範: https://google.github.io/styleguide/javaguide.html"}]}]}]},{"type":"listitem","content":[{"type":"paragraph","attrs":{"indent":0,"number":3,"align":null,"origin":null},"content":[{"type":"link","attrs":{"href":"https://github.com/alibaba/p3c","title":""},"content":[{"type":"text","text":"阿里巴巴 Java 開發手冊:https://github.com/alibaba/p3c "}]},{"type":"text","text":" (國內常用)"}]}]}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"還有我最近常用的 Ruby 語言,官方所推崇的幾種風格規範:"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"numberedlist","attrs":{"start":"1","normalizeStart":1},"content":[{"type":"listitem","content":[{"type":"paragraph","attrs":{"indent":0,"number":1,"align":null,"origin":null},"content":[{"type":"link","attrs":{"href":"https://github.com/rubocop-hq/ruby-style-guide","title":""},"content":[{"type":"text","text":"Ruby Style Guide:https://github.com/rubocop-hq/ruby-style-guide"}]}]}]},{"type":"listitem","content":[{"type":"paragraph","attrs":{"indent":0,"number":2,"align":null,"origin":null},"content":[{"type":"link","attrs":{"href":"https://github.com/airbnb/ruby","title":""},"content":[{"type":"text","text":"Airbnb Ruby Style:https://github.com/airbnb/ruby"}]}]}]}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"但凡是標準規範都是比較機械化的條條框框,應該交給機器去檢查(常用的工具由:P3C,Rubocop,SonarQube 等),機器靜態掃描效率不僅比人高出一個數量級,而且非常嚴謹,不容易出錯,"},{"type":"text","marks":[{"type":"strong"}],"text":"甚至可以武斷的說:所有的自動化工具的本質,都是爲了要減少對人的依賴性"},{"type":"text","text":",因爲人本身是具備很多種不確定性,所以並不適合做一些需要確定性並且反覆重複的事情"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"heading","attrs":{"align":null,"level":3},"content":[{"type":"text","text":"Code Review 的時機(天時地利人和)"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"在以往的工作經驗中,"},{"type":"text","marks":[{"type":"strong"}],"text":"Code Review 越是靠左移,修改代碼的成本越低,開發人員的修改意願也就越高"},{"type":"text","text":",那什麼叫左移?"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"我們看一下軟件開發的流水線和個人認爲最合理的 code review 時機:"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"image","attrs":{"src":"https://static001.geekbang.org/infoq/fc/fc74675de2b45bec1cd1bbd4efce0ad3.png","alt":"常規的開發流水線","title":null,"style":null,"href":null,"fromPaste":true,"pastePass":true}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"軟件工程的開發流水線(圖)"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"從流水線上來說,有些人會在臨近上線,"},{"type":"text","marks":[{"type":"strong"}],"text":"在靠右的地方"},{"type":"text","text":"合併 master 的時候才進行 code review,這個時候修改成本就很高,因爲代碼已經測試過,如果因爲 code review 有問題需要重新修改代碼,那麼"},{"type":"text","marks":[{"type":"strong"}],"text":"功能本身又要回歸測試,佔用的測試雙倍的時間,對於人力資源是雙倍的浪費"},{"type":"text","text":",因爲已經臨近上線,卻因爲 code review 被打回,開發人員願意重構代碼的意願也會很低,如果明明發現問題,又因爲上線壓力,不打回不符合規範的代碼,那麼久而久之大家失去對 code review 的敬畏心理,code review 也會慢慢變成形式化,應用發佈流程而已,既不能提高代碼質量,降低系統 Bug,也不能提升開發人員的水平,反而降低的開發團隊的效率,所以"},{"type":"text","marks":[{"type":"strong"}],"text":"選擇在上線前進行 code review 不是一個好主意"},{"type":"text","text":",所以從性價比上來說 code review 最好的時機應該是在 "},{"type":"text","marks":[{"type":"strong"}],"text":"功能分支自測完成後,需要合併到 develop 分支申請提測前"},{"type":"text","text":" 通知項目組成員對增量的代碼進行 code review。"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"所以,代碼審查要高效的話,核心就是要追求"},{"type":"text","marks":[{"type":"strong"}],"text":"快速反饋"},{"type":"text","text":",越早發現代碼問題修改的成本就越低,具體參考下圖:"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"image","attrs":{"src":"https://static001.geekbang.org/infoq/62/62a1aa34f8c4959ffcb33a36b468a433.png","alt":"極客時間-研發效率破局之道(圖)","title":null,"style":null,"href":null,"fromPaste":true,"pastePass":true}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"這裏需要注意的是,代碼在經過機器掃描後("},{"type":"text","marks":[{"type":"strong"}],"text":"這裏有一個技巧就是可以在 GitLab CI 加入自動的代碼風格檢查,代碼靜態掃描是一個高頻操作,一天可能會有幾十,甚至上百次的 Commit,如果接入 GitLab CI 實現自動化靜態掃描,大家不需要在自己本地執行靜態掃描,那麼效率也會大大的提升"},{"type":"text","text":"),項目組成員只需要把注意力放在 "},{"type":"text","marks":[{"type":"strong"}],"text":"代碼邏輯結構,功能設計的可維護,可擴展性 等機器不容易發現問題的地方上"},{"type":"text","text":",然後就完成代碼審查。因爲代碼還未提測,所以就算 Merge Request 不合格被打回後,因爲還未提測,也不會佔用測試人員的資源,開發人員的修改意願也會更高,總體來說是可以達到高效和質量的要求"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"heading","attrs":{"align":null,"level":5},"content":[{"type":"text","text":"Code Review 要計入開發的工作量"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"很多團隊不做 code review 都有一個共同的原因是覺得"},{"type":"text","marks":[{"type":"strong"}],"text":"浪費時間"},{"type":"text","text":",結果導致糟糕的代碼合併入庫,頻繁出現線上問題,然後開發人員疲於奔命的去修復線上事故 BUG,雖然短期來看功能是快速上線了,但是算上覆工的時間,"},{"type":"text","marks":[{"type":"strong"}],"text":"長期來看整體的交付週期還是被拉長了,整體還是低效的"},{"type":"text","text":",而且糟糕的生產質量人很容易打擊開發人員的持續生產高質量代碼的信心,所以"},{"type":"text","marks":[{"type":"strong"}],"text":"將 code review 計入開發的工作量是重視長期利益的一種做法,也是 code review 能夠成功落地的重要前提"},{"type":"text","text":",從團隊管理的角度來說,不計入工作量的事情就不會被重視,不被重視的話那麼 code review 最終在團隊只會被廢棄或者流於應付形式,並未發揮作用。也是很多團隊推行 code review 失敗的原因。"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"heading","attrs":{"align":null,"level":3},"content":[{"type":"text","text":"推行 Code Review 的關鍵原則"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"想要在審覈代碼的時候,避免團隊成員因爲某些模糊不清的細節爭論不休的情況,那麼就要提前讓團隊建立對代碼審覈的原則和方法達成共識,我就曾經見過團隊的技術人員在代碼審覈的時候因爲某個函數方法的實現方式爭吵不休,各自都認爲自己的實現是正確的,那麼提前建立一下這種共識:"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"heading","attrs":{"align":null,"level":5},"content":[{"type":"text","text":"相互尊重原則"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"站在代碼作者的角度:"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"numberedlist","attrs":{"start":"1","normalizeStart":1},"content":[{"type":"listitem","content":[{"type":"paragraph","attrs":{"indent":0,"number":1,"align":null,"origin":null},"content":[{"type":"text","text":"審覈人花費時間和精力閱讀他不熟悉的代碼,並且幫忙指出代碼中的問題來幫助代碼作者提高,代碼作者應該儘可能的爲審覈人提供配合和方便"}]}]},{"type":"listitem","content":[{"type":"paragraph","attrs":{"indent":0,"number":2,"align":null,"origin":null},"content":[{"type":"text","text":"代碼作者提交高質量的代碼,就是對審覈人和審覈團隊的最基本尊重(提交一堆亂如麻花的代碼,沒有自測錯誤百出的代碼是極度不負責任的表現)"}]}]},{"type":"listitem","content":[{"type":"paragraph","attrs":{"indent":0,"number":3,"align":null,"origin":null},"content":[{"type":"text","text":"最好要有清晰的 commit 歷史,讓人可以一目瞭然代碼的提交內容,如果代碼過度複雜,那麼就需要和審覈人面對面溝通,才能足夠的高效"}]}]}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"站在代碼審查者的角度:"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"numberedlist","attrs":{"start":"1","normalizeStart":1},"content":[{"type":"listitem","content":[{"type":"paragraph","attrs":{"indent":0,"number":1,"align":null,"origin":null},"content":[{"type":"text","text":"一定要懂得相互尊重,提出建議要懂得換位思考,考慮代碼作者的感受,不要用主觀的批評或者情緒化的語氣指責團隊的同事"}]}]},{"type":"listitem","content":[{"type":"paragraph","attrs":{"indent":0,"number":2,"align":null,"origin":null},"content":[{"type":"text","text":"提出代碼改進建議,必須是基於事實,或者明確的代碼規範文檔,不可強行把個人喜好強加在對方身上(例如用不同的語法實現相同的功能 for/while )"}]}]},{"type":"listitem","content":[{"type":"paragraph","attrs":{"indent":0,"number":3,"align":null,"origin":null},"content":[{"type":"text","text":"不要鑽進代碼的牛角尖和摳細節,人工審查更多的要把精力放在代碼邏輯,功能設計等無法掃描的問題上"}]}]}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"heading","attrs":{"align":null,"level":5},"content":[{"type":"text","text":"建立共識"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"站在團隊的角度:"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"numberedlist","attrs":{"start":"1","normalizeStart":1},"content":[{"type":"listitem","content":[{"type":"paragraph","attrs":{"indent":0,"number":1,"align":null,"origin":null},"content":[{"type":"text","text":"code review 的目標長期來看,收益是提升團隊的項目質量,減少團隊陷入反覆修復 bug 的困境中,讓團隊有機會去面對更多的挑戰"}]}]},{"type":"listitem","content":[{"type":"paragraph","attrs":{"indent":0,"number":2,"align":null,"origin":null},"content":[{"type":"text","text":"code review 對個人和團隊而言都是成長的機會,放下不必要的自尊心,要用開放的包容的心態去接受不同的意見,取其精華"}]}]}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"heading","attrs":{"align":null,"level":3},"content":[{"type":"text","text":"總結"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"以上就是我個人和團隊在 code review 中的實踐和總結,Code Review 關鍵還是要結合團隊的情況選擇合適的審查方式,如果團隊追求敏捷開發,快速迭代那麼集中式的代碼審查會可能就不太適合你們當前的團隊,可能項目成員 1 對 1 的結對編程可以更加高效的完成代碼審查,每個團隊的發展階段不同,適用的 GitFlow 開發流程也不同,反正沒有最好的工具,最有最合適的工具。"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}}]}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章