前言
很多公司都要求項(xiàng)目做CodeReview巢块,但很多人第一次CodeReview往往不知道該如何做键袱,也不知道為什么去做鹉动。筆者參加過幾個(gè)項(xiàng)目的CodeReview再菊,發(fā)現(xiàn)一些共性問題:
- 有時(shí)候參與Review的人太多了,意見太分散颜曾,Review時(shí)間拉的很長(zhǎng)纠拔,發(fā)現(xiàn)問題效率低;
- 有時(shí)候會(huì)發(fā)現(xiàn)一個(gè)CodeReview時(shí)間很長(zhǎng)泛豪,參與者會(huì)覺得煎熬和浪費(fèi)時(shí)間稠诲;
- 有時(shí)候不太了解對(duì)方評(píng)審的東西侦鹏,沒法跟上大家的思路,影響效率臀叙;
- 有時(shí)候走查的代碼量太大了略水,無法做到詳細(xì)走查;
- 有時(shí)候會(huì)看到有些人無所事事劝萤、精神不集中渊涝、不發(fā)言,影響效果床嫌。
對(duì)這些問題跨释,用魚骨圖做個(gè)分析:
希望本文中的一些建議能夠緩解上述問題,能使大家更快的了解CodeReview的意義和方法厌处,有經(jīng)驗(yàn)的人能夠更加快速有效的進(jìn)行CodeReview鳖谈。
CodeReview的目標(biāo)和原則
CodeReview的目的是提升代碼質(zhì)量,盡早發(fā)現(xiàn)潛在缺陷與BUG阔涉,降低修復(fù)成本缆娃,同時(shí)促進(jìn)團(tuán)隊(duì)內(nèi)部知識(shí)共享,幫助更多人更好地理解系統(tǒng)瑰排。
建議CodeReview的原則如下:
- 發(fā)現(xiàn)代碼的正確性
代碼審查用意是在代碼提交前找到其中的問題——你要發(fā)現(xiàn)的是它的正確性贯要。在代碼審查中最常犯的錯(cuò)誤—幾乎每個(gè)新手都會(huì)犯的錯(cuò)誤是,審查者根據(jù)自己的編程習(xí)慣來評(píng)判別人的代碼凶伙。
- 不僅是在Review Code郭毕,更是在分享和學(xué)習(xí)
Code Review最重要的是講解者分享業(yè)務(wù)流程和設(shè)計(jì)思路,參與者通過這些講解獲得這些信息函荣,使得更多人理解這個(gè)系統(tǒng)显押,提升團(tuán)隊(duì)整體水平,使得團(tuán)隊(duì)維護(hù)代碼的能力提升傻挂。
- 高效迅速完成CodeReview
我們不能為了應(yīng)付匆匆忙忙的進(jìn)行一次代碼審查乘碑,效率也是很重要的,如果不能保證Code Review目的實(shí)現(xiàn)金拒,那么評(píng)審便是徒勞的兽肤。
如何高效完成CodeReview?
參與者要檢查設(shè)計(jì)的合理性以及業(yè)務(wù)邏輯是否錯(cuò)誤绪抛,檢查代碼可讀性资铡;講解者要想辦法分享設(shè)計(jì)、技術(shù)幢码、經(jīng)驗(yàn)等知識(shí)笤休。
1.檢查設(shè)計(jì)的合理性和業(yè)務(wù)邏輯的正確性:
-
代碼的設(shè)計(jì)是否符合設(shè)計(jì)要求:
- 如果存在代碼和設(shè)計(jì)有出入的地方需要問詢?yōu)槭裁匆儎?dòng),因?yàn)檫@些變動(dòng)有可能是出于開發(fā)者在真正設(shè)計(jì)代碼時(shí)候的深入考慮症副,或者是由于一時(shí)大意出現(xiàn)偏差店雅。
-
業(yè)務(wù)邏輯是否正確:
- 業(yè)務(wù)流程是否按照詳細(xì)設(shè)計(jì)的流程走政基,不要出現(xiàn)原本是先A流程后B流程而設(shè)計(jì)的時(shí)候出現(xiàn)先B后A,或者丟失流程闹啦。
- 某些傳入?yún)?shù)是否合理:判斷某些接口的參數(shù)輸入是否是冗余的沮明,比如輸入A字段可以滿足A接口里面的所有操作,那么多輸入一個(gè)B就冗余的窍奋。
- 數(shù)據(jù)庫字段的設(shè)計(jì)荐健,數(shù)據(jù)庫的設(shè)計(jì)是對(duì)實(shí)際業(yè)務(wù)的映射,我們要保證每一個(gè)字段的出現(xiàn)都反應(yīng)實(shí)際業(yè)務(wù)并且經(jīng)過合理性的驗(yàn)證费变,比如設(shè)計(jì)table1的時(shí)候A字段在table2中已經(jīng)出現(xiàn)摧扇,并且A和B表有相應(yīng)的關(guān)聯(lián),那么要注意A字段對(duì)于table1的冗余是否有合理性挚歧,如果沒有合理的說服性可以去掉A扛稽,而節(jié)省對(duì)A字段的維護(hù)成本(存儲(chǔ)空間,更新操作等)滑负。
- 某些判斷是否合理在张,比如某些參數(shù)的輸入金額是否可以為0的判斷等等。
- 系統(tǒng)交互是否合理矮慕,比如在代碼設(shè)計(jì)的時(shí)候沒有關(guān)注考慮系統(tǒng)交互的順序而造成有些信息不能獲取到帮匾;比如獲取支付方式的費(fèi)率信息必須要等待支付的時(shí)候才能拿到,那么獲取這些信息就應(yīng)該放在pay_trans的時(shí)候而不是create_trans痴鳄,大多數(shù)這種問題其實(shí)都是詳細(xì)設(shè)計(jì)時(shí)出現(xiàn)的瘟斜,代碼評(píng)審階段比較少見。
- 是否有異常處理機(jī)制痪寻,一個(gè)好的代碼設(shè)計(jì)應(yīng)該考慮各種異常并對(duì)相應(yīng)的異常做出合理的處理螺句,比如接口的可重入,當(dāng)代碼檢測(cè)到有重入的這種情況橡类,怎樣去做這種異常處理使得調(diào)用方能捕捉的這些異常而進(jìn)行后面的處理蛇尚。
-
關(guān)注業(yè)務(wù)可拓展性:
- 我們的業(yè)務(wù)在不斷的發(fā)展,每一個(gè)項(xiàng)目設(shè)計(jì)都會(huì)影響后續(xù)業(yè)務(wù)的拓展顾画,一個(gè)好的設(shè)計(jì)應(yīng)該考慮到后續(xù)業(yè)務(wù)的發(fā)展取劫,而盡量避免定制化的設(shè)計(jì)。
-
關(guān)注使用到的數(shù)據(jù)結(jié)構(gòu)研侣、設(shè)計(jì)模式和代碼性能:
- 一個(gè)好的數(shù)據(jù)結(jié)構(gòu)和設(shè)計(jì)模式可以增加代碼的可維護(hù)性安全性和效率等谱邪,比如我們?cè)谠O(shè)計(jì)的時(shí)候要考慮到不同的場(chǎng)景選擇什么樣的數(shù)據(jù)結(jié)構(gòu),有時(shí)候我們會(huì)糾結(jié)于用map還是用hash_map庶诡,這時(shí)候我們要根據(jù)具體的情況具體分析虾标;
- 當(dāng)我們?cè)O(shè)計(jì)代碼的時(shí)候如果能用上系統(tǒng)提供的函數(shù)那么最好不要自己去寫,比如自己實(shí)現(xiàn)一個(gè)鏈表的時(shí)候是否可以想到用系統(tǒng)庫提供的list_head以確保鏈表結(jié)構(gòu)的正確性;
- 某些設(shè)計(jì)如果能套用設(shè)計(jì)模式會(huì)讓設(shè)計(jì)更加美觀也讓閱讀者更加明了璧函;出于對(duì)系統(tǒng)性能的考量,我們要關(guān)注編寫代碼對(duì)系統(tǒng)的開銷基显,包括使用的算法是否合理蘸吓,以及對(duì)某些比較耗時(shí)的操作比如數(shù)據(jù)庫的操作要加以關(guān)注。
2.檢查代碼可讀性和可維護(hù)性:
- 如果代碼的可讀性強(qiáng)撩幽,那么維護(hù)起來也就方便很多库继;一個(gè)好的代碼規(guī)范和編碼風(fēng)格會(huì)節(jié)省大家對(duì)代碼的理解時(shí)間,減少維護(hù)成本窜醉;雖然我們有編程規(guī)范檢查工具宪萄,但有些內(nèi)容檢查不出來,是需要靠大家去規(guī)范的榨惰。
- 關(guān)注代碼注釋:我們?cè)诰帉懞瘮?shù)和進(jìn)行邏輯判斷的時(shí)候最好要標(biāo)注一下這個(gè)函數(shù)或者這段判斷是用來做什么的拜英;做了這種注釋的好處,一來當(dāng)別人閱讀這段代碼的時(shí)候看到你的注釋以后就會(huì)根據(jù)你的思路快速理解代碼琅催,甚至不閱讀直接跳過居凶;二來防止自己由于長(zhǎng)時(shí)間不閱讀代碼而忘記這段代碼的用途。
- 關(guān)注命名規(guī)范:雖然我們有自己的編碼規(guī)范藤抡,但是這種規(guī)范只是限制了使用駝峰命名法還是其他命名法侠碧;而好的命名風(fēng)格應(yīng)該是看到變量或者函數(shù)名字就能“望文生義”,畢竟我們不能把自己寫的所有代碼都做注釋缠黍。
- 關(guān)注重復(fù)代碼:如果出現(xiàn)大量的重復(fù)性代碼弄兜,要考慮將這些代碼抽象出公用函數(shù),以減少代碼量并增強(qiáng)代碼可讀性瓷式。
- 關(guān)注繁瑣的邏輯:如果一個(gè)簡(jiǎn)單的功能卻對(duì)應(yīng)大篇幅的代碼替饿,要考慮一下是不是有比較簡(jiǎn)單的實(shí)現(xiàn)方式,因?yàn)檫^于復(fù)雜的代碼會(huì)給后來者的維護(hù)帶來麻煩蒿往;如果沒有簡(jiǎn)略的辦法盛垦,一定要把注釋寫好。
3.分享設(shè)計(jì)瓤漏、技術(shù)腾夯、知識(shí)和經(jīng)驗(yàn)
- 在代碼審查的過程中,大家往往把關(guān)注點(diǎn)放在發(fā)現(xiàn)代碼的不足上蔬充,忽略了代碼評(píng)審過程中的設(shè)計(jì)思想蝶俱、技術(shù)方法、業(yè)務(wù)知識(shí)的傳播饥漫,我覺得這些內(nèi)容也是非常重要的榨呆,也需要同時(shí)關(guān)注。
- 評(píng)審者在自己的代碼時(shí)會(huì)深入業(yè)務(wù)流程庸队,參與這可以看到評(píng)審代碼的一些算法积蜻、數(shù)據(jù)結(jié)構(gòu)闯割、設(shè)計(jì)模式甚至是系統(tǒng)架構(gòu)等知識(shí)以及評(píng)審者在編碼過程中踩過的坑;通過這些信息參與者可以提升自己的業(yè)務(wù)水平和技術(shù)能力使得整個(gè)團(tuán)隊(duì)的水平得到提高竿拆。
- 參與者除了要有這種學(xué)習(xí)意識(shí)外宙拉,評(píng)審者也要想辦法讓參與者更加快速高效的去理解代碼中傳播的知識(shí),這樣能幫助提升Review速度丙笋,所以建議評(píng)審者能簡(jiǎn)單介紹一下項(xiàng)目的背景以及詳細(xì)設(shè)計(jì)谢澈,這些信息的介紹有以下好處:
- 首先,代碼的設(shè)計(jì)是按照詳細(xì)設(shè)計(jì)來執(zhí)行的御板,但是設(shè)計(jì)者在真正code的時(shí)候會(huì)出現(xiàn)一些變動(dòng)锥忿,這些變動(dòng)要給大家一個(gè)同步;
- 其次怠肋,參與過詳細(xì)設(shè)計(jì)的人可能由于沒有直接參與的code敬鬓,時(shí)間長(zhǎng)會(huì)忘記之前詳細(xì)設(shè)計(jì)的流程,簡(jiǎn)單介紹之后就會(huì)讓參與者想起灶似,方便參與者的理解列林;
- 第三,對(duì)于沒參與詳細(xì)設(shè)計(jì)的同學(xué)酪惭,在簡(jiǎn)單介紹過這些信息后希痴,可以有個(gè)大致了解,不然整個(gè)評(píng)審過程會(huì)很煎熬春感;
- 所以砌创,如果參與者對(duì)代碼的信息不理解,會(huì)造成參與者理解代碼的難度鲫懒,也就不能提出有建設(shè)性的意見嫩实,同時(shí)也難以學(xué)到評(píng)審中傳播的知識(shí);這一點(diǎn)在之前的評(píng)審中是比較容易被大家忽略的窥岩,尤其是在跨團(tuán)隊(duì)代碼評(píng)審時(shí)甲献,準(zhǔn)備不足和經(jīng)驗(yàn)不足的同學(xué)是很難理解對(duì)方在講什么的。
- 講解code的時(shí)候最好是以接口功能為單位去講解
- 如果評(píng)審者一下子把所有的詳細(xì)設(shè)計(jì)都講解完颂翼,可能會(huì)因?yàn)樾畔⒘勘容^大晃洒,或者設(shè)計(jì)到一些細(xì)節(jié)問題,參與者不能有效的記住或理解也會(huì)影響評(píng)審的速度和效率朦乏;
- 評(píng)審者可以在講解的過程中分享一下自己踩過的坑球及,參與者可以隨時(shí)根據(jù)自己發(fā)現(xiàn)的問題進(jìn)行討論。
如何迅速完成CodeReview呻疹?
所謂的迅速就是節(jié)省時(shí)間吃引,只要我們盡量避免一些意義不大的事情就能節(jié)省時(shí)間,加快評(píng)審速度,要做到這點(diǎn)建議大家盡量不要做以下這些事情:
1.不要刻意地去尋找代碼bug
- 有些代碼的邏輯是比較復(fù)雜的镊尺,如果是很容易就發(fā)現(xiàn)的缺陷朦佩,大多數(shù)情況下評(píng)審者自己在編碼過程就會(huì)發(fā)現(xiàn),那么剩下不容易發(fā)現(xiàn)的缺陷要發(fā)現(xiàn)也會(huì)花費(fèi)較多的時(shí)間鹅心,這些問題可以交給測(cè)試人員去發(fā)現(xiàn)吕粗;
- 如果參與者刻意去找bug會(huì)造成顧此失彼,忽略更重要的東西旭愧;當(dāng)然,有些bug你可能一眼就看出來了宙暇,那提出來就再好不過了输枯。
2.不要按照自己的編程風(fēng)格去評(píng)論別人的代碼
- 有些人參與者比較自信,對(duì)自己寫得代碼感覺很滿意占贫,所以有時(shí)候就會(huì)根據(jù)自己熟悉的編碼語言或者編碼風(fēng)格去評(píng)論別人的代碼桃熄;
- 作為參與者,只要覺得評(píng)審者的代碼符合命名要求和設(shè)計(jì)要求就可以了型奥,但假如評(píng)審者的代碼缺陷很明顯瞳收,可以提出帶大家進(jìn)行討論。
3.不要帶著抨擊和質(zhì)疑別人能力的心態(tài)去進(jìn)行代碼評(píng)審
- 有時(shí)候參與者可能心情不好厢汹,或者感覺對(duì)方是新人就忍不住會(huì)抨擊對(duì)方的代碼螟深,這樣會(huì)比較容易在模棱兩可的問題上浪費(fèi)時(shí)間;
- 參與者可能認(rèn)為A方法好烫葬,評(píng)審者可能認(rèn)為B方法也不壞界弧,這樣就會(huì)造成沒有必要的爭(zhēng)論而浪費(fèi)時(shí)間。
4.不要在不確定的問題上爭(zhēng)來爭(zhēng)去
- 大家在討論的時(shí)候如果某些問題討論一段時(shí)間以后仍然沒有結(jié)論搭综,或者需要第三方確認(rèn)或者評(píng)審者不能馬上理解參與者提出的意見時(shí)垢箕,不要花太多時(shí)間討論這些問題;
- 把這些問題先記錄下來兑巾,等會(huì)議結(jié)束后評(píng)審者可以與參與者進(jìn)行線下討論条获,同時(shí)將這些問題根據(jù)自己的理解進(jìn)行解決,之后給大家一個(gè)反饋即可蒋歌,這樣可以節(jié)省很多時(shí)間帅掘。
5.不要聽不進(jìn)別人的意見
- 有些評(píng)審者比較固執(zhí),不愿意接受大家的意見奋姿,會(huì)造成一些不必要的爭(zhēng)端和討論锄开,浪費(fèi)時(shí)間;
- 當(dāng)然称诗,有時(shí)候參與者的意見不見得是最好的萍悴,作為評(píng)審者將其作為一個(gè)參照的方向和視角,如果存在爭(zhēng)論,這些建議也可以做成會(huì)議記錄癣诱,評(píng)審者私下和建議提出者討論以后給大家一個(gè)結(jié)論计维。
6.參與者最好不要自己都沒想明白就提意見
- 如果參與者自己沒有想明白的事情就去提意見,那么評(píng)審者反問的時(shí)候會(huì)浪費(fèi)大家的時(shí)間撕予;
- 參與者可以先將自己的想法大致記下來鲫惶,自己想清楚了之后再提給評(píng)審者也是節(jié)省時(shí)間的辦法。
7.評(píng)審前最好先通過代碼靜態(tài)檢查工具檢測(cè)
- 一般規(guī)范性的問題都可以通過靜態(tài)檢測(cè)工具發(fā)現(xiàn)实抡,借助工具是最省事欠母,也是效率最高的,還可以避免大家都評(píng)審時(shí)提出很多規(guī)范性問題吆寨,而遺漏了業(yè)務(wù)邏輯赏淌、設(shè)計(jì)合理性等問題。
寫在最后
希望我們都能夠有效而迅速進(jìn)行CoderReview啄清,一方面提升代碼質(zhì)量本身六水,另一方面也可以創(chuàng)造一個(gè)良好的學(xué)習(xí)氛圍互相支持提升團(tuán)隊(duì)的整體代碼水平。