...

Code Review最佳實踐

2022-01-15

我一直認爲Code Review(代碼審查)是軟件開(kāi)發(fā)中的最佳實踐之一,可以有效提高整體代碼質量,及時(shí)發(fā)現代碼中可能(néng)存在的問題。包括像Google、微軟這(zhè)些公司,Code Review都(dōu)是基本要求,代碼合并之前必須要有人審查通過(guò)才行。

然而對(duì)于我觀察到的大部分軟件開(kāi)發(fā)團隊來說(shuō),認真做Code Review的很少,有的流于形式,有的可能(néng)根本就(jiù)沒(méi)有Code Review的環節,代碼質量隻依賴于事(shì)後(hòu)的測試。也有些團隊想做好(hǎo)代碼審查,但不知道(dào)怎麼(me)做比較好(hǎo)。

網上關于如何做Code Review的文章已經(jīng)有很多了,這(zhè)裡(lǐ)我結合自己的一些經(jīng)驗,也總結整理了一下Code Review的最佳實踐,希望能(néng)對(duì)大家做好(hǎo)Code Review有所幫助。

Code Review有什麼(me)好(hǎo)處?

很多團隊或個人不做Code Review,根源還(hái)是不覺得這(zhè)是一件有意義的事(shì)情,不覺得有什麼(me)好(hǎo)處。這(zhè)個問題要從幾個角度來看。

  • 首先是團隊知識共享的角度 

一個開(kāi)發(fā)團隊中,水平有高有低,每個人側重的領域也有不同。怎麼(me)讓高水平的幫助新人成(chéng)長(cháng)?怎麼(me)讓大家都(dōu)對(duì)自己側重領域之外的知識保持了解?怎麼(me)能(néng)有人離職後(hòu)其他人能(néng)快速接手?這(zhè)些都(dōu)是團隊管理者關心的問題。

而代碼審查,就(jiù)是一個很好(hǎo)的知識共享的方式。通過(guò)代碼審查,高手可以直接指出新手代碼中的問題,新手可以馬上從高手的反饋中學(xué)習到好(hǎo)的實踐,得到更快的成(chéng)長(cháng);通過(guò)代碼審查,前端也可以去學(xué)習後(hòu)端的代碼,做功能(néng)模塊A的可以去了解功能(néng)模塊B的。

可能(néng)有些高手覺得給新手代碼審查浪費時(shí)間,自己也沒(méi)收獲。其實不然,新人成(chéng)長(cháng)了,就(jiù)可以更多的幫高手分擔繁重的任務;代碼審查中花時(shí)間,就(jiù)少一些幫新人填坑擦屁股的時(shí)間;良好(hǎo)的溝通能(néng)力、發(fā)現問題的能(néng)力、幫助其他人成(chéng)長(cháng),都(dōu)是技術轉管理或技術上更上一層樓必不可少的能(néng)力,而通過(guò)代碼審查可以有效的去練習這(zhè)些方面(miàn)的能(néng)力。

  • 然後(hòu)是代碼質量的角度

現實中的項目總是人手缺進(jìn)度緊,所以被(bèi)壓縮的往往就(jiù)是自動化測試和代碼審查,結果影響代碼質量,欠下技術債務,最後(hòu)還(hái)是要加倍償還(hái)。

也有人寄希望于開(kāi)發(fā)後(hòu)的人工測試,然而對(duì)于代碼質量來說(shuō),很多問題通過(guò)測試是測試不出來的,隻能(néng)通過(guò)代碼審查。比如說(shuō)代碼的可讀性可維護性,比如代碼的結構,比如一些特定條件才觸發(fā)的死循環、邏輯算法錯誤,還(hái)有一些安全上的漏洞也更容易通過(guò)代碼審查發(fā)現和預防。 

也有人覺得自己水平高就(jiù)不需要代碼審查了。對(duì)于高手來說(shuō),讓别人審查自己的代碼,可以讓其他人學(xué)習到好(hǎo)的實踐;在讓其他人審查的同時(shí),在給别人說(shuō)明自己代碼的時(shí)候,也等于自己對(duì)自己的代碼進(jìn)行了一次審查。這(zhè)其實就(jiù)跟我們上學(xué)時(shí)做數學(xué)題一樣(yàng),真正能(néng)拿高分的往往是那些做完後(hòu)還(hái)會(huì)認真檢查的。

  • 還(hái)有團隊規範的角度 

每個團隊都(dōu)有自己的代碼規範,有自己的基于架構設計的開(kāi)發(fā)規範,然而時(shí)間一長(cháng),就(jiù)會(huì)發(fā)現代碼中出現很多不遵守代碼規範的情況,有很多繞過(guò)架構設計的代碼。比如難以理解和不規範的命名,比如三層架構裡(lǐ)面(miàn)UI層繞過(guò)業務邏輯層直接調用數據訪問層代碼。 

如果這(zhè)些違反規範的代碼被(bèi)糾正的晚了,後(hòu)面(miàn)再要修改就(jiù)成(chéng)本很高了,而且團隊的規範也會(huì)慢慢的形同虛設。

通過(guò)代碼審查,就(jiù)可以及時(shí)的去發(fā)現和糾正這(zhè)些問題,保證團隊規範的執行。

關于代碼審查的好(hǎo)處,還(hái)有很多,也不一一列舉。還(hái)是希望能(néng)認識到Code Review和寫自動化測試一樣(yàng),都(dōu)是屬于磨刀不誤砍柴工的工作,在上面(miàn)投入一點點時(shí)間,未來會(huì)收獲代碼質量,會(huì)節約整體的開(kāi)發(fā)時(shí)間。

該怎麼(me)做? 

現在很多人都(dōu)已經(jīng)有意識到Code Review的重要性了,隻是苦于不知道(dào)如何去實踐,不知道(dào)怎麼(me)樣(yàng)算是好(hǎo)的Code Review實踐。

把Code Review作爲開(kāi)發(fā)流程的必選項而不是可選項

在很早以前,我就(jiù)嘗試過(guò)將(jiāng)代碼審查作爲代碼流程的一部分,但隻是一個可選項,沒(méi)有Code Review也可以把代碼合并到master。這(zhè)樣(yàng)的結果就(jiù)是想起(qǐ)來才會(huì)去做Code Review,去檢查的時(shí)候已經(jīng)有了太多的代碼變更,審查起(qǐ)來非常困難,另外就(jiù)算審查出問題,也很難得以修改。 

我們現在對(duì)代碼的審查則是作爲開(kāi)發(fā)流程的一個必選項,每次開(kāi)發(fā)新功能(néng)或者修複Bug,開(kāi)一個新的分支,分支要合并到master有兩(liǎng)個必要條件:

  • 所有的自動化測試通過(guò)

  • 有至少一個人Code Review通過(guò),如果是新手的PR,還(hái)必須有資深程序員Code Review通過(guò)

圖片來源:How to Do Code Reviews Like a Human

這(zhè)樣(yàng)把Code Review作爲開(kāi)發(fā)流程的一個必選項後(hòu),就(jiù)很好(hǎo)的保證了代碼在合并之前有過(guò)Code Review。而且這(zhè)樣(yàng)合并前要求代碼審查的流程,好(hǎo)處也很明顯:

  • 由于每一次合并前都(dōu)要做代碼審查,這(zhè)樣(yàng)一般一次審查的代碼量也不會(huì)太大,對(duì)于審查者來說(shuō)壓力也不會(huì)太大

  • 如果在Code Review時(shí)發(fā)現問題,被(bèi)審查者希望代碼能(néng)盡快合并,也會(huì)積極的對(duì)審查出來的問題進(jìn)行修改,不至于對(duì)審查結果太過(guò)抵觸

如果你覺得Code Review難以推行,不妨先嘗試著(zhe)把Code Review變成(chéng)你開(kāi)發(fā)流程的一個必選項。

把Code Review變成(chéng)一種(zhǒng)開(kāi)發(fā)文化而不僅僅是一種(zhǒng)制度

把Code Review 作爲開(kāi)發(fā)流程的必選項後(hòu),不代表Code Review這(zhè)件事(shì)就(jiù)可以執行的很好(hǎo),因爲Code Review 的執行,很大部分程度上依賴于審查者的認真審查,以及被(bèi)審查者的積極配合,兩(liǎng)者缺一不可!

如果僅僅隻是當作一個流程制度,那麼(me)就(jiù)可能(néng)會(huì)流于形式。最終結果就(jiù)是看起(qǐ)來有Code Review,但沒(méi)有人認真審查,随便看下就(jiù)通過(guò)了,或者發(fā)現問題也不願意修改。

真要把Code Review這(zhè)件事(shì)做好(hǎo),必須讓Code Review變成(chéng)團隊的一種(zhǒng)文化,開(kāi)發(fā)人員從心底接受這(zhè)件事(shì),并認真執行這(zhè)件事(shì)。

要形成(chéng)這(zhè)樣(yàng)的文化,不那麼(me)容易,也沒(méi)有想象的那麼(me)難,比如這(zhè)些方面(miàn)可以參考:

  • 首先,得讓開(kāi)發(fā)人員認識到Code Review這(zhè)件事(shì)爲自己、爲團隊帶來的好(hǎo)處

  • 然後(hòu),得要有幾個人做好(hǎo)表率作用,榜樣(yàng)的力量很重要

  • 還(hái)有,對(duì)于管理者來說(shuō),你激勵什麼(me),往往就(jiù)會(huì)得到什麼(me)

  • 最後(hòu),像寫自動化測試一樣(yàng),把Code Review要作爲開(kāi)發(fā)任務的一部分,給審查者和被(bèi)審查者都(dōu)留出專門的時(shí)間去做這(zhè)件事(shì),不能(néng)光想著(zhe)馬兒跑得快又舍不得給馬兒吃草 

如何形成(chéng)這(zhè)樣(yàng)的文化,有心的話,還(hái)有很多方法可以嘗試。隻有真正讓大家都(dōu)認同和踐行,才可能(néng)去做好(hǎo)Code Review這(zhè)件事(shì)。

一些Code Review的經(jīng)驗技巧

在做好(hǎo)Code Review這(zhè)件事(shì)上,還(hái)有一些經(jīng)驗技巧可以參考。

選什麼(me)工具輔助做CODE REVIEW?

現在很多源代碼管理工具都(dōu)自帶Code Review工具,典型的像Github、Gitlab、微軟的Azure DevOps,尤其是像Gitlab,還(hái)可以自己在本地搭建環境,根據自己的需要靈活配置。 

配合什麼(me)樣(yàng)的開(kāi)發(fā)流程比較好(hǎo)?

Github Flow這(zhè)樣(yàng)基于分支開(kāi)發(fā)的流程是特别适合搭配Code Review的。其實不管什麼(me)樣(yàng)的開(kāi)發(fā)流程,關鍵點在于代碼合并到master(主幹)之前,要先做Code Review。

真遇到緊急情況,來不及代碼審查怎麼(me)辦? 

雖然原則上,必須要Code Review才能(néng)合并,但有時(shí)候确實會(huì)存在一些緊急情況,比如說(shuō)線上故障補丁,而又沒(méi)有其他人在線,那麼(me)這(zhè)種(zhǒng)情況下,最好(hǎo)是在任務管理系統中,創建一個Ticket,用來後(hòu)續跟蹤,确保後(hòu)續補上Code Review,并對(duì)Code Review結果有後(hòu)續的代碼更新。

先設計再編碼

有些新人發(fā)現自己的代碼提交PR(Pull Request)後(hòu),會(huì)收到一堆的Code Review意見,必須要做大量的改動。這(zhè)多半是因爲在開(kāi)始做之前,沒(méi)有做好(hǎo)設計,做出來後(hòu)才發(fā)現問題很多。 

建議在做一個新功能(néng)之前,寫一個簡單的設計文檔,表達清楚自己的設計思路,找資深的先幫你做一下設計的審查,發(fā)現設計上的問題。設計上沒(méi)問題了,再著(zhe)手開(kāi)發(fā),那麼(me)到Review的時(shí)候,相對(duì)問題就(jiù)會(huì)少很多。

代碼在提交CODE REVIEW之前,作者要自己先REVIEW和測試一遍 

我在做代碼審查的時(shí)候,有時(shí)候會(huì)發(fā)現一些非常明顯的問題,有些甚至自己都(dōu)沒(méi)有測試過(guò),就(jiù)等著(zhe)别人Code Review和測試幫助發(fā)現問題。這(zhè)種(zhǒng)依賴心理無論是對(duì)自己還(hái)是對(duì)團隊都(dōu)是很不負責任的。 

一個好(hǎo)的開(kāi)發(fā)人員,代碼在提交Code Review之前,肯定是要自己先Review一遍,把該寫的自動化測試代碼寫上,自己把基本的測試用例跑一遍的。 

我對(duì)于團隊提交的PR,有個要求就(jiù)是要在PR的描述中增加截圖或者錄屏,就(jiù)是爲了通過(guò)截圖或者錄屏,确保提交PR的人自己是先測試過(guò)的。這(zhè)也是一個有效的輔助手段。

PR要小 

在做Code Review的時(shí)候,如果有大量的文件修改,那麼(me)Review起(qǐ)來是很困難的,但如果PR比較小,相對(duì)就(jiù)比較容易Review,也容易發(fā)現代碼中可能(néng)存在的問題。

所以在提交PR時(shí),PR要小,如果是比較大的改動,那麼(me)最好(hǎo)分批提交,以減輕審查者的壓力。

對(duì)評論進(jìn)行分級

在做Code Review時(shí),需要針對(duì)審查出有問題的代碼行添加評論,如果隻是評論,有時(shí)候對(duì)于被(bèi)審查者比較難甄别評論所代表的含義,是不是必須要修改。

建議可以對(duì)Review的評論進(jìn)行分級,不同級别的結果可以打上不同的Tag,比如說(shuō):

  • [blocker]: 在評論前面(miàn)加上一個[blocker]标記,表示這(zhè)個代碼行的問題必須要修改

  • [optional]:在評論前面(miàn)加上一個[optional]标記,表示這(zhè)個代碼行的問題可改可不改

  • [question]:在評論前面(miàn)加上一個[question]标記,表示對(duì)這(zhè)個代碼行不理解,有問題需要問,被(bèi)審查者需要針對(duì)問題進(jìn)行回複澄清 

類似這(zhè)樣(yàng)的分級可以幫助被(bèi)審查者直觀了解Review結果,提高Review效率。

評論要友好(hǎo),避免負面(miàn)詞彙;有說(shuō)不清楚的問題當面(miàn)溝通 

雖然評論是主要的Code Review溝通方式,但也不要過(guò)于依賴,有時(shí)候面(miàn)對(duì)面(miàn)的溝通效率更高,也容易消除誤解。

另外文明用語,不要用一些負面(miàn)的詞彙。 

總結 

Code Review是一種(zhǒng)非常好(hǎo)的開(kāi)發(fā)實踐,如果你還(hái)沒(méi)開(kāi)始,不妨逐步實踐起(qǐ)來;如果已經(jīng)做了效果不好(hǎo),不妨對(duì)照一下,看有沒(méi)有把Code Review作爲開(kāi)發(fā)流程的必選項而不是可選項?有沒(méi)有把Code Review變成(chéng)一種(zhǒng)開(kāi)發(fā)文化而不僅僅是一種(zhǒng)制度?


來源:cnblogs