不做程式碼審查又怎樣?

ThoughtWorks發表於2016-04-25

從一次回顧會議開始

“要不……我們不做……程式碼審查了……試試?”還記得當有人丟擲這個建議時周圍同學的表情,那種表情用兩個字加兩個標點符號就可以形容:“什麼?!”

對了,先介紹一下背景,這是專案一次普通的回顧會議,我們正在討論的是如何讓程式碼審查更有效率和效果。我們做程式碼審查的方式比較簡單直接,就是每日站會後,大家圍在一臺開發機周圍,逐一輪換講解昨天所有提交的內容,就像下圖中的那樣。還有,這是一個已經超過了7年的比較大型的專案,程式碼審查是我們從專案開始就堅持的一個實踐,所以當有人提議廢除它的時候,這在很多同學心裡是想都沒想過的事情。

程式碼審查是一個很好的實踐,可以幫助團隊裡的同學瞭解其他同學在做什麼,可以分享專案的上下文,可以分享技術上的一些小魔法,可以發現很多潛在的程式碼缺陷,可以提高程式碼質量,還可以有很多很多好處……

但是,在真正的實施過程中,很多情況下並不像想象的那般美好,經常出現例如有些同學由於跟不上其他人講解的速度(畢竟不是自己寫的)或是沒有相關的上下文(例如剛加入專案的新成員),或是由於提交沒有被很好的切分和組織,導致整個過程都處於遊離狀態(就像下圖中的我……毫無擺拍痕跡),而程式碼審查的效果也打了折扣,漸漸的變成了一個流程,一個過場, 一個習慣。

00

於是團隊裡就有人站了出來,引導大家去發現背後的問題,也就引來了這樣一場激烈的討論。在討論中,有些同學堅持在說程式碼審查還是很有用的,有這樣那樣的好處,需要保持下去;有些同學則非常實際地指出了執行上的各種困難和問題。討論異常激烈,直到有人小心翼翼地提出了文章開頭的那個建議,一片譁然後大家都陷入沉寂:是啊,不做程式碼審查了,我們會失去或是得到什麼呢?

溝通的收益和成本

在我看來,程式碼審查所暴露出的問題本質上就是如何權衡溝通的成本和收益的問題

在軟體開發過程的發展中,無論是從一開始的瀑布,後來的敏捷,還是當下的精益。都有很大一部分篇幅是在強調溝通或者說是強調溝通方式的演進,都是為了解決已有溝通方式所帶來的各種限制和問題。

例如在我們自己的專案中就採用以下的實踐來促進團隊內外的溝通,包括:迭代計劃會(Iteration Planning Meeting),每日站會(Daily Standup),程式碼評審會(Code Review),回顧會議(Retrospective Meeting);還有XP中的結對程式設計(Pair programming),現場客戶 ( On-site Customer )等。

而溝通的好處是可以得到快速的反饋,無論是80年之前就出現的PDCA環還是前兩年大熱的精益創業,都是在強調快速反饋和基於反饋的快速迭代,通過這種方式來消除生產和創業過程中造成的各種浪費。

但是(對,又是但是……),溝通也是有成本的,而且成本一般都還不低,相信這點也不需要多解釋,大家肯定都經歷過各種各樣效率極低令人抓狂的討論或是會議。

在溝通的成本和收益同時擺在我們面前,如何做出選擇?如何才能設計一套剛剛好的溝通體系,平衡收益與成本,來滿足團隊和專案的需要呢?

溝通金字塔

在讀《重構》的時候,我深深地體會到:這個世界上沒有什麼是不變的,包括變化本身。所以要想得到解脫,我們就需要從簡單的對與錯,好與壞的漩渦中跳脫出來,用變化的眼光來看待周圍的事物,並做好一直變化的準備。

而面對溝通成本與收益的選擇困境時,我第一個想到的就是測試金字塔。瞭解測試金字塔的同學肯定都知道,測試金字塔是一個很好的工具,它幫助我們從單一的測試選擇困境中跳脫出來,將各種不同型別的測試建立起關聯、納入一個統一的體系,從而讓我們可以在一個更高的維度來系統的思考和審視每一種測試的策略,關注點也從簡單的“該不該”變為了“如何變化”。

01

至於“如何變化”?我們可以通過在金字塔上新增一層新的測試種類來彌補整體測試策略中粒度太粗的問題;也可以根據專案情況通過移除一層測試種類,用其上層或是下層的測試來覆蓋其測試用例,來減少成本;也可以通過將某個測試用例在金字塔中向上層或是向下層移動來尋找收益與成本的平衡。

舉個實際點兒的例子,例如我可以將一些基於UI的整合測試用例下移,用成本更低的單元測試來覆蓋從而減少成本,加快反饋速度;也可以將一個單元測試用例上移,用基於UI的測試來增加其穩定性的和體現的業務價值。

看,我們討論的內容從簡單的要不要寫UI測試,需要寫多少單元測試測試已經被轉換到對於整體策略的變化和調整上來了。那對於程式碼審查的問題能否也通過金字塔這個工具轉換到更大的空間上尋求突破呢?這就是溝通金字塔

02

相比於測試金字塔中的“UI--Service--UT,“Iteration Planning Meeting(見上圖)-- Code Review(見上上上圖)-- Pair programming(見下圖)”就可以類比成溝通金字塔,和測試金字塔一樣更靠近金字塔頂端的(例如迭代計劃會)溝通頻率越低,成本越高,但越接近業務;越靠近金字塔底端的(例如結對程式設計)溝通頻率越高,成本越低,越接近實現。這幾種不同的溝通方式所溝通的內容肯定也會有所重疊,通過將各個層次的溝通方式進行組合來保證我們團隊的整體溝通質量,就像通過金字塔中的各種測試層次的組合來保證產品質量的一樣。

03

如果可以這麼類比的話,那我們對於溝通質量的管理也應該是動態的、系統的、從整體上出發的。例如就可以通過在溝通金字塔中新增一層新的溝通機制來彌補溝通粒度過粗的問題,例如QA Team現在在做的每週例會就是一個好的例子;也可以將一些溝通內容通過層次(上下)的調整,甚至是通過直接減少一層溝通方式來優化我們的整體溝通效率,例如我們可以通過增加結對程式設計的Switch頻度來替換掉成本更高的程式碼審查。而目標就是通過不斷地動態調整和優化溝通結構,試圖尋求一個溝通成本,溝通收益,溝通效率平衡的溝通環境。

回到問題上來

如果溝通金字塔的理論說的通,那程式碼評審就不再是一個:“必須要做的敏捷實踐”,而只是溝通金字塔上的一層而已。那它的存在必然是為了彌補上下層溝通之間的空隙,那這個空隙到底是什麼呢?是什麼樣的溝通是結對程式設計所不能覆蓋,而用類似於迭代計劃會這種更高層的溝通機制覆蓋又不太經濟的呢?為了讓團隊重新找回這個答案,我們最終決定試一試:停止程式碼審查一個月,在這一個月的時間我們去體會沒有程式碼審查的得與失,在一個月之後重新舉行回顧會議再來討論是否要繼續做程式碼審查

在一個月後如期進行的回顧會議上,團隊又重新討論了這個議題,最終覺得通過這一個月的嘗試,在還無法做到更頻繁地Switch Pair的情況下,程式碼審查還是很有必要的。例如在這個月中,大家對於其他人在做的工作了解變少,整合出現了很多衝突;缺陷的數量也有所增加,其中有些是很明顯的錯誤,很容易通過程式碼審查的方式發現並在前期消除;程式碼質量也有明顯下降,出現了測試的缺失和很多程式碼壞味道。

而另一方面為了讓程式碼審查能夠真正的發揮其作用和價值,經過討論我們也優化了程式碼審查的方式,讓大家更有參與感,更有效率,也更有樂趣(見下圖抓拍)。

04

交付價值 Over 遵循實踐

日本劍道有個心訣,叫守 破 離:
1.“守”:最初階段須遵從老師教誨,認真練習基礎,達到熟練的境界。
2.“破”:基礎熟練後,試著突破原有規範讓自己得到更高層次的進化。
3.“離”:在更高層次得到新的認識並總結,自創新招數另闢出新境界。

守固然重要,但如果不能在守得基礎上尋求突破,領會其中的奧祕和背後的道理,則始終無法達到離的新境界。在中國的武術中也有“無招勝有招”的說法,這裡的無招就是指在將招數融會貫通之後,能夠運用招式背後的原理,打破招數的限制,隨機應變,自由應對。

而反觀我們自己,是不是已經慢慢的不知不覺的被困在“守”的圍城之內,變成了猴子定律中最後的那群猴子,只知道去拿香蕉會被打,也會跟著其他猴子去打那些試圖拿香蕉的新猴子,但是為什麼要這麼做?我們已經忘了,或從來都沒有知道過。

所以,不要以為遵循了敏捷提倡的一些實踐我們就是敏捷的,不要以為遵循了精益的實踐我們就是精益的。在我們沒有理解並追求其背後真正價值的時候,只不過是平添了另外一份成本而已,不如不做。

相關文章