技術(shù)團(tuán)隊(duì)如何高效落地代碼CR
?引言
代碼CR(Code Review)是軟件研發(fā)活動(dòng)中保障平臺(tái)產(chǎn)品質(zhì)量的重要環(huán)節(jié),相信很多技術(shù)團(tuán)隊(duì)平常都會(huì)進(jìn)行代碼CR。就拿阿里來(lái)說(shuō),一般周二和周四都是發(fā)布日,那么在發(fā)布上線某項(xiàng)功能之前都要組織進(jìn)行發(fā)布代碼CR,CR不通過(guò)的代碼必須修改檢查通過(guò)后才能發(fā)布上線,可見(jiàn)一線互聯(lián)網(wǎng)大廠技術(shù)團(tuán)隊(duì)對(duì)于代碼CR的重視程度。雖然大家對(duì)于代碼CR都不陌生,但是在自己團(tuán)隊(duì)中實(shí)際落地的時(shí)候不免還是會(huì)遇到這樣或者那樣的問(wèn)題,比較典型的問(wèn)題有如下幾種:
1、到底是所有的代碼都需要進(jìn)行CR,還是只要核心業(yè)務(wù)代碼才需要進(jìn)行CR?
2、怎樣才能讓reviwer能夠認(rèn)真評(píng)審代碼?
3、線上CR還是線下CR?
4、代碼CR很費(fèi)時(shí)間和精力,如何才能保證在花費(fèi)的時(shí)間和精力后可以達(dá)到預(yù)期效果?
本文就和大家探討下到底怎么做才能在技術(shù)團(tuán)隊(duì)中高效的落地代碼CR活動(dòng),而不至于最后導(dǎo)致代碼評(píng)審活動(dòng)流于形式只是走個(gè)流程而已。
為什么要進(jìn)行代碼CR
提升團(tuán)隊(duì)代碼水平
一般技術(shù)團(tuán)隊(duì)都會(huì)由不同技術(shù)水平以及不同工作年限的同學(xué)組成,而Code Review是非常好的大家在一起互相學(xué)習(xí)代碼設(shè)計(jì)的機(jī)會(huì),因?yàn)樵贑ode Reiew過(guò)程中不僅僅會(huì)檢查業(yè)務(wù)代碼邏輯問(wèn)題,還包含了結(jié)構(gòu)設(shè)計(jì)、程序性能、代碼安全、程序魯棒性等等方面綜合性檢查。因此團(tuán)隊(duì)中的核心骨干如果能夠重度參與代碼CR活動(dòng)中,不僅在一定程度上可以幫助其他同學(xué)的成長(zhǎng),同時(shí)也可以協(xié)助新同學(xué)快速融入團(tuán)隊(duì)。
另外在編碼的時(shí)候,代碼CR機(jī)制會(huì)像一只無(wú)形的手,不斷鞭策著團(tuán)隊(duì)成員不要寫(xiě)爛代碼。因?yàn)榇蠹抑雷约簩?xiě)的代碼需要在團(tuán)隊(duì)內(nèi)部進(jìn)行公開(kāi)的CR,這樣壓力就會(huì)油然而生,它會(huì)促進(jìn)自己不要寫(xiě)爛代碼,因?yàn)槊總€(gè)人也不希望自己寫(xiě)的爛代碼曝光在大家面前,這樣自己面子上也掛不住。因此CR機(jī)制在一定程度上可以讓團(tuán)隊(duì)同學(xué)避免寫(xiě)一些短期收益的代碼,從而欠下技術(shù)債留給未來(lái)維護(hù)同學(xué)。
CodeReview不是人情世故,而是程序員的技術(shù)煉金場(chǎng)。
?確保設(shè)計(jì)實(shí)現(xiàn)一致
在程序猿的日常工作中,通常在業(yè)務(wù)方需求KO之后會(huì)進(jìn)行對(duì)應(yīng)需求的設(shè)計(jì)和實(shí)現(xiàn)。但是在實(shí)際的研發(fā)活動(dòng)中,經(jīng)常會(huì)出現(xiàn)實(shí)現(xiàn)和設(shè)計(jì)之間存在一定的偏差gap,而這些gap可能會(huì)導(dǎo)致后期上線的Bug以及代碼維護(hù)問(wèn)題,因此在代碼CR的時(shí)候就要重點(diǎn)關(guān)注設(shè)計(jì)與代碼實(shí)際實(shí)現(xiàn)之間存在差異問(wèn)題,尤其是需求Owner要重點(diǎn)review業(yè)務(wù)-》設(shè)計(jì)》實(shí)現(xiàn)的一致性。
統(tǒng)一團(tuán)隊(duì)編碼規(guī)范
在實(shí)際的代碼CR過(guò)程中,經(jīng)驗(yàn)豐富的老司機(jī)分別會(huì)從命名、代碼結(jié)構(gòu)設(shè)計(jì)、程序性能等方面進(jìn)行分析。其實(shí)同樣一個(gè)需求,讓100個(gè)程序員來(lái)做,寫(xiě)出來(lái)的代碼可能有100種樣子,我覺(jué)得這很正常。實(shí)現(xiàn)邏輯可以五花八門(mén),但是在一些比較通用的編碼規(guī)范層面,需要保持統(tǒng)一。
如果有這樣的業(yè)務(wù)場(chǎng)景,你定義了一個(gè)訂單的DTO類(lèi),其中有個(gè)字段是訂單的審核狀態(tài),假設(shè)有待審核、審核通過(guò)、審核不通過(guò)三種狀態(tài),我們通過(guò)定義枚舉的方式來(lái)表示不同的狀態(tài)。這里的inspectStatus分別對(duì)應(yīng)枚舉中的三個(gè)狀態(tài)屬性。大家覺(jué)得下面的代碼有什么問(wèn)題?
public class OrderDTO {
...
/**
*審核狀態(tài)
*/
private Integer inspectStatus
...
}
實(shí)際上并不是代碼本身有什么問(wèn)題(都是屬性能有啥問(wèn)題),而是在可讀性方面存在問(wèn)題。假設(shè)你是剛接手負(fù)責(zé)這個(gè)模塊,當(dāng)你看到這個(gè)定義的時(shí)候,是不是迫切想知道到底這個(gè)審核狀態(tài)有哪幾種,但是由于代碼不熟悉,你并不知道去哪里尋找,因此在可讀性以及可維護(hù)性方面不盡如人意。
遇到這種情況我們可以在審核狀態(tài)字段的注釋上面加上一個(gè)@link,可以直接鏈接到對(duì)應(yīng)的狀態(tài)枚舉類(lèi),這樣后來(lái)維護(hù)業(yè)務(wù)的同事可以通過(guò)實(shí)體類(lèi)直接查看到訂單的各個(gè)審核狀態(tài),總比自己無(wú)頭蒼蠅的在工程中找或者問(wèn)其他組內(nèi)同事來(lái)的效率高。因此我們?cè)诰帉?xiě)代碼的時(shí)候不僅要考量如何實(shí)現(xiàn)當(dāng)前的需求,也要想著如果未來(lái)別人來(lái)維護(hù)我寫(xiě)的代碼,那么怎樣才能讓后續(xù)維護(hù)的同學(xué)更好更快的掌握業(yè)務(wù)邏輯。
public class OrderDTO {
...
/**
*審核狀態(tài)
*{@link com.mufeng.eshop.biz.order.InspectStatusEnum}
*/
private Integer inspectStatus
...
}
這里舉了個(gè)看似簡(jiǎn)單的例子,但是在實(shí)際的編碼中卻十分常見(jiàn),因此需要對(duì)團(tuán)隊(duì)中的代碼規(guī)范進(jìn)行統(tǒng)一的規(guī)定。代碼規(guī)范性層面可以參考《阿里巴巴Java開(kāi)發(fā)手冊(cè)》,另外Idea有對(duì)應(yīng)的插件Alibaba Java Coding Guidelines。
厘清業(yè)務(wù)邏輯細(xì)節(jié)
一般一個(gè)技術(shù)團(tuán)隊(duì)可能會(huì)負(fù)責(zé)多條不同的業(yè)務(wù)線。這些業(yè)務(wù)可能都是存在一定的關(guān)聯(lián)關(guān)系的。但是平時(shí)同學(xué)們都在忙于應(yīng)付各種各樣的業(yè)務(wù)方需求,大家可能沒(méi)有太關(guān)注同組同學(xué)所負(fù)責(zé)的業(yè)務(wù)的具體邏輯細(xì)節(jié),因此通過(guò)代碼CR可以讓大家有機(jī)會(huì)了解各個(gè)業(yè)務(wù)線的邏輯細(xì)節(jié),這樣更加便于團(tuán)隊(duì)成員厘清上下游的業(yè)務(wù)邏輯,將來(lái)涉及到完整業(yè)務(wù)鏈業(yè)務(wù)需求的時(shí)候,在進(jìn)行設(shè)計(jì)的時(shí)候可以考慮的更加全面以及識(shí)別一些關(guān)鍵設(shè)計(jì)點(diǎn)。
如何保證代碼CR效果
如果我們想要保證代碼CR的落地效果,我們就需要搞清楚到底哪些因素會(huì)影響技術(shù)團(tuán)隊(duì)代碼CR效果。這里大致總結(jié)了日常工作中影響代碼CR效果的因素:
對(duì)于提交代碼評(píng)審的同學(xué):
1、不清楚提交代碼CR的范圍;
2、不清楚需要給哪些人提交代碼CR;
3、怎樣才能讓別人認(rèn)真評(píng)審代碼;
對(duì)于評(píng)審別人代碼的同學(xué):
1、不清楚需要CR代碼的業(yè)務(wù)上下文是怎樣的,不容易判斷代碼結(jié)構(gòu)設(shè)計(jì)的合理性;
2、一下子提交幾千行代碼,哪些代碼是CR的重點(diǎn)內(nèi)容,哪些不是;
上述問(wèn)題都是制約技術(shù)團(tuán)隊(duì)代碼CR落地效果最常見(jiàn)的問(wèn)題,我們到底應(yīng)該怎么解決這額問(wèn)題呢?
線上評(píng)審結(jié)合線下評(píng)審
線上評(píng)審一般是主要的代碼CR方式,但是在提交評(píng)審的時(shí)候還是要遵循一定的原則,以便于提高代碼評(píng)審的效率。
1、每次提交CR的代碼不能過(guò)多,如果每次評(píng)審的時(shí)候一下子推給別人幾千行代碼,估計(jì)對(duì)應(yīng)的reviwer看都不想看,很難保證review的質(zhì)量;
2、在提交評(píng)審的時(shí)候,需要附上一定的說(shuō)明,闡述清楚這些代碼主要實(shí)現(xiàn)什么樣的業(yè)務(wù)需求,主要核心邏輯在哪些文件中,這樣reviwer在評(píng)審代碼的時(shí)候可以有的放矢。
線下評(píng)審作為線上評(píng)審的重要組成部分,比如一周一到兩次的線下會(huì)議評(píng)審一般可以滿足需要。在線上評(píng)審之前最好先和reviwer敲定好時(shí)間以及需要評(píng)審的代碼,提前準(zhǔn)備好需要CR的代碼背景,比如說(shuō)對(duì)應(yīng)具體的需求是什么,自己在進(jìn)行代碼落地的時(shí)候是如何分析問(wèn)題的,大致的類(lèi)結(jié)構(gòu)是如何設(shè)計(jì)的等等,這樣reviewer們可以比較清晰的理解代碼的背景。
另外線下評(píng)審的代碼量不要過(guò)大,時(shí)間盡量保持在一個(gè)小時(shí)左右。評(píng)審會(huì)議的時(shí)候要記錄大家提出來(lái)的建議以及問(wèn)題,會(huì)后修改后再和大家對(duì)焦確認(rèn)。
找到合適的代碼評(píng)審者
將代碼提交給合適的Reviewer進(jìn)行評(píng)審這一點(diǎn)非常重要,因?yàn)槿绻麑⒋a提交給了沒(méi)什么業(yè)務(wù)關(guān)聯(lián)的或者和自己技術(shù)水平差不多的Reviewer,一方面業(yè)務(wù)不相關(guān)的同學(xué)很難理解其中的業(yè)務(wù)規(guī)則代碼看起來(lái)也費(fèi)時(shí)又費(fèi)力,另一方面水平相似無(wú)法高屋建瓴的提出來(lái)改進(jìn)意見(jiàn),因此基本很難獲得比較好的review結(jié)果。
1、向團(tuán)隊(duì)中經(jīng)驗(yàn)豐富的程序員提交CR,以便于獲得更加高水平的代碼設(shè)計(jì)反饋;
2、向業(yè)務(wù)需求Owner提交CR,需求Owner一般對(duì)于這部分的業(yè)務(wù)需求非常熟悉,因此可以從業(yè)務(wù)層面或者技術(shù)層面給出更好的意見(jiàn);
3、向修改過(guò)相同文件的同學(xué)提交CR,這樣大家彼此知道自己的修改意圖以及原因,便于評(píng)估影響范圍。
建立評(píng)審獎(jiǎng)勵(lì)機(jī)制
或許是因?yàn)榇蠹移綍r(shí)工作太忙,或許是因?yàn)樘峤唤o了不合適的reviewer。我們總是擔(dān)心別人到底有沒(méi)有認(rèn)真CR我們的代碼,那我們到底該怎么激發(fā)大家認(rèn)真review代碼呢?這里提供一個(gè)可落地實(shí)操的機(jī)制,比如我們可以在團(tuán)隊(duì)內(nèi)部建立明確的代碼CR獎(jiǎng)勵(lì)機(jī)制,對(duì)于在代碼CR過(guò)程中評(píng)審出來(lái)的高質(zhì)量Bug的reviewer進(jìn)行獎(jiǎng)勵(lì)(獎(jiǎng)牌或者獎(jiǎng)杯都可以,同時(shí)在P8下面的大團(tuán)隊(duì)中進(jìn)行通報(bào)表?yè)P(yáng)提升影響力)。每個(gè)月評(píng)選捉蟲(chóng)高手,注重?cái)?shù)量更加注重質(zhì)量,通過(guò)這樣的獎(jiǎng)勵(lì)機(jī)制來(lái)正向引導(dǎo)大家去積極進(jìn)行代碼CR。
不過(guò)這里面存在一個(gè)隱含的Bug,就是如果團(tuán)隊(duì)中有一個(gè)技術(shù)大牛,那么大家可能都會(huì)把代碼提交給他來(lái)審核,那么技術(shù)大牛代碼評(píng)審量就會(huì)非常大,對(duì)于大牛來(lái)說(shuō)就變成甜蜜的負(fù)擔(dān)了,因此還是要有所取舍,比較核心重要的代碼再提交給技術(shù)大牛進(jìn)行評(píng)審,這樣既保證了核心業(yè)務(wù)邏輯代碼的評(píng)審權(quán)威性,也不會(huì)給團(tuán)隊(duì)中資深工程師的工作負(fù)擔(dān)。