Code Review落地方案

之前的博文也寫(xiě)過(guò)兩篇關(guān)于Code Review的文章陌选,出發(fā)點(diǎn)的各不相同:

似乎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

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)題!
do CR right

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)提出了一些基本要求:

  1. 不同的聚合方式來(lái)查看diff:
    • 改動(dòng)涉及的不同倉(cāng)庫(kù)(改動(dòng)涉及多倉(cāng)者疤,分開(kāi)看)

    • 改動(dòng)的文件類型(如統(tǒng)一查看.java后綴的文件改動(dòng))

    • 被修改文件的組成的目錄樹(shù)

  2. diff代碼顏色高亮展示,支持查看diff代碼以外的其他代碼
  3. 支持任意代碼添加CR評(píng)論 以及 展示評(píng)論的解決情況
  4. 展示source分支的歷史commit message
  5. 展示source分支以及要合并到的target分支
  6. 綁定文檔模板叠赦,讓RD按模板填寫(xiě)相關(guān)內(nèi)容
  7. 查看所有需要待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è)想法:

流程總覽

  1. RD完成代碼開(kāi)發(fā)篮条,提交代碼發(fā)起Merge Request
  2. 根據(jù)RD改動(dòng)的文件,結(jié)合 該文件與其他文件的 關(guān)聯(lián)關(guān)系吩抓,獲取被修改文件相關(guān)的其他文件涉茧,層級(jí)上下共x層(可配置)
  3. 遍歷這些關(guān)聯(lián)文件,逐一找出這些文件模塊的RD(如果是子repo疹娶,獲取repo owner伴栓;如果是子文件,根據(jù)git blame等git命令獲取文件的最新(or最頻繁)改動(dòng)RD雨饺,否則兜底到根據(jù)配置獲取文件負(fù)責(zé)人)
  4. pick這些RD進(jìn)來(lái)CR代碼钳垮,或者推薦給發(fā)起CR的RD讓ta自己選擇拉誰(shuí)

一個(gè)具體例子

  1. RD小陳修改了代碼文件A.java,提交后發(fā)起Merge Request
  2. 分析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)系
  3. 獲取 [ A.java, B.java, C.java, D.java, E.java, F.java, G.java ] 這些代碼文件的CR候選人(這里可以根據(jù)git代碼行修改人獲取對(duì)應(yīng)RD舵稠,也可以配置RD)
  4. 這些候選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)題

  1. 關(guān)聯(lián)關(guān)系的分析性能嚎朽,能否做到實(shí)時(shí)分析?使用線下分析的關(guān)聯(lián)結(jié)果準(zhǔn)確率多高柬帕?
  2. 大范圍的改動(dòng)哟忍,比如代碼沉庫(kù)、代碼遷移陷寝,是否也適用锅很?
  3. 打通代碼庫(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)落地形式,比如:

  1. 做一份人員配對(duì)名單坎藐,幾個(gè)相關(guān)RD為一組为牍,互相review對(duì)方的代碼
  2. 篩選部分需求放到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è)試不用做一樣次绘。


參考資料

從 CODE REVIEW 談如何做技術(shù)

Code Review方案

Google Engineering Practices Documentation

Code Review Guidelines for Humans

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末瘪阁,一起剝皮案震驚了整個(gè)濱河市,隨后出現(xiàn)的幾起案子邮偎,更是在濱河造成了極大的恐慌管跺,老刑警劉巖,帶你破解...
    沈念sama閱讀 218,204評(píng)論 6 506
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件钢猛,死亡現(xiàn)場(chǎng)離奇詭異伙菜,居然都是意外死亡,警方通過(guò)查閱死者的電腦和手機(jī)命迈,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,091評(píng)論 3 395
  • 文/潘曉璐 我一進(jìn)店門(mén)贩绕,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái)火的,“玉大人,你說(shuō)我怎么就攤上這事淑倾×蠛祝” “怎么了?”我有些...
    開(kāi)封第一講書(shū)人閱讀 164,548評(píng)論 0 354
  • 文/不壞的土叔 我叫張陵娇哆,是天一觀的道長(zhǎng)湃累。 經(jīng)常有香客問(wèn)我,道長(zhǎng)碍讨,這世上最難降的妖魔是什么治力? 我笑而不...
    開(kāi)封第一講書(shū)人閱讀 58,657評(píng)論 1 293
  • 正文 為了忘掉前任,我火速辦了婚禮勃黍,結(jié)果婚禮上宵统,老公的妹妹穿的比我還像新娘。我一直安慰自己覆获,他們只是感情好马澈,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,689評(píng)論 6 392
  • 文/花漫 我一把揭開(kāi)白布。 她就那樣靜靜地躺著弄息,像睡著了一般痊班。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上摹量,一...
    開(kāi)封第一講書(shū)人閱讀 51,554評(píng)論 1 305
  • 那天涤伐,我揣著相機(jī)與錄音,去河邊找鬼荆永。 笑死废亭,一個(gè)胖子當(dāng)著我的面吹牛国章,可吹牛的內(nèi)容都是我干的具钥。 我是一名探鬼主播,決...
    沈念sama閱讀 40,302評(píng)論 3 418
  • 文/蒼蘭香墨 我猛地睜開(kāi)眼液兽,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼骂删!你這毒婦竟也來(lái)了?” 一聲冷哼從身側(cè)響起四啰,我...
    開(kāi)封第一講書(shū)人閱讀 39,216評(píng)論 0 276
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤宁玫,失蹤者是張志新(化名)和其女友劉穎,沒(méi)想到半個(gè)月后柑晒,有當(dāng)?shù)厝嗽跇?shù)林里發(fā)現(xiàn)了一具尸體欧瘪,經(jīng)...
    沈念sama閱讀 45,661評(píng)論 1 314
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,851評(píng)論 3 336
  • 正文 我和宋清朗相戀三年匙赞,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了佛掖。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片妖碉。...
    茶點(diǎn)故事閱讀 39,977評(píng)論 1 348
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡,死狀恐怖芥被,靈堂內(nèi)的尸體忽然破棺而出欧宜,到底是詐尸還是另有隱情,我是刑警寧澤拴魄,帶...
    沈念sama閱讀 35,697評(píng)論 5 347
  • 正文 年R本政府宣布冗茸,位于F島的核電站,受9級(jí)特大地震影響匹中,放射性物質(zhì)發(fā)生泄漏夏漱。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,306評(píng)論 3 330
  • 文/蒙蒙 一顶捷、第九天 我趴在偏房一處隱蔽的房頂上張望麻蹋。 院中可真熱鬧,春花似錦焊切、人聲如沸扮授。這莊子的主人今日做“春日...
    開(kāi)封第一講書(shū)人閱讀 31,898評(píng)論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)。三九已至埃碱,卻和暖如春嚎尤,著一層夾襖步出監(jiān)牢的瞬間荔仁,已是汗流浹背。 一陣腳步聲響...
    開(kāi)封第一講書(shū)人閱讀 33,019評(píng)論 1 270
  • 我被黑心中介騙來(lái)泰國(guó)打工芽死, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留乏梁,地道東北人。 一個(gè)月前我還...
    沈念sama閱讀 48,138評(píng)論 3 370
  • 正文 我出身青樓关贵,卻偏偏與公主長(zhǎng)得像遇骑,于是被迫代替她去往敵國(guó)和親。 傳聞我的和親對(duì)象是個(gè)殘疾皇子揖曾,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,927評(píng)論 2 355