【轉】Code Review 程序員的寄望與哀傷

Code Review 程序員的寄望與哀傷

2017-01-20 07:25

一個程序員,他寫完了代碼,在測試環(huán)境通過了測試,然后他把它發(fā)布到了線上生產環(huán)境,但很快就發(fā)現(xiàn)在生產環(huán)境上出了問題,有潛在的 bug。

事后分析,是生產環(huán)境的一些微妙差異,使得這種 bug 場景在線下測試中很難被發(fā)現(xiàn)。畢竟想要在測試環(huán)境完美的復制生產環(huán)境的所有情況也是不太可能的,導致出現(xiàn)了疏漏。對于這類情況,我們在想是否可以通過在線下做一些 Code Review(代碼審查)假想線上的環(huán)境差異,通過在頭腦中的假想上線運行來獲得一些概念驗證,這樣是否能夠減少上線后出現(xiàn) bug 的概率呢?

感性

Code Review 是很多軟件工程理論和方法學中的重要一環(huán),而且程序員們大多都感性的認識到 Code Review 對于提升代碼質量和減少 bug 有幫助,但在我過去工作的這些年里,經歷了幾家公司,數(shù)個不同的團隊,卻幾乎沒有把 Code Review 作為必要的一環(huán)去執(zhí)行的團隊。

過去,總是在線上出現(xiàn)一些奇怪的疑難問題后,我們一群程序員才圍坐一堆,打開相關代碼來逐行分析,根據(jù)線上現(xiàn)場的尸檢來做事后分析和推導,這樣的代碼審查和分析實際上根本不是 Code Review,也完全違背了 Code Review 的初衷。Code Review 的初衷是在代碼進入生產環(huán)境前經過同行評審來減少代碼出現(xiàn) bug 的概率。這一點程序員都好理解,提前的 Code Review 就像雷達掃描我們重點關注的代碼領地,以期發(fā)現(xiàn)或明顯或隱藏的威脅因素。

想必很多人都看過一部叫《火影忍者》的漫畫,里面有一種忍術技能——白眼。根據(jù)忍者能力強弱白眼能觀察的距離不同,雖然白眼有近 360° 的觀察范圍,依然存在觀察死角。不是所有的程序員都擁有類似「白眼」的技能,我們在寫程序時力求思考的全面,不留死角或盲點,但實際死角或盲點總是存在,隨著程序員經驗或經歷的成長,思考和認識的越發(fā)全面(越發(fā)接近 360°),擁有了近乎「白眼」的能力,但像白眼一樣依然存在盲點。

我們看不到自己的后腦勺,所以假如在我們的后腦勺放上一個伙伴的眼睛,他的視角就彌補了我們自己的盲點。世上沒有兩片完全一樣的樹葉,也許也不會有兩個認知視角完全重疊的人。

像 Code Review 或結對編程這樣的實踐正是基于這樣的感性認知,試圖找出盲點區(qū)域的 bug,但到底這樣的做法能降低多少出現(xiàn) bug 的概率呢?

理性

有人對 Code Review 的作用進行了更理性且量化的分析,來自 Wikipedia(維基百科)。

卡珀斯·瓊斯(Capers Jones)分析了超過 12,000 個軟件開發(fā)項目,其中使用正式代碼審查的項目,發(fā)現(xiàn)潛在缺陷率約在 60-65% 之間,若是非正式的代碼審查,發(fā)現(xiàn)潛在缺陷率不到 50%。大部份的測試,發(fā)現(xiàn)的潛在缺陷率會在 30% 左右。

一般的代碼審查速度約是一小時 150 行程式碼,對于一些關鍵的軟體(例如安全關鍵系統(tǒng)的嵌入式軟體),一小時審查數(shù)百行程式碼的審查速度太快,可能無法找到程式中的問題。代碼審查一般可以找到及移除約 65% 的錯誤,最高可以到 85%。

也有研究針對代碼審查找到的缺陷類型進行分析。代碼審查找到的缺陷中,有 75% 是和計算機安全隱患有關。對于產品生命周期很長的軟件公司而言,代碼審查是很有效的工具。

從上面的實驗分析結果看,Code Review 對于發(fā)現(xiàn)潛在缺陷很有用(相比測試能發(fā)現(xiàn)的缺陷率高一倍),但也需要投入巨大的時間成本(一小時審查 150 行代碼,再快就不利于發(fā)現(xiàn)潛在缺陷了),而且更適用于長生命周期的產品。

所以,有個現(xiàn)象就容易理解了。我發(fā)現(xiàn)在同一家公司做 Code Review 較多的都是研發(fā)通用底層技術產品或中間件的團隊,而做業(yè)務開發(fā)的團隊則較少做 Code Review。一方面是底層技術產品或中間件的需求較穩(wěn)定,且生命周期長,而業(yè)務項目(特別是嘗試性的新業(yè)務)需求不穩(wěn)定,時間要求緊迫,而生命周期很多都偏短。

困難

通過了理性的分析我們可以看出 Code Review 是有很大好處的,但適用的場景和花費的成本也需要去平衡。除了這點,也許還有一些關于如何實施 Code Review 的困難。

如果把 Code Review 作為一個必要環(huán)節(jié)引入到研發(fā)流程中,也許會引發(fā)下面一些問題:項目 deadline 已定,時間緊迫,天天加班忙成狗了,誰還愿意搞Code Review?這是一個最常見的客觀阻礙因素,因為 deadline 很多時候都不是我們自己確定的。

即使強推下去,團隊認識不到其好處,也不夠重視,每次走個過場,Code Review 的效果如何能保障?如果你是一個父親,為自己的孩子制定一個最簡單的規(guī)則,比如說:飯前洗手。你如何保障這個規(guī)則的實施效果,你當然可以每次吃飯前檢查下孩子的手是否干凈,但你也很難每頓飯都和孩子一塊兒吃,所以你就檢查不到了。要是孩子有個智能的碗,當孩子吃飯時手一接觸到碗就能檢測細菌是否超標,然后發(fā)出提醒和拒絕措施,這樣是否就保障了這個規(guī)則與你在或不在的實施有效性。而 Code Review 顯然是個更復雜的規(guī)則,需要的智能工具支持也更復雜。

團隊人員結構搭配不合理,新人沒經驗的多,有經驗的少。天天安排經驗多的少數(shù)人幫助 review 多數(shù)新人的代碼,新人或有收獲,但對高級或資深程序員又有多大裨益?一個好的規(guī)則或制度總是需要既符合多方參與者的個體利益又能滿足組織或團隊的共同利益,這樣的規(guī)則或制度才能順暢的實施和運轉。

若你的團隊中存在一些自信超強大的程序員,覺得自己的寫的代碼絕對沒 bug,不需要別人來給我 review。這樣的人未必就很差,他寫的代碼甚至確實出 bug 的概率比普通人更低,但肯定依然存在潛在 bug。這樣團隊成員的存在,也會成為 Code Review 的一個障礙。

路徑

Code Review 確實存在很多各種各樣的困難,導致很多團隊都能認識到它的好處卻實施不下去。尤其在國內,我?guī)缀鯖]聽說過嚴格把 Code Review 作為一項研發(fā)制度或規(guī)則要求的公司。

但在大洋的另一端,無論是老牌大公司如 Google 或是新近崛起的創(chuàng)業(yè)公司如 Airbnb 都把 Code Review 作為上線進入生產環(huán)境前強制且必須的一環(huán)。在一篇介紹 Google Code Review 的實踐文章中說道,在 Google 任何產品,任何工程的代碼,在被進行嚴格或者明確的審查(Code Review)之前,是不允許提交的。你看,Google 通過工具控制在進行 Code Review 前甚至是無法提交代碼的。

Google 以一種強硬的姿態(tài)來制定關于 Code Review 的且應用于全公司范圍內的規(guī)則,對任何人都不例外。即使面對團隊中超自信且強大的程序員也無例外,要么遵守規(guī)則,要么離開組織。這一點從 C 語言和 Unix 的發(fā)明者、圖靈獎得主、最具傳奇性的程序員 Ken Thompson 在 Google 的趣事——作為 C 語言發(fā)明者之一因為沒有參加 Google 的編程語言能力測試所以無法在 Google 提交 C 代碼——從中可以一窺 Google 規(guī)則的強硬性。

所以像 Google 這樣的公司對于 Code Review 屬于高度認可且有公司制度和規(guī)則的強硬支持,再輔助自動檢測和控制工具的嚴格執(zhí)行,方能如此。這也屬于一種嚴格的同步 Code Review,所謂同步就是必須要等待 Code Review 有了結果并無異議后方能提交或上線代碼。

但要實施如此嚴格的同步 Code Review 似乎對大部分國內公司又感覺過于無奈,這需要公司制度、團隊文化和技術工具三方面的支持。而在大部分以業(yè)務目標、KPI和績效導向的公司,不說在制度和文化方面得到支持,能不被反對就不錯了。關于這一點陳皓(@左耳朵耗子)寫過一篇文章《從 Code Review 談如何做技術》其中寫到了在阿里實施 Code Review 遇到的各種文化上的阻礙和反對。而阿里已是國內頂級互聯(lián)網公司,可見實施同步 Code Review 的路徑并不簡單。

如果實施同步 Code Review 如此困難,那么是否可以退而求其次,設計一種異步的 Code Review 方式呢?就像我們提升系統(tǒng)性能一樣,把一些同步的串行調用變成異步的并行調用,按這個思路 YY 了以下場景。

程序員完成編碼,提交測試,測試通過后就去上線發(fā)布,另一方面也組織并行的 Code Review。畢竟測試通過只能證明測試覆蓋的場景無 bug,但可能代碼實現(xiàn)并不優(yōu)化和合理,而并行的 Code Review 即使發(fā)現(xiàn)了潛在問題依然來不及阻止本次上線,但可以為下次上線提供優(yōu)化點或方向。另外在制度上把 Code Review 作為工程師的日常 KPI,比如:要求每周對其他同事的代碼變動做 1~2 次 Review。

而 Review 的方式除了閱讀代碼,也可以為 Review 的代碼提供 Unit Test 間接達到了結對編程的目的。為了確保代碼確實被 Review 過需要工具支持,對 Review 過的代碼進行簽名,對不同的 Review 形式(簽名表示讀過,Unit Test 表示不僅讀過還白盒測試過)進行分類統(tǒng)計,發(fā)布 Code Review 統(tǒng)計排行榜和覆蓋分析。

以類似這樣的方式,逐步培養(yǎng)起交叉 Code Review 的文化和氛圍,同時也顯性將 Code Review 納入了程序員的工作業(yè)績之中。一開始不必像同步 Code Review 一樣對所有上線進行了阻塞,帶來巨大的陣痛。當然這也依然是一個理想化的 YY 場景,實施起來依然需要克服不少困難和準備前提工具。

在另外在一篇叫《谷歌是如何做代碼審查的》文章中,一位 Google 的工程師對 Code Review 的認識是:

代碼審查的最大的功用是純社會性的。

還有一個非常重要的好處,代碼審查能傳播知識。

而防止 bug 混入,這反倒是它最不重要的一點。

第一點是這么理解的,如果你在編程,而且知道一定將會有同事檢查你的代碼,那么你編程的姿勢和態(tài)度都會完全不同。之間的微妙差異可類比于你是在為公司的內部系統(tǒng)編程,還是在給開源軟件貢獻代碼。這是一個很有趣的視角,它其實反應了公司的制度和文化。

現(xiàn)實

以前嘗試過要在團隊內部做 Code Review,聽說兄弟團隊搞得不錯,然后就一起交流經驗,最后交流的重心就落在了應該選個什么好用的 Code Review 工具來做,如今想來這完全是舍本逐末了。

這就像以為有了好的編輯器(或 IDE)就能寫出好的代碼一樣,事實就是有很多好用的 Code Review 工具我們依然做不好 Code Review。古龍小說《陸小鳳》中有一段描述,記憶尤深:

西門吹雪:此劍乃天下利器,劍鋒三尺七寸,凈重七斤十三兩。

葉孤城:好劍。

西門吹雪:的確是好劍。

葉孤城:此劍乃海外寒劍精英,吹毛斷發(fā),劍鋒三尺三,凈重六斤四兩。

西門吹雪:好劍。

葉孤城:本就是好劍。

劍是好劍,但最好先成為像西門吹雪或葉孤城這樣的好劍客,再來居高俯視、吹毛斷發(fā)的談劍是否是好劍。

即使在最差的環(huán)境下,完全沒有人關心 Code Review 這件事。一個有追求的程序員依然可以做到一件事,自己給自己 review。就像寫文章,我寫完一篇文章從來不會立刻發(fā)布,而是從頭腦中放下(unload),過上一段時間(也許是幾小時、也許是幾天)再自己重新細讀一遍,改掉其中必然會出現(xiàn)的錯別字或文句不通暢之處,甚或論據(jù)不充分或不準確的地方,因為我知道不管我寫了多少文字,總還會有這些 bug,這就是給自己的 review。

即使如此,有時發(fā)出去的文章還是依然存在 bug,但總會比不 review 少了些。程序員在估算開發(fā)任務時也最好加上自己給自己 review 的時間,給自己 review 是一種自省,自我的成長總是從自省開始。

...

我提交了一段代碼,卻沒人給我 review,稍后我自己給自己 review 了,得到了一段更好的代碼和一個更好的自己。

寫點程序世間的文字,畫點生活瞬間的畫兒。

?著作權歸作者所有,轉載或內容合作請聯(lián)系作者
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發(fā)布,文章內容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務。

推薦閱讀更多精彩內容