Code Review最佳實踐
我一(yī / yì /yí)直認爲(wéi / wèi)Code Review(代碼審查)是(shì)軟件開發中的(de)最佳實踐之(zhī)一(yī / yì /yí),可以(yǐ)有效提高整體代碼質量,及時(shí)發現代碼中可能存在(zài)的(de)問題。包括像Google、微軟這(zhè)些公司,Code Review都是(shì)基本要(yào / yāo)求,代碼合并之(zhī)前必須要(yào / yāo)有人(rén)審查通過才行。
然而(ér)對于(yú)我觀察到(dào)的(de)大(dà)部分軟件開發團隊來(lái)說(shuō),認真做Code Review的(de)很少,有的(de)流于(yú)形式,有的(de)可能根本就(jiù)沒有Code Review的(de)環節,代碼質量隻依賴于(yú)事後的(de)測試。也(yě)有些團隊想做好代碼審查,但不(bù)知道(dào)怎麽做比較好。
網上(shàng)關于(yú)如何做Code Review的(de)文章已經有很多了(le/liǎo),這(zhè)裏我結合自己的(de)一(yī / yì /yí)些經驗,也(yě)總結整理了(le/liǎo)一(yī / yì /yí)下Code Review的(de)最佳實踐,希望能對大(dà)家做好Code Review有所幫助。
Code Review有什麽好處?
很多團隊或個(gè)人(rén)不(bù)做Code Review,根源還是(shì)不(bù)覺得這(zhè)是(shì)一(yī / yì /yí)件有意義的(de)事情,不(bù)覺得有什麽好處。這(zhè)個(gè)問題要(yào / yāo)從幾個(gè)角度來(lái)看。
首先是(shì)團隊知識共享的(de)角度
一(yī / yì /yí)個(gè)開發團隊中,水平有高有低,每個(gè)人(rén)側重的(de)領域也(yě)有不(bù)同。怎麽讓高水平的(de)幫助新人(rén)成長?怎麽讓大(dà)家都對自己側重領域之(zhī)外的(de)知識保持了(le/liǎo)解?怎麽能有人(rén)離職後其他(tā)人(rén)能快速接手?這(zhè)些都是(shì)團隊管理者關心的(de)問題。
而(ér)代碼審查,就(jiù)是(shì)一(yī / yì /yí)個(gè)很好的(de)知識共享的(de)方式。通過代碼審查,高手可以(yǐ)直接指出(chū)新手代碼中的(de)問題,新手可以(yǐ)馬上(shàng)從高手的(de)反饋中學習到(dào)好的(de)實踐,得到(dào)更快的(de)成長;通過代碼審查,前端也(yě)可以(yǐ)去學習後端的(de)代碼,做功能模塊A的(de)可以(yǐ)去了(le/liǎo)解功能模塊B的(de)。
可能有些高手覺得給新手代碼審查浪費時(shí)間,自己也(yě)沒收獲。其實不(bù)然,新人(rén)成長了(le/liǎo),就(jiù)可以(yǐ)更多的(de)幫高手分擔繁重的(de)任務;代碼審查中花時(shí)間,就(jiù)少一(yī / yì /yí)些幫新人(rén)填坑擦屁股的(de)時(shí)間;良好的(de)溝通能力、發現問題的(de)能力、幫助其他(tā)人(rén)成長,都是(shì)技術轉管理或技術上(shàng)更上(shàng)一(yī / yì /yí)層樓必不(bù)可少的(de)能力,而(ér)通過代碼審查可以(yǐ)有效的(de)去練習這(zhè)些方面的(de)能力。
然後是(shì)代碼質量的(de)角度
現實中的(de)項目總是(shì)人(rén)手缺進度緊,所以(yǐ)被壓縮的(de)往往就(jiù)是(shì)自動化測試和(hé / huò)代碼審查,結果影響代碼質量,欠下技術債務,最後還是(shì)要(yào / yāo)加倍償還。
也(yě)有人(rén)寄希望于(yú)開發後的(de)人(rén)工測試,然而(ér)對于(yú)代碼質量來(lái)說(shuō),很多問題通過測試是(shì)測試不(bù)出(chū)來(lái)的(de),隻能通過代碼審查。比如說(shuō)代碼的(de)可讀性可維護性,比如代碼的(de)結構,比如一(yī / yì /yí)些特定條件才觸發的(de)死循環、邏輯算法錯誤,還有一(yī / yì /yí)些安全上(shàng)的(de)漏洞也(yě)更容易通過代碼審查發現和(hé / huò)預防。
也(yě)有人(rén)覺得自己水平高就(jiù)不(bù)需要(yào / yāo)代碼審查了(le/liǎo)。對于(yú)高手來(lái)說(shuō),讓别人(rén)審查自己的(de)代碼,可以(yǐ)讓其他(tā)人(rén)學習到(dào)好的(de)實踐;在(zài)讓其他(tā)人(rén)審查的(de)同時(shí),在(zài)給别人(rén)說(shuō)明自己代碼的(de)時(shí)候,也(yě)等于(yú)自己對自己的(de)代碼進行了(le/liǎo)一(yī / yì /yí)次審查。這(zhè)其實就(jiù)跟我們上(shàng)學時(shí)做數學題一(yī / yì /yí)樣,真正能拿高分的(de)往往是(shì)那些做完後還會認真檢查的(de)。
還有團隊規範的(de)角度
每個(gè)團隊都有自己的(de)代碼規範,有自己的(de)基于(yú)架構設計的(de)開發規範,然而(ér)時(shí)間一(yī / yì /yí)長,就(jiù)會發現代碼中出(chū)現很多不(bù)遵守代碼規範的(de)情況,有很多繞過架構設計的(de)代碼。比如難以(yǐ)理解和(hé / huò)不(bù)規範的(de)命名,比如三層架構裏面UI層繞過業務邏輯層直接調用數據訪問層代碼。
如果這(zhè)些違反規範的(de)代碼被糾正的(de)晚了(le/liǎo),後面再要(yào / yāo)修改就(jiù)成本很高了(le/liǎo),而(ér)且團隊的(de)規範也(yě)會慢慢的(de)形同虛設。
通過代碼審查,就(jiù)可以(yǐ)及時(shí)的(de)去發現和(hé / huò)糾正這(zhè)些問題,保證團隊規範的(de)執行。
關于(yú)代碼審查的(de)好處,還有很多,也(yě)不(bù)一(yī / yì /yí)一(yī / yì /yí)列舉。還是(shì)希望能認識到(dào)Code Review和(hé / huò)寫自動化測試一(yī / yì /yí)樣,都是(shì)屬于(yú)磨刀不(bù)誤砍柴工的(de)工作,在(zài)上(shàng)面投入一(yī / yì /yí)點點時(shí)間,未來(lái)會收獲代碼質量,會節約整體的(de)開發時(shí)間。
該怎麽做?
現在(zài)很多人(rén)都已經有意識到(dào)Code Review的(de)重要(yào / yāo)性了(le/liǎo),隻是(shì)苦于(yú)不(bù)知道(dào)如何去實踐,不(bù)知道(dào)怎麽樣算是(shì)好的(de)Code Review實踐。
把Code Review作爲(wéi / wèi)開發流程的(de)必選項而(ér)不(bù)是(shì)可選項
在(zài)很早以(yǐ)前,我就(jiù)嘗試過将代碼審查作爲(wéi / wèi)代碼流程的(de)一(yī / yì /yí)部分,但隻是(shì)一(yī / yì /yí)個(gè)可選項,沒有Code Review也(yě)可以(yǐ)把代碼合并到(dào)master。這(zhè)樣的(de)結果就(jiù)是(shì)想起來(lái)才會去做Code Review,去檢查的(de)時(shí)候已經有了(le/liǎo)太多的(de)代碼變更,審查起來(lái)非常困難,另外就(jiù)算審查出(chū)問題,也(yě)很難得以(yǐ)修改。
我們現在(zài)對代碼的(de)審查則是(shì)作爲(wéi / wèi)開發流程的(de)一(yī / yì /yí)個(gè)必選項,每次開發新功能或者修複Bug,開一(yī / yì /yí)個(gè)新的(de)分支,分支要(yào / yāo)合并到(dào)master有兩個(gè)必要(yào / yāo)條件:
所有的(de)自動化測試通過
有至少一(yī / yì /yí)個(gè)人(rén)Code Review通過,如果是(shì)新手的(de)PR,還必須有資深程序員Code Review通過
圖片來(lái)源:How to Do Code Reviews Like a Human
這(zhè)樣把Code Review作爲(wéi / wèi)開發流程的(de)一(yī / yì /yí)個(gè)必選項後,就(jiù)很好的(de)保證了(le/liǎo)代碼在(zài)合并之(zhī)前有過Code Review。而(ér)且這(zhè)樣合并前要(yào / yāo)求代碼審查的(de)流程,好處也(yě)很明顯:
由于(yú)每一(yī / yì /yí)次合并前都要(yào / yāo)做代碼審查,這(zhè)樣一(yī / yì /yí)般一(yī / yì /yí)次審查的(de)代碼量也(yě)不(bù)會太大(dà),對于(yú)審查者來(lái)說(shuō)壓力也(yě)不(bù)會太大(dà)
如果在(zài)Code Review時(shí)發現問題,被審查者希望代碼能盡快合并,也(yě)會積極的(de)對審查出(chū)來(lái)的(de)問題進行修改,不(bù)至于(yú)對審查結果太過抵觸
如果你覺得Code Review難以(yǐ)推行,不(bù)妨先嘗試着把Code Review變成你開發流程的(de)一(yī / yì /yí)個(gè)必選項。
把Code Review變成一(yī / yì /yí)種開發文化而(ér)不(bù)僅僅是(shì)一(yī / yì /yí)種制度
把Code Review 作爲(wéi / wèi)開發流程的(de)必選項後,不(bù)代表Code Review這(zhè)件事就(jiù)可以(yǐ)執行的(de)很好,因爲(wéi / wèi)Code Review 的(de)執行,很大(dà)部分程度上(shàng)依賴于(yú)審查者的(de)認真審查,以(yǐ)及被審查者的(de)積極配合,兩者缺一(yī / yì /yí)不(bù)可!
如果僅僅隻是(shì)當作一(yī / yì /yí)個(gè)流程制度,那麽就(jiù)可能會流于(yú)形式。最終結果就(jiù)是(shì)看起來(lái)有Code Review,但沒有人(rén)認真審查,随便看下就(jiù)通過了(le/liǎo),或者發現問題也(yě)不(bù)願意修改。
真要(yào / yāo)把Code Review這(zhè)件事做好,必須讓Code Review變成團隊的(de)一(yī / yì /yí)種文化,開發人(rén)員從心底接受這(zhè)件事,并認真執行這(zhè)件事。
要(yào / yāo)形成這(zhè)樣的(de)文化,不(bù)那麽容易,也(yě)沒有想象的(de)那麽難,比如這(zhè)些方面可以(yǐ)參考:
首先,得讓開發人(rén)員認識到(dào)Code Review這(zhè)件事爲(wéi / wèi)自己、爲(wéi / wèi)團隊帶來(lái)的(de)好處
然後,得要(yào / yāo)有幾個(gè)人(rén)做好表率作用,榜樣的(de)力量很重要(yào / yāo)
還有,對于(yú)管理者來(lái)說(shuō),你激勵什麽,往往就(jiù)會得到(dào)什麽
最後,像寫自動化測試一(yī / yì /yí)樣,把Code Review要(yào / yāo)作爲(wéi / wèi)開發任務的(de)一(yī / yì /yí)部分,給審查者和(hé / huò)被審查者都留出(chū)專門的(de)時(shí)間去做這(zhè)件事,不(bù)能光想着馬兒跑得快又舍不(bù)得給馬兒吃草
如何形成這(zhè)樣的(de)文化,有心的(de)話,還有很多方法可以(yǐ)嘗試。隻有真正讓大(dà)家都認同和(hé / huò)踐行,才可能去做好Code Review這(zhè)件事。
一(yī / yì /yí)些Code Review的(de)經驗技巧
在(zài)做好Code Review這(zhè)件事上(shàng),還有一(yī / yì /yí)些經驗技巧可以(yǐ)參考。
選什麽工具輔助做CODE REVIEW?
現在(zài)很多源代碼管理工具都自帶Code Review工具,典型的(de)像Github、Gitlab、微軟的(de)Azure DevOps,尤其是(shì)像Gitlab,還可以(yǐ)自己在(zài)本地(dì / de)搭建環境,根據自己的(de)需要(yào / yāo)靈活配置。
配合什麽樣的(de)開發流程比較好?
像Github Flow這(zhè)樣基于(yú)分支開發的(de)流程是(shì)特别适合搭配Code Review的(de)。其實不(bù)管什麽樣的(de)開發流程,關鍵點在(zài)于(yú)代碼合并到(dào)master(主幹)之(zhī)前,要(yào / yāo)先做Code Review。
真遇到(dào)緊急情況,來(lái)不(bù)及代碼審查怎麽辦?
雖然原則上(shàng),必須要(yào / yāo)Code Review才能合并,但有時(shí)候确實會存在(zài)一(yī / yì /yí)些緊急情況,比如說(shuō)線上(shàng)故障補丁,而(ér)又沒有其他(tā)人(rén)在(zài)線,那麽這(zhè)種情況下,最好是(shì)在(zài)任務管理系統中,創建一(yī / yì /yí)個(gè)Ticket,用來(lái)後續跟蹤,确保後續補上(shàng)Code Review,并對Code Review結果有後續的(de)代碼更新。
先設計再編碼
有些新人(rén)發現自己的(de)代碼提交PR(Pull Request)後,會收到(dào)一(yī / yì /yí)堆的(de)Code Review意見,必須要(yào / yāo)做大(dà)量的(de)改動。這(zhè)多半是(shì)因爲(wéi / wèi)在(zài)開始做之(zhī)前,沒有做好設計,做出(chū)來(lái)後才發現問題很多。
建議在(zài)做一(yī / yì /yí)個(gè)新功能之(zhī)前,寫一(yī / yì /yí)個(gè)簡單的(de)設計文檔,表達清楚自己的(de)設計思路,找資深的(de)先幫你做一(yī / yì /yí)下設計的(de)審查,發現設計上(shàng)的(de)問題。設計上(shàng)沒問題了(le/liǎo),再着手開發,那麽到(dào)Review的(de)時(shí)候,相對問題就(jiù)會少很多。
代碼在(zài)提交CODE REVIEW之(zhī)前,作者要(yào / yāo)自己先REVIEW和(hé / huò)測試一(yī / yì /yí)遍
我在(zài)做代碼審查的(de)時(shí)候,有時(shí)候會發現一(yī / yì /yí)些非常明顯的(de)問題,有些甚至自己都沒有測試過,就(jiù)等着别人(rén)Code Review和(hé / huò)測試幫助發現問題。這(zhè)種依賴心理無論是(shì)對自己還是(shì)對團隊都是(shì)很不(bù)負責任的(de)。
一(yī / yì /yí)個(gè)好的(de)開發人(rén)員,代碼在(zài)提交Code Review之(zhī)前,肯定是(shì)要(yào / yāo)自己先Review一(yī / yì /yí)遍,把該寫的(de)自動化測試代碼寫上(shàng),自己把基本的(de)測試用例跑一(yī / yì /yí)遍的(de)。
我對于(yú)團隊提交的(de)PR,有個(gè)要(yào / yāo)求就(jiù)是(shì)要(yào / yāo)在(zài)PR的(de)描述中增加截圖或者錄屏,就(jiù)是(shì)爲(wéi / wèi)了(le/liǎo)通過截圖或者錄屏,确保提交PR的(de)人(rén)自己是(shì)先測試過的(de)。這(zhè)也(yě)是(shì)一(yī / yì /yí)個(gè)有效的(de)輔助手段。
PR要(yào / yāo)小
在(zài)做Code Review的(de)時(shí)候,如果有大(dà)量的(de)文件修改,那麽Review起來(lái)是(shì)很困難的(de),但如果PR比較小,相對就(jiù)比較容易Review,也(yě)容易發現代碼中可能存在(zài)的(de)問題。
所以(yǐ)在(zài)提交PR時(shí),PR要(yào / yāo)小,如果是(shì)比較大(dà)的(de)改動,那麽最好分批提交,以(yǐ)減輕審查者的(de)壓力。
對評論進行分級
在(zài)做Code Review時(shí),需要(yào / yāo)針對審查出(chū)有問題的(de)代碼行添加評論,如果隻是(shì)評論,有時(shí)候對于(yú)被審查者比較難甄别評論所代表的(de)含義,是(shì)不(bù)是(shì)必須要(yào / yāo)修改。
建議可以(yǐ)對Review的(de)評論進行分級,不(bù)同級别的(de)結果可以(yǐ)打上(shàng)不(bù)同的(de)Tag,比如說(shuō):
[blocker]: 在(zài)評論前面加上(shàng)一(yī / yì /yí)個(gè)[blocker]标記,表示這(zhè)個(gè)代碼行的(de)問題必須要(yào / yāo)修改
[optional]:在(zài)評論前面加上(shàng)一(yī / yì /yí)個(gè)[optional]标記,表示這(zhè)個(gè)代碼行的(de)問題可改可不(bù)改
[question]:在(zài)評論前面加上(shàng)一(yī / yì /yí)個(gè)[question]标記,表示對這(zhè)個(gè)代碼行不(bù)理解,有問題需要(yào / yāo)問,被審查者需要(yào / yāo)針對問題進行回複澄清
類似這(zhè)樣的(de)分級可以(yǐ)幫助被審查者直觀了(le/liǎo)解Review結果,提高Review效率。
評論要(yào / yāo)友好,避免負面詞彙;有說(shuō)不(bù)清楚的(de)問題當面溝通
雖然評論是(shì)主要(yào / yāo)的(de)Code Review溝通方式,但也(yě)不(bù)要(yào / yāo)過于(yú)依賴,有時(shí)候面對面的(de)溝通效率更高,也(yě)容易消除誤解。
另外文明用語,不(bù)要(yào / yāo)用一(yī / yì /yí)些負面的(de)詞彙。
總結
Code Review是(shì)一(yī / yì /yí)種非常好的(de)開發實踐,如果你還沒開始,不(bù)妨逐步實踐起來(lái);如果已經做了(le/liǎo)效果不(bù)好,不(bù)妨對照一(yī / yì /yí)下,看有沒有把Code Review作爲(wéi / wèi)開發流程的(de)必選項而(ér)不(bù)是(shì)可選項?有沒有把Code Review變成一(yī / yì /yí)種開發文化而(ér)不(bù)僅僅是(shì)一(yī / yì /yí)種制度?