之前的博文也寫(xiě)過(guò)兩篇關(guān)于Code Review的文章陌选,出發(fā)點(diǎn)的各不相同:
QA測(cè)試是否要看代碼——QA讀產(chǎn)品代碼的必要性
Code Review的思考——Code Review存在的必要性
閱讀代碼小感——閱讀代碼的一些方法論
似乎Code Review相關(guān)的話題特別容易水文章??理郑。其實(shí)網(wǎng)上有很多介紹Code Review的流程介紹,中英資料都不缺少咨油,但是并沒(méi)有一個(gè)更加系統(tǒng)的文章來(lái)闡述一個(gè)完整可行的Code Review方案您炉,具體到流程的每一個(gè)環(huán)節(jié)。
相比于再水一篇爛大街的《如何做Code Review》役电,梳理一篇更系統(tǒng)的Code Review落地方案赚爵,給有需要的同學(xué)提供參考似乎更有趣也更有意義。本著這樣的想法法瑟,我從QA的視野冀膝,嘗試從研發(fā)效率的角度整理一些經(jīng)驗(yàn)以及想法,其中有不少靈感是來(lái)源于當(dāng)前所在的研發(fā)團(tuán)隊(duì)正在落地的Code Review方案霎挟,Code Review后面簡(jiǎn)稱CR窝剖。
Code Review 背景
大家都知道Bug越早被發(fā)現(xiàn),修復(fù)成本越低氓扛,各種自動(dòng)化檢查就是盡可能地讓測(cè)試左移,在研發(fā)流程早期發(fā)現(xiàn)Bug论笔。按照這個(gè)思路從研發(fā)流程的角度看采郎,先有RD自測(cè),然后是RD的提交代碼前后的單元測(cè)試狂魔,接下來(lái)是代碼合入主干分支觸發(fā)的自動(dòng)化測(cè)試以及CR蒜埋。先拋開(kāi)RD的自測(cè)與單測(cè)不說(shuō),這兩個(gè)點(diǎn)想要做好時(shí)常難度較大最楷,需要很強(qiáng)的推動(dòng)力整份。那從這個(gè)角度看待错,代碼合入主干分支的時(shí)間點(diǎn)基本上是外界介入測(cè)試的最早階段,而CR正是一種早期發(fā)現(xiàn)Bug的手段烈评,自然而然可以融合進(jìn)來(lái)火俄。
另一方面,CR落地情況體現(xiàn)了一個(gè)研發(fā)團(tuán)隊(duì)的工程氛圍讲冠,新人很容易通過(guò)CR獲得技術(shù)提升瓜客;同時(shí),CR提升了大家對(duì)同一個(gè)模塊的熟悉度竿开,避免一個(gè)模塊只有單一同學(xué)了解谱仪,防止人員流動(dòng)導(dǎo)致代碼開(kāi)發(fā)維護(hù)上的真空期,好比分布式系統(tǒng)是不希望出現(xiàn)單點(diǎn)否彩,master節(jié)點(diǎn)要隨時(shí)可被替代一樣疯攒,否則系統(tǒng)出現(xiàn)故障的概率就變高。
更進(jìn)一步列荔,線上事故經(jīng)常有敬尺,我們的QA聯(lián)合RD對(duì)一系列線上事故做分析之后,發(fā)現(xiàn)很多造成事故的Bug都具備在CR階段被發(fā)現(xiàn)的可能性(當(dāng)然不是100%能被發(fā)現(xiàn))肌毅。
綜上三點(diǎn)筷转,已經(jīng)闡述了Code Review的必要性。
QA如何做 Code Review
QA為何難以參與CR
很多QA可能覺(jué)得CR是RD的工作悬而,跟QA沒(méi)有關(guān)系呜舒,這是片面的。CR確實(shí)是RD主導(dǎo)笨奠,但也不失為QA貫徹測(cè)試左移原則一個(gè)好的切入點(diǎn)袭蝗,還能順便看看產(chǎn)品代碼從細(xì)節(jié)上熟悉被測(cè)對(duì)象,何樂(lè)而不為般婆?
個(gè)人感覺(jué)QA難以在CR中體現(xiàn)出參與感的一個(gè)最關(guān)鍵的點(diǎn)到腥,可能是很多QA本身缺少一定的代碼經(jīng)驗(yàn)或白盒測(cè)試思維導(dǎo)致CR參與度低,換句話說(shuō)蔚袍,就是缺少做CR經(jīng)驗(yàn)和方法論乡范,這些都是可以通過(guò)實(shí)踐去積累的。老QA員工就不看重CR啤咽,上梁不正下梁歪晋辆,新來(lái)的QA同學(xué)很可能也不會(huì)看重CR。另一方面宇整,確實(shí)是日常需求測(cè)試比較重瓶佳,尤其是客戶端(移動(dòng)端和Web端)的同學(xué),業(yè)務(wù)壓力大鳞青,是客觀現(xiàn)象霸饲,這就不在這里做討論了为朋。私以為,一個(gè)好QA厚脉,除了充當(dāng)流程規(guī)范的把關(guān)者外习寸,技術(shù)能力是不應(yīng)該跟RD相差太遠(yuǎn)的。
我所在的QA團(tuán)隊(duì)做CR也一直有問(wèn)題器仗,如下:
業(yè)務(wù)類需求(泛指常規(guī)具備交互因素的功能)融涣,大多數(shù)都是需求完成測(cè)試后才發(fā)起CR,CR的時(shí)間節(jié)點(diǎn)過(guò)于滯后精钮,導(dǎo)致CR發(fā)現(xiàn)問(wèn)題改代碼后又缺失測(cè)試環(huán)節(jié)威鹿。正確做法應(yīng)該在測(cè)試前或者測(cè)試中完成CR,或CR修改完后復(fù)測(cè)
技術(shù)類需求(泛指代碼優(yōu)化或UI不好體現(xiàn)的功能)轨香,QA沒(méi)有參與需求前期階段忽你,在不清楚上下文的情況下被RD拉進(jìn)去對(duì)陌生功能模塊進(jìn)行CR,沒(méi)有效果
鑒于上面兩點(diǎn)臂容,QA很難發(fā)揮真正的合碼卡口質(zhì)量擔(dān)保的作用科雳,也沒(méi)辦法建立RD對(duì)QA在技術(shù)上的認(rèn)可度,QA的CR流于形式(甚至RD的CR也是)
QA視角的CR目標(biāo)
最終目標(biāo)都是質(zhì)量保障脓杉,CR是一種測(cè)試左移的手段糟秘,意圖在測(cè)試前期發(fā)現(xiàn)Bug,降低Bug修復(fù)的成本球散。QA視角的CR其實(shí)是對(duì)RD視角的CR做補(bǔ)充尿赚,在關(guān)注點(diǎn)上會(huì)有區(qū)別。QA是以發(fā)現(xiàn)代碼中的質(zhì)量缺陷為首要目標(biāo)蕉堰,也就是找Bug凌净,而不是代碼是否優(yōu)雅或代碼有無(wú)更優(yōu)實(shí)現(xiàn)方式。
QA的CR準(zhǔn)則
要明白QA在CR中扮演的角色屋讶,CR的關(guān)注點(diǎn)可以很多冰寻,如:代碼設(shè)計(jì)、可維護(hù)性皿渗、可擴(kuò)展性斩芭、安全、性能等乐疆,但并非要求QA面面俱到划乖,作為質(zhì)量把控的角色,QA應(yīng)該更集中在功能實(shí)現(xiàn)和代碼健壯性上诀拭。
1. 不糾結(jié)編碼風(fēng)格
- 理想情況下迁筛,編碼風(fēng)格的把關(guān)應(yīng)該交由專門(mén)工具(各種lint)或RD自己保證煤蚌,QA的主要精力應(yīng)該在代碼邏輯上而非命名風(fēng)格耕挨、函數(shù)長(zhǎng)度细卧、函數(shù)返回值等這類規(guī)范細(xì)節(jié)上。
2. 明確 Change List
- 改動(dòng)范圍是QA判斷CR策略的核心信息筒占,QA對(duì)代碼本身以及模塊設(shè)計(jì)的熟悉度肯定不及RD贪庙,在CR時(shí)需要獲取更多輔助信息協(xié)助CR。
- 知悉改動(dòng)范圍可以在業(yè)務(wù)知識(shí)上先行識(shí)別代碼風(fēng)險(xiǎn)翰苫,然后根據(jù)風(fēng)險(xiǎn)點(diǎn)從代碼層面上逐個(gè)排查——可以理解為QA根據(jù)改動(dòng)先設(shè)計(jì) CR用例止邮,再拿具體代碼對(duì)著 CR用例 來(lái)找Bug,如針對(duì)一段循環(huán)邏輯奏窑,QA基于業(yè)務(wù)知識(shí)知道循環(huán)的結(jié)束條件导披,再結(jié)合具體實(shí)現(xiàn)尋找是否存在導(dǎo)致死循環(huán)的潛在條件場(chǎng)景。
- Double check附帶的說(shuō)明文檔埃唯,以防理解錯(cuò)誤或遺漏信息撩匕。
3. 思考Bug在哪里
- 請(qǐng)跟我默念:什么場(chǎng)景下這塊代碼會(huì)出Bug。QA CR關(guān)鍵是要做思維切換 —— 盡量刻意遍歷墨叛、覆蓋可能出Bug的場(chǎng)景止毕。而不是順著代碼邏輯看下去有沒(méi)有疑點(diǎn),可能就被RD的思維同化了漠趁。比如看到一個(gè)if判斷扁凛,就要思考這個(gè)判斷變量的邊界值、觸發(fā)場(chǎng)景等闯传。
- 得先理解RD的實(shí)現(xiàn)思路谨朝,可能還是要順著RD的思路先過(guò)一遍,理清功能細(xì)節(jié)與調(diào)用關(guān)系丸边,再轉(zhuǎn)換思維重看一遍叠必。
4. 疑問(wèn)找RD解答
- 尤其是對(duì)于技術(shù)需求,大多數(shù)情況下不能保證QA的前期參與妹窖,QA不清楚需求背景與代碼設(shè)計(jì)纬朝,存在嚴(yán)重信息不對(duì)稱,無(wú)法google解決的疑問(wèn)不要花太多時(shí)間琢磨骄呼,直接問(wèn)RD的效率更高共苛。
- 不要覺(jué)得問(wèn)實(shí)現(xiàn)相關(guān)的問(wèn)題很羞恥,RD之間review代碼都要互相了解實(shí)現(xiàn)細(xì)節(jié)蜓萄,QA就更不用說(shuō)了隅茎,比如特殊實(shí)現(xiàn)手法、語(yǔ)言高級(jí)特性嫉沽、改動(dòng)點(diǎn)涉及的調(diào)用關(guān)系等辟犀,都能找RD解答。
- 如果大范圍看不懂且該CR很重要绸硕,果斷找RD當(dāng)面了解堂竟,或遠(yuǎn)程語(yǔ)音魂毁。
5. 嚴(yán)格控制時(shí)間花銷
- 保證CR的速度,把控時(shí)間花銷出嘹,很重要O!税稼!特別是一個(gè)QA對(duì)接好多RD的需求這種現(xiàn)狀烦秩,如果集成代碼那天來(lái)5個(gè)Merge Request,一次CR半小時(shí)郎仆,那當(dāng)天就沒(méi)了快一半的時(shí)間(算上任務(wù)切換的耗時(shí))只祠。QA做CR以走讀為主,關(guān)鍵代碼細(xì)看即可扰肌,不必每行都看懂铆农。
- 不同的需求對(duì)CR要求不一樣,平臺(tái)強(qiáng)相關(guān)的進(jìn)階技術(shù)狡耻、大范圍多文件改動(dòng)墩剖、基于復(fù)雜功能的調(diào)整、UI需求等QA可能較難review夷狰,建議粗粒度CR岭皂;對(duì)于CR更友好的需求,如新增一個(gè)依賴少的獨(dú)立小功能沼头,QA可以獲取到完整的上下文爷绘,應(yīng)該多花一些時(shí)間CR。
- CR來(lái)的時(shí)間不合適进倍,考慮換一個(gè)具備相關(guān)能力的QA同學(xué)review土至。
6. 可以給RD提建議
- 覺(jué)得存在遺漏的場(chǎng)景或未知風(fēng)險(xiǎn)的代碼,應(yīng)該指出來(lái)猾昆,可能是不知悉代碼上下文帶來(lái)的誤判陶因,也有可能是真的有問(wèn)題!
QA做CR的一些經(jīng)驗(yàn)
RD做CR更多的是從風(fēng)格垂蜗、代碼設(shè)計(jì)楷扬、注釋、功能贴见、性能烘苹、安全、可維護(hù)性片部、等各種維度下手镣衡,QA做CR更多是從功能、異常處理、性能廊鸥、可測(cè)性方面下手然爆,關(guān)注點(diǎn)會(huì)比RD少但是更集中。一般可以根據(jù)代碼Diff黍图,順著數(shù)據(jù)流轉(zhuǎn)鏈路往前后延伸走讀,下面列舉一些經(jīng)驗(yàn)性的關(guān)注點(diǎn)奴烙。
可以讓RD當(dāng)面解釋數(shù)據(jù)流轉(zhuǎn)過(guò)程助被,有奇效。
?? QA重要考點(diǎn)
- 正確初始化
- 弱網(wǎng)切诀、斷網(wǎng)揩环、失敗
- 緩存清理、緩存失效
- 持久化數(shù)據(jù)被刪
- 變量判空
- 越界
- 循環(huán)結(jié)束條件
- 數(shù)據(jù)格式與類型非預(yù)期(常見(jiàn)服務(wù)端線上事故)
- 鎖獲确恰:餓死丰滑、死鎖
- 阻塞與非阻塞、同步還是異步
- 內(nèi)存/資源泄露倒庵,尤其是異常邏輯
- 隱式類型轉(zhuǎn)換
- 上下游接口明確
- 實(shí)現(xiàn)方案有缺陷
- 安全問(wèn)題(如關(guān)鍵信息明文持久化)
- ab實(shí)驗(yàn)相關(guān)代碼要了解開(kāi)實(shí)驗(yàn)的詳情
一個(gè)簡(jiǎn)單卻又經(jīng)常被忽略的輔助信息:歷史commit message褒墨。
代碼可測(cè)性
如果需要QA做具體測(cè)試的需求,還要關(guān)注一下代碼程序的可測(cè)性擎宝。
- 可驗(yàn)證性
- 添加必要的日志
- 因輸入導(dǎo)致變更的點(diǎn)就是輸出郁妈,輸出全部可查看(正例:中間數(shù)據(jù)的落盤(pán))
- 提示信息可讀,意義明確且唯一(反例:返回碼意義不明確且多個(gè)不同錯(cuò)誤用同一個(gè)返回碼)
- 可操作性
- 簡(jiǎn)化測(cè)試準(zhǔn)備和測(cè)試清理工作(正例:幾個(gè)標(biāo)志組合的判斷條件绍申,可一鍵完成標(biāo)志設(shè)置噩咪,不需要人工操作場(chǎng)景完成設(shè)置)
- 測(cè)試過(guò)程有易用的配套工具
- 可控制性
- 所有影響輸出的因素都可控(反例:難以構(gòu)造的死鎖現(xiàn)場(chǎng);難以構(gòu)造的內(nèi)部異常)
- 可直接控制中間狀態(tài)的數(shù)據(jù)
- 可分解性
- 大系統(tǒng)中可以針對(duì)小模塊獨(dú)立測(cè)試
- 可理解性
- 文檔明確且隨時(shí)update
- 提供修改背景和影響范圍
CR例子
這里給一些簡(jiǎn)單例子极阅,可能不嚴(yán)謹(jǐn)胃碾,體會(huì)到意思即可。
一筋搏、變量沒(méi)有初始化即使用
// 注意java基本類型默認(rèn)有初始值仆百,但是賦初值還是個(gè)好習(xí)慣
public class A{
// ...
}
A a;
// ...
uploadData(a);
</br>
二、代碼不符本意
mainDic已經(jīng)初始化奔脐,if 判空邏輯永遠(yuǎn)為T(mén)rue儒旬,應(yīng)該是 mainDic.count
NSMutableDictionary *mainDic = [NSMutableDictionary dictionary];
if (mainDic){
// ...
}
</br>
三、異常情況遺漏處理 或 處理不完善
如斷網(wǎng)弱網(wǎng)重試帖族、異常拋出未catch栈源、變量不判空。
// 文件資源在拋異常時(shí)沒(méi)有close竖般,資源泄露
try{
OutputStream out = new FileOutputStream("");
// ...
out.close();
}catch(Exception e){
e.printStackTrace();
}
</br>
四甚垦、循環(huán)結(jié)束判斷條件錯(cuò)誤
喜聞樂(lè)見(jiàn)你懂的,不用舉例了。
</br>
五艰亮、手誤寫(xiě)錯(cuò)變量名闭翩、函數(shù)名
int rulesForA(){
// ...
}
int rulesForB(){
// ...
}
A a = new A();
B b = new B()
rulesForA(b); // 手誤寫(xiě)錯(cuò)變量名or函數(shù)名
rulesForB(a);
</br>
六、全局變量與局部變量混淆使用
class Test{
static int a = 0;
public void test(){
int a = 9;
// ...
a += 1; // 可能本意是對(duì)全局變量a自增迄埃,這里錯(cuò)誤把局部變量a自增
}
}
更多關(guān)于做CR的方法論疗韵,谷歌也出了一個(gè)CR工程師實(shí)踐,文末參考資料附上鏈接侄非。
Code Review 配套工具
流程平臺(tái)
想要好好做CR蕉汪,必須要依托工程平臺(tái)的支持,你不可能把別人提交的分支代碼拉到本地來(lái)diff著看吧逞怨,所以針對(duì)CR環(huán)節(jié)也對(duì)工程平臺(tái)提出了一些基本要求:
- 不同的聚合方式來(lái)查看diff:
改動(dòng)涉及的不同倉(cāng)庫(kù)(改動(dòng)涉及多倉(cāng)者疤,分開(kāi)看)
改動(dòng)的文件類型(如統(tǒng)一查看.java后綴的文件改動(dòng))
被修改文件的組成的目錄樹(shù)
- diff代碼顏色高亮展示,支持查看diff代碼以外的其他代碼
- 支持任意代碼添加CR評(píng)論 以及 展示評(píng)論的解決情況
- 展示source分支的歷史commit message
- 展示source分支以及要合并到的target分支
- 綁定文檔模板叠赦,讓RD按模板填寫(xiě)相關(guān)內(nèi)容
- 查看所有需要待CR的Merge Request
精準(zhǔn)pick人
相信有參與CR流程的同學(xué)都會(huì)遇到同一個(gè)問(wèn)題驹马,就是在需求扎堆上車合碼的日期,當(dāng)天會(huì)收到大量CR邀請(qǐng)除秀,不說(shuō)手頭工作進(jìn)度被拖累糯累,收到的CR邀請(qǐng)可能還跟自己負(fù)責(zé)的模塊不相關(guān),尤其是QA同學(xué)對(duì)接多個(gè)RD册踩,可能都會(huì)被不同的RD邀請(qǐng)CR寇蚊。所以這個(gè)問(wèn)題必須要解決:如何更精確地pick CR候選人。
相比于隨機(jī)選擇CR人選棍好,有一個(gè)十分簡(jiǎn)單的解決辦法:通過(guò)后臺(tái)配置仗岸,指定某個(gè)代碼目錄匹配相關(guān)CR人選。一個(gè)代碼目錄應(yīng)該有一到兩個(gè)負(fù)責(zé)人借笙,再加上若干候選人扒怖,CR的時(shí)候自動(dòng)拉負(fù)責(zé)人,候選人則隨機(jī)拉若干個(gè)业稼,這樣基本上就解決了隨機(jī)選擇CR人選導(dǎo)致CR不相關(guān)效果差的問(wèn)題盗痒。
但是隨著模塊越來(lái)越多,團(tuán)隊(duì)越來(lái)越大低散,人員流動(dòng)與代碼變更會(huì)變得十分頻繁俯邓,上面提到的配置名單是否還方便維護(hù)呢?答案肯定是No熔号,每來(lái)一個(gè)新人稽鞭,就要將這個(gè)新人添加到配置里,太麻煩了引镊!還需要一種更精準(zhǔn)的自動(dòng)推薦CR人選的方式朦蕴,這里我有一個(gè)想法:
流程總覽
- RD完成代碼開(kāi)發(fā)篮条,提交代碼發(fā)起Merge Request
- 根據(jù)RD改動(dòng)的文件,結(jié)合 該文件與其他文件的 關(guān)聯(lián)關(guān)系吩抓,獲取被修改文件相關(guān)的其他文件涉茧,層級(jí)上下共x層(可配置)
- 遍歷這些關(guān)聯(lián)文件,逐一找出這些文件模塊的RD(如果是子repo疹娶,獲取repo owner伴栓;如果是子文件,根據(jù)git blame等git命令獲取文件的最新(or最頻繁)改動(dòng)RD雨饺,否則兜底到根據(jù)配置獲取文件負(fù)責(zé)人)
- pick這些RD進(jìn)來(lái)CR代碼钳垮,或者推薦給發(fā)起CR的RD讓ta自己選擇拉誰(shuí)
一個(gè)具體例子
- RD小陳修改了代碼文件A.java,提交后發(fā)起Merge Request
- 分析A.java的改動(dòng)沛膳,發(fā)現(xiàn)本次改動(dòng)中添加/刪除/修改 方法function,根據(jù)A.java的代碼進(jìn)行分析汛聚,方法function屬于類Example锹安,類Example在B.java中被定義聲明,被A.java import了進(jìn)來(lái)倚舀;A.java在文件C.java叹哭、D.java中也有被使用,而C.java痕貌、D.java里定義的類被E.java和F.java調(diào)用风罩。所以最后獲取到關(guān)聯(lián)的上下游文件集合有 [ A.java, B.java, C.java, D.java, E.java, F.java ],下面附一個(gè)簡(jiǎn)單的圖來(lái)表達(dá)這個(gè)上下關(guān)聯(lián)關(guān)系
- 獲取 [ A.java, B.java, C.java, D.java, E.java, F.java, G.java ] 這些代碼文件的CR候選人(這里可以根據(jù)git代碼行修改人獲取對(duì)應(yīng)RD舵稠,也可以配置RD)
- 這些候選RD推薦給CR發(fā)起人超升,讓他選擇拉哪些RD進(jìn)來(lái)CR
代碼文件的關(guān)聯(lián)關(guān)系舉例核心問(wèn)題
如何抽取出代碼文件之間的關(guān)聯(lián)關(guān)系?使用什么樣的靜態(tài)代碼分析技術(shù)哺徊?
以前有接觸過(guò)類似的項(xiàng)目室琢,通過(guò)正則表達(dá)式匹配不同的java語(yǔ)法,匹配范圍包括:類對(duì)象的創(chuàng)建聲明落追、包的引用關(guān)系盈滴,這樣就可以知道一個(gè)文件會(huì)對(duì)外提供什么類,以及它使用了來(lái)自什么包的哪個(gè)類轿钠,進(jìn)一步地巢钓,就可以匹配出兩個(gè)java文件之間是否有關(guān)聯(lián)關(guān)系——你調(diào)用我還是我調(diào)用你,也就是上下游關(guān)聯(lián)關(guān)系疗垛。比如A.java有類A症汹,B.java引入了類A并進(jìn)行使用,那么B.java與A.java就存在關(guān)聯(lián)關(guān)系贷腕。
基于正則的代碼分析方案會(huì)有非常多坑烈菌,一方面是語(yǔ)法很難通過(guò)正則來(lái)窮極表達(dá)阵幸,難免出現(xiàn)語(yǔ)法遺漏覆蓋導(dǎo)致關(guān)聯(lián)關(guān)系的丟失;另外還需要處理大量代碼格式兼容問(wèn)題芽世,代碼格式稍有變動(dòng)(比如敲多倆空格挚赊,代碼中間換行展示)就可能導(dǎo)致正則匹配miss,又會(huì)出現(xiàn)關(guān)聯(lián)關(guān)系丟失济瓢,所以不建議采用正則來(lái)做分析荠割。
業(yè)界更常見(jiàn)的做法,是基于parser獲取的AST(Abstract Syntax Tree)分析文件的關(guān)聯(lián)關(guān)系旺矾。
對(duì)于移動(dòng)端代碼蔑鹦,本身又有很多系統(tǒng)平臺(tái)提供的回調(diào)函數(shù)(比如Android onCreate方法等),這些在關(guān)聯(lián)關(guān)系上還需要做特別處理箕宙。
其他可能的問(wèn)題
- 關(guān)聯(lián)關(guān)系的分析性能嚎朽,能否做到實(shí)時(shí)分析?使用線下分析的關(guān)聯(lián)結(jié)果準(zhǔn)確率多高柬帕?
- 大范圍的改動(dòng)哟忍,比如代碼沉庫(kù)、代碼遷移陷寝,是否也適用锅很?
- 打通代碼庫(kù)提交歷史,具備靜態(tài)代碼分析能力以獲取代碼文件之間的關(guān)聯(lián)關(guān)系凤跑,根據(jù)修改歷史
Code Review 落地
Code Review流程大家應(yīng)該基本清楚爆安,那么CR應(yīng)該如何落地,下面展開(kāi)講述一下仔引。
理念宣講
CR落地扔仓,第一件事就要宣講CR理念,讓大家知道這么一件事情的存在咖耘。最關(guān)鍵是要講清楚為什么要做CR当辐、CR如何嵌入當(dāng)前流程、大家需要比平時(shí)額外做一些什么以及如何做CR鲤看,最后表達(dá)CR正式落地后的預(yù)期收益缘揪。
流程試點(diǎn)
研發(fā)流程改動(dòng)是一件大事,起碼CR的加入义桂,涉及到RD與QA的工作流程變動(dòng)找筝,上上下下就是幾十甚至上百人,再不能100%確定可以獲取足夠的收益前慷吊,流程試點(diǎn)是必須的袖裕。
不得不提,CR本身雖然只是一個(gè)流程環(huán)節(jié)溉瓶,但是CR環(huán)節(jié)效果的好壞跟前置流程直接相關(guān)急鳄,比如需求評(píng)審的粗細(xì)谤民、技術(shù)文檔的質(zhì)量、代碼注釋的多寡等疾宏。
在CR全面推廣普及之前张足,CR可以有多種試點(diǎn)落地形式,比如:
- 做一份人員配對(duì)名單坎藐,幾個(gè)相關(guān)RD為一組为牍,互相review對(duì)方的代碼
- 篩選部分需求放到CR池子,RD選擇想要review的需求自行參與CR
兩種形式各有優(yōu)缺點(diǎn)岩馍,但是第二種形式給了更多自由碉咆,可能參與度更高,但是也要避免需求的扎堆Review蛀恩,尤其是技術(shù)性很強(qiáng)很高大上的需求疫铜,畢竟做工程師很多都會(huì)對(duì)高深技術(shù)有向往,每個(gè)需求要設(shè)置一個(gè)CR上限人數(shù)双谆,超過(guò)人數(shù)后就從CR池子中剔除壳咕。
獎(jiǎng)懲機(jī)制
正向鼓勵(lì)可以加速CR氛圍的形成,最終要以實(shí)物作為獎(jiǎng)勵(lì)(京東卡佃乘?)囱井,所以需要一些預(yù)算??驹尼,根據(jù)大家的產(chǎn)出來(lái)授予獎(jiǎng)品趣避。至于懲罰理所當(dāng)然就是事故共擔(dān),線上問(wèn)題責(zé)任按比例分配新翎。
獎(jiǎng)勵(lì)考慮通過(guò)積分來(lái)兌換程帕,所以可以做一個(gè)CR積分排行榜,具體分?jǐn)?shù)可由如下幾項(xiàng)指標(biāo)轉(zhuǎn)換過(guò)來(lái):
- 主動(dòng)評(píng)估
- reviewer評(píng)估本次CR給自身帶來(lái)的收獲打分(對(duì)模塊的熟悉度地啰、代碼技能的提升等)
- CR效果打分(reviewer在CR結(jié)束后打分愁拭,評(píng)估本次review效果)
- 被動(dòng)評(píng)估
- CR前置發(fā)現(xiàn)的問(wèn)題數(shù)
- 千行代碼Bug數(shù)(可以按不同維度細(xì)分:團(tuán)隊(duì)、個(gè)人亏吝、需求等維度)
- 單個(gè)需求的Bug數(shù)
- 有效的CR評(píng)論(標(biāo)記為已解決的評(píng)論)
寫(xiě)在最后
從各種資料看岭埠,國(guó)外大廠似乎比較流行Code Review,也許這使得國(guó)內(nèi)對(duì)Code Review的態(tài)度時(shí)不時(shí)會(huì)有種難以言狀的推崇或者仰望蔚鸥,錯(cuò)誤地認(rèn)為Code Review可以解決很多問(wèn)題惜论。Code Review僅僅作為一種質(zhì)量保障的補(bǔ)充手段,它并不是銀彈止喷,不要指望Code Review可以發(fā)現(xiàn)多少關(guān)鍵問(wèn)題馆类,即使投入無(wú)限的人力也只能獲取有限的收益,它的效果不如測(cè)試那么穩(wěn)定弹谁。
這不代表就不需要Code Review乾巧,長(zhǎng)期來(lái)看一個(gè)健康的技術(shù)團(tuán)隊(duì)是需要實(shí)踐Code Review的句喜。尤其是大體量產(chǎn)品,體量越大Bug產(chǎn)生的影響也就越大沟于,而Code Review的性價(jià)比越高咳胃,為什么這么說(shuō)呢?
試想一下產(chǎn)品的日活從100W變成1000W社裆,同樣癥狀的線上事故拙绊,影響的用戶量整整相差一個(gè)量級(jí),也就代表著100W日活時(shí)一個(gè)P2級(jí)線上事故泳秀,在1000W日活時(shí)它會(huì)上升為P1級(jí)甚至P0級(jí)标沪。
產(chǎn)品代碼越復(fù)雜,Bug就隱藏得越深嗜傅,問(wèn)題場(chǎng)景就越構(gòu)造金句,線下人工或者自動(dòng)化測(cè)試,礙于工具支持以及建設(shè)程度吕嘀,總有難以覆蓋到的點(diǎn)违寞,而Code Review正是一種精細(xì)耕作的手段,以彌補(bǔ)測(cè)試的不足偶房,特別是很隱晦的Bug趁曼,比如資源競(jìng)爭(zhēng)導(dǎo)致死鎖餓死、異常處理分支出錯(cuò)棕洋、大流量下的性能問(wèn)題挡闰、技術(shù)債的有無(wú)(技術(shù)債也是一種問(wèn)題,未來(lái)需要成本解決)等……這些就是Code Review獨(dú)特的作用掰盘。
隨著產(chǎn)品體量增大摄悯,Code Review能發(fā)揮的價(jià)值會(huì)有所增長(zhǎng)。
Code Review做得不好愧捕,就說(shuō)Code Review無(wú)用奢驯,這樣的說(shuō)法就好比單元測(cè)試寫(xiě)得爛,就說(shuō)單元測(cè)試不用做一樣次绘。