新聞中心
怎么做 code review?本文分享了 Shopify 非常實用的 6 個 code review 實踐技巧。

創(chuàng)新互聯(lián)公司成立以來不斷整合自身及行業(yè)資源、不斷突破觀念以使企業(yè)策略得到完善和成熟,建立了一套“以技術為基點,以客戶需求中心、市場為導向”的快速反應體系。對公司的主營項目,如中高端企業(yè)網(wǎng)站企劃 / 設計、行業(yè) / 企業(yè)門戶設計推廣、行業(yè)門戶平臺運營、成都app軟件開發(fā)、移動網(wǎng)站建設、微信網(wǎng)站制作、軟件開發(fā)、成都棕樹電信機房等實行標準化操作,讓客戶可以直觀的預知到從創(chuàng)新互聯(lián)公司可以獲得的服務效果。
Code reviews 是打造高效團隊的重要方面,這已經(jīng)成為共識。關于這個主題,有許多文章曾經(jīng)討論過,比如這篇論文——《An Empirical Study of the Impact of Modern Code Review Practices on Software Quality》?,F(xiàn)實中,許多企業(yè)的無數(shù)團隊都進行過某種形式的 code reviews。
https://sail.cs.queensu.ca/Downloads/EMSE_AnEmpiricalStudyOfTheImpactOfModernCodeReviewPracticesOnSoftwareQuality.pdf
而實際情況是,code reviews 剛開始時,人們的激情高漲,之后,code reviews 則流于形式,或者要么反饋不清晰、要么讓人難以執(zhí)行。長久以往,這讓團隊錯失了加快學習、分享知識的機會,最終難以提高代碼的質(zhì)量。
在 Shopify,我們不僅立足長遠,而且希望追求發(fā)展更快。以我們的經(jīng)驗來看,優(yōu)秀的 code reviews 實踐對工程師的成長和我們所打造的產(chǎn)品質(zhì)量有著巨大影響。
1. 噩夢般的編碼經(jīng)歷
這樣一個場景相信很多人都很熟悉:
你剛剛加入一個新團隊,領導很快給你分配了一個編碼任務。作為新人,你特別想表現(xiàn)自己,因為你想秀一下自己的編碼水平。于是,你接下來做了這些事:
- 你為了完成任務瘋狂地敲了三周代碼;
- 你將一個包含大約 1000 行新代碼的 Pull Request 提交評審;
- 你收到兩條關于 code style 的評論,以及一個關于評審人表示他看不懂這些代碼用途的問題;
- 你修復 code style 并回答評審人的問題,然后評審人通過你寫的代碼;
- 你把代碼分支合并到 Master,雙眼緊閉,緊握著拳頭,緊咬牙關等待著結果。幾分鐘后,CI 完成。幸好,Master 沒有崩潰。然而......
- 此后 6 個月,你一直戰(zhàn)戰(zhàn)兢兢,不知道代碼何時會崩潰,以及以什么方式崩潰。
你可能經(jīng)歷過上述噩夢般的經(jīng)歷,那我們談談怎樣改進這個流程吧!
2. 實用的 Code Review 實踐
在 Shopify,我們看重交付速度、學習以及長期發(fā)展。這些價值觀雖然有時會產(chǎn)生沖突,但卻引導我們不斷嘗試許多新技術,并推動團隊變革。
我在本文總結了一系列 Shopify 內(nèi)部使用的實用技巧。借助這些技巧,我們能交付經(jīng)得起時間考驗的有價值的代碼。
術語說明:我們將 Pull Requests(PR)定義為合并到基礎分支前進行 code reviews 的一個工作單元。Github 和 Bitbucket 的用戶對這個術語很熟悉。
將 Pull Request 拆分為較小的代碼段
這個方法很簡單,可以成為提高 code reviews 工作流程最有用的技術。它之所以有效,主要有兩個原因:
- 評審人心理上更容易接受開始和完成一小塊代碼的評審工作。更大的 PR 自然會讓評審人推遲和拖延評審,并且在評審過程中被打斷的可能性更大。
- 作為一名評審人,如果 PR 太長,就很難深入進去。要檢查的代碼越多,我們越需要耗費更多腦力來理解整個代碼塊。
將 PR 拆分為更小的代碼段,讓你有更多機會在更短時間內(nèi)得到更深入的評審。
目前,我們無法設置一個適用于所有編程語言和所有類型工作的通用標準。對于內(nèi)部的數(shù)據(jù)工程項目,我們原則上是要將 PR 控制在 200-300 行代碼。如果超過這個閾值,我們一般會將它拆分成更小的塊。
當然,我們也要注意不要將 PR 拆分得過小,因為這意味著評審人可能需要檢查好幾個 PR 才能理解整體邏輯。
使用 Draft PRs
你聽過造一輛汽車與畫一輛汽車的比喻嗎?這個比喻是這么說的:
- 用戶要你造一輛車;
- 6 個月后,你造了一輛漂亮的保時捷;
- 你向用戶展示這輛車后,他們問你這輛車能不能放得下他們的 5 個孩子和沖浪板。
顯然,這里的問題在于目標不清晰,團隊沒有收集到足夠的反饋就直接構建解決方案。如果在第一步后,我們先畫一幅汽車的草圖,并將其展示給用戶,他們會問相同的問題,這樣就可以進一步了解客戶需求。如此,就為我們節(jié)省了 6 個月的工作量。軟件也不例外,我們可能會犯同樣的錯誤,在用戶不需要的特性或模塊上投入大量工作。
在 Shopify,一般用 Work In Progress (WIP) PRs 來獲得早期反饋,其目標是驗證方向(算法、設計、API 等等選擇)。盡早變更可以避免在細節(jié)、修飾、文檔等方面浪費精力。
作為一名寫代碼的人,這意味著你要對變更工作方向持開放態(tài)度。
在 Shopify,我們信奉的原則是允許大家有自己的理解,但不固執(zhí)己見。我們希望大家能在有充足理由的情況下自信地做出決定,但同時也能樂于學習其他更好的新方案。在實際工作中,我們使用 Github 的 Draft PRs,它們明確表明這項工作仍在流程中流轉(zhuǎn),Github 不允許你合并一個 Draft PR。其他工具可能有類似的功能,至少你創(chuàng)建正常 PR 時可以加上一個 WIP 標簽,以明確表示該工作還處于前期階段。這將幫助你的評審人專注于適當?shù)念I域,提出適當?shù)姆答仭?/p>
https://engineering.shopify.com/blogs/engineering/scaling-mobile-development-by-treating-apps-as-services
One PR Per Concern
除了行數(shù)外,需要考慮的另一個維度是你的工作單元試圖解決的問題數(shù)量。一個關注點可以是一個特性、一個錯誤修復、一個依賴項升級、一個 API 變更等等。你是否在重構的同時引入一個新特性?一次修復了兩個錯誤?同時引入了類庫升級和新的服務?
把 PR 分解為一個個單獨的關注點,它會產(chǎn)生下列影響:
- 更獨立的評審單元,這意味著更好的審查質(zhì)量;
- 受影響的人更少,因此可以聚集在更少的幾個專業(yè)領域中;
- 原子性回滾,可以回滾小的 commit 或 PR。這是很有價值的,因為如果出了問題,就更容易確定錯誤是在哪里引入的,以及回滾哪些部分。
- 將易事和難事分開。假設有一個新特性,需要重構一個頻繁使用的 API。你可以更改這個 API,升級十幾個調(diào)用的站點,然后實現(xiàn)這個特性。你的變更中有 80% 不是功能上的變更,明顯可以忽略掉,而 20% 是需要仔細注意測試覆蓋率、預期行為、錯誤處理等等的新代碼,并且可能要經(jīng)過多次修訂。對于每一個修訂,評審人都需要瀏覽所有的修改以找到相關的部分。通過將其分成兩個 PR,很容易就可以快速完成大部分工作,并優(yōu)化評審工作,將主要精力投入到難點上。
如果你最終拿到手的 PR 包含多個關注點,那么你可以將其分解為多個單獨的塊。這樣能針對每一塊進行單獨的評審,每次評審的迭代周期可以更快,從而加速這個 PR 的總體評審周期。通常情況下,有一部分工作能先快速完成,避免代碼爛到不能用以及引起合并沖突。
將 PR 分解成單獨的關注點
上例的 PR 包含三個不同的關注點,我們將其進行拆分??梢钥吹?,每個評審人需要檢查的上下文少了許多。最重要的是,只要其中任何一個部分的評審完成,代碼作者就能一邊等待其他評審反饋,一邊著手處理已經(jīng)反饋的問題。在最極端的情況下,代碼作者會陸續(xù)收到各個部分的評審反饋,幾乎可以不間斷地處理完這一系列 PR,而不是完成初稿后,等上幾天(已經(jīng)去忙其他的事),然后最后再返回頭來處理反饋意見。
專注代碼,而不是人
專注于代碼,而不是人,這條實踐談的是人與人之間的溝通方式和關系。從根本上講,這是提倡我們嘗試把注意力集中在如何改進產(chǎn)品上,避免作者將評審意見當作對他個人的批評。
以下是一些你可以遵循的技巧:
- 評審人可以這樣想:“這是我們自己的代碼,我們該如何改進它呢?”
- 提出肯定意見!如果你看到有些代碼部分寫得不錯,就加條評論表揚一下。這能讓代碼作者繼續(xù)保持好的一面,并有助于他在心理上更容易接受改進建議。
- 代碼作者不妨這么想,評審人的出發(fā)點肯定是好的,不要將評論當作是對個人的批評。
- 下表列出了一些存在不足的評審反饋,以及如何按以上建議進行重寫的建議。
歸根結底,code review 給我們提供了互教互學的機會,我們應該對此持開放歡迎的態(tài)度。
挑選合適的評審人
決定由誰來評審你的工作通常很有挑戰(zhàn)性。以下問題可作為參考:
- 誰具備你正在構建的特性或組件的上下文?
- 誰精通你正在使用的語言、框架或工具?
- 誰對這一主題知之甚深,有自己的理解?
- 誰關心你所寫代碼的結果?
- 誰應該學習這些東西?或者,如果你是一名正在評審“老鳥"的菜鳥程序員,不妨抓住這個機會多多提問學習。別怕你的問題太幼稚,一個強大的團隊會找時間來分享知識。
無論你的團隊遵循哪些原則,請記住,作為一名代碼的作者,你有責任尋求并接受適當?shù)娜藢δ愕拇a進行高質(zhì)量的 code review。
給評審人提供關鍵的上下文
最后但同樣非常重要的一點是,你的 PR 描述至關重要。這取決于你選擇的評審人,不同的人會有不同的上下文。代碼的作者有責任提供關鍵信息或更多上下文的鏈接,幫助評審人能夠反饋有價值的意見。
你可以把以下問題放到你的 PR 模板中:
- 為什么這個 PR 是必要的?
- 誰會從中受益?
- 可能會出什么問題?
- 你還考慮過其他方法嗎?你為什么決定采用這種方法?
- 這對其他系統(tǒng)有什么影響?
好的代碼不僅沒有錯誤,還非常有用。作為一名代碼的作者,請確保你的 PR 描述將代碼與團隊目標聯(lián)系起來,最好能與待辦事項中的特性或缺陷描述聯(lián)系起來。作為評審人,會先評審 PR 描述,如果它不夠完整,你是無法針對未定義的目標來判斷代碼是否適當?shù)?,不如在評審代碼前就把它打回去。請記住,有時代碼審查的最佳結果是認識到根本不需要這些代碼!
3. 我們會有哪些收獲?
通過采用上面的一些技術,你可以在很大程度上影響軟件構建過程的速度和質(zhì)量。但除此之外,還有潛在的文化影響:
- 團隊將達成共識。團隊會更了解你的工作,除你之外,其他團隊成員可以完善代碼庫的這一部分。
- 團隊將共同承擔責任。如果出現(xiàn)問題,不只是某個人的代碼需要修復,而是整個團隊的代碼都需要修復。
任何團隊成員都應該能夠休上幾天假,他幾天不工作不會讓公司面臨風險,也不會因為擔心世界末日而不停地去看電子郵件。
4. 個人可以如何改進團隊的代碼審查流程?
如果你是團隊主管,不妨開始嘗試這些技巧,找出適合你所帶團隊的方法。
如果你是獨立貢獻者,可以與主管討論一下為什么你認為代碼審查技術很重要,以及它如何提高效率和幫助團隊。
在下次一對一交流或團隊會議上,探討一下這個問題。
文章標題:6個實用的CodeReview實踐技巧
鏈接地址:http://fisionsoft.com.cn/article/cddgcic.html


咨詢
建站咨詢
