譯者 | 劉汪洋
審校 | 重樓
反饋就像一塊牛排 - 如果太生,沒有人喜歡;但如果過熟,難以下咽。
(ChatGPT)

通過不斷審查他人代碼,你不僅可以提升自己的技能,對你的職業(yè)發(fā)展也有很大好處。不僅可以幫助別人成長,也能為你所在的公司創(chuàng)造價值。
在本文中,我們要探討代碼審查的好處,以及一些在審查過程中應(yīng)遵循的原則,如與同事的互動等。
名詞解釋
代碼審查:對作者代碼分支的書面反饋過程。
Pull Request:GitHub 上用于展示新分支與主分支之間差異的術(shù)語,你可以在其中發(fā)表評論。
代碼審查?是否已經(jīng)過時?
如果你是一名敏捷開發(fā)者,你可能會懷疑代碼審查的必要性,可能會有這樣的觀點:
- 我們?nèi)绻恢边M(jìn)行結(jié)對編程,就沒有必要再做正式的代碼審查了。因為這樣就不會有一個“陌生人”在你已經(jīng)完成所有工作并花費了大量時間之后,才來評價你的代碼,而他對你的代碼的上下文可能一無所知。
- 代碼的正確性已通過 TDD (測試驅(qū)動開發(fā))方法進(jìn)行了驗證。
- 語法和風(fēng)格可以由 linter 自動檢查。
這些考慮無疑是有道理的。
但:
代碼審查本質(zhì)上是一種團(tuán)隊成員之間和不同團(tuán)隊之間的知識共享機(jī)制。
代碼審查的好處
一旦你不再把代碼審查視為負(fù)擔(dān)或者無聊的任務(wù),你會發(fā)現(xiàn),代碼審查能帶來很多好處。
為了支持這個觀點,我提出了一個用于在同事的 pull request 中提供反饋的框架。
W3H:即“為什么(why)、做什么(what)、何時(when)以及如何做(how)”
盡管我并非縮寫詞的狂熱愛好者,但我還是創(chuàng)建了一個 W3H 的縮寫詞,旨在概括我們在接觸新的代碼時所需要考慮的關(guān)鍵問題。
為什么(why)
代碼審查可能是由于你的組織內(nèi)部的 CI/CD 流程強(qiáng)制推動的,因此,“為什么”的問題可以簡單地回答為“因為我被指示要這樣做”。
然而,有更有價值的問題值得我們思考:“為什么代碼審查如此重要?”或者說,“為什么我應(yīng)該主動去進(jìn)行代碼審查?”
首先,代碼審查對審查者和代碼作者來說都是一個提升自我技術(shù)水平的好機(jī)會。代碼作者可以得到有效的反饋和建議,有助于其技術(shù)水平的提升。審查者則可以從中學(xué)習(xí)新的編程技巧和習(xí)語。
此外,作為開發(fā)者,你還可以:
- 更快地理解新的代碼庫。
- 有更多的機(jī)會進(jìn)行團(tuán)隊內(nèi)交流,尤其在團(tuán)隊成員分布在不同地理位置的情況下。
- 發(fā)現(xiàn)其他團(tuán)隊工作中可能存在的重復(fù)問題。
- 在代碼庫中推動最佳實踐的實行。
- 提升你在其他工程師和管理者心中的專業(yè)形象和知識儲備。
- 提高你的溝通技巧(我們將在“如何”一節(jié)中詳細(xì)討論)。
- 結(jié)識新朋友!
做什么(what)
我們?nèi)绾味x“優(yōu)秀的”代碼?
在對別人的代碼發(fā)表任何評價之前,你需要明確好代碼的基本標(biāo)準(zhǔn)。
以下是一些通用的原則:
- 代碼中不應(yīng)存在 明顯的 錯誤,例如變量名的拼寫錯誤,或者不規(guī)范的代碼縮進(jìn)。當(dāng)我審查一個我并不太熟悉的模塊的 PR 時,我通常會從這些基礎(chǔ)的檢查開始。
- 無論代碼完成的任務(wù)有多復(fù)雜,代碼本身都應(yīng)該是 結(jié)構(gòu)清晰 和 易于理解。
- 代碼中不應(yīng)存在嚴(yán)重的 性能問題,例如,一個可以通過一次循環(huán)讀取完成的列表被多次讀取。這在移動應(yīng)用開發(fā)中尤其重要,因為這可能導(dǎo)致不必要的電池電量消耗。
- PR 只應(yīng)該修改完成任務(wù)(新特性,錯誤修復(fù),重構(gòu))所必需的 文件。這不僅可以減輕審查者的工作壓力,而且如果出現(xiàn)了重大的生產(chǎn)問題,也會更容易找到問題并進(jìn)行回滾。如果代碼涉及多個方面,建議作者將其拆分為兩個或更多的審查。
- 清晰理解更改的目標(biāo)。PR 的描述應(yīng)該清晰地說明更改的內(nèi)容或者鏈接到包含詳細(xì)信息的外部文檔(例如 Jira 或 Trello 工單)。理解了更改的目標(biāo)后,再檢查更改是否滿足了預(yù)設(shè)的要求。
- 如果 PR 是用來修復(fù)一個錯誤,修復(fù)方案還應(yīng)該包含一組測試,這樣可以針對特定的場景進(jìn)行測試,并避免相同的錯誤在未來再次發(fā)生。
何時(when)
你應(yīng)該在什么時候進(jìn)行代碼審查?
我通常每周安排兩次,每次約 30 分鐘的時間,審查其他團(tuán)隊的 PR,這些與我自己團(tuán)隊的工作并無直接關(guān)聯(lián)。如果我團(tuán)隊有緊迫的項目截止日期,可能我會減少審查的時間;如果是工作相對清閑,并且有一些評論引發(fā)了大量的討論,我可能會投入更多的時間。
在我剛開始接觸 iOS 開發(fā)時,我花在代碼審查上的時間和學(xué)習(xí) Swift 和 iOS 的時間幾乎一樣多。這使我能夠快速地熟悉新的代碼庫,語言習(xí)語,最佳實踐,以及了解項目中的關(guān)鍵人物。
我通常在面對學(xué)習(xí)新的大型代碼庫時,會立即開始進(jìn)行代碼審查(這是作者有效學(xué)習(xí)和了解新代碼庫的一種方法)
如何(how)
編寫大量的評論可能會讓你感到枯燥乏味,因此你可能在表述上變得過于直白。書面交流與口頭交流有所不同,我建議你遵循以下建議:
友善待人
這一點無需多說。通常情況下,當(dāng)我向我不太熟悉的人寫評論時,我會首先用一個簡單的 "你好 " 打招呼。如果你發(fā)現(xiàn)有什么項目缺失,不要直接用 "這是不完整的" 來表示,你可以詢問 "這里為什么會缺失?"
注意細(xì)節(jié)
嘗試在關(guān)鍵的和不那么關(guān)鍵的修改之間找到平衡,這需要你的經(jīng)驗來指導(dǎo)。我們不希望因為一個小的空格問題而阻塞了一個重要功能的實現(xiàn)或者 bug 的解決!
詢問作者的意見
如果你提出的改動不顯著,或者你提出了重構(gòu)的建議,那么最好在你的評論結(jié)尾處詢問一下 "你怎么看?" 或者 "你對此有什么看法?"
有時需要權(quán)衡
有些項目比其他項目更為重要。盡量不要因為小的修改而堅持不懈,以免造成發(fā)布延遲。你可以與作者達(dá)成共識,以后再創(chuàng)建一個"打磨"分支。然而,我常說:
以后 == 永不(later == never)
不要做假設(shè)
你正在審查一個 PR 并發(fā)現(xiàn)了一個明顯的錯誤,而這段代碼的開發(fā)者的職稱是"初級"。你可能會假設(shè)這個錯誤是由于他們的經(jīng)驗不足,或?qū)σ恍┗靖拍畹睦斫獠粔蛏钊搿R部赡苁撬麄兇颐ν瓿傻模蛘咴诙冗^了一天的勞累后提交的。或者……可能有一些我們未能看到的、合理的原因在背后。如果有疑問,告訴作者: "可能是我漏掉了什么,但是……"
保持個人偏好的開放性
當(dāng)你在代碼審查中建議更改時,確保這些更改是對代碼的實實在在的改進(jìn),而非審查者的個人偏好,這些偏好可能并不符合公司或行業(yè)的最佳實踐。當(dāng)我提出這樣的更改時,我會說: "這是個人偏好的問題,但如果你愿意,可以試試<代碼更改>"
贊美作者
“看起來很好(LGTM)” 可能會被解讀為“我草率地審查了你的 PR”。對我來說,看到這個還好,但是,如果你真的認(rèn)為代碼寫得很好,那就在 PR 中大膽地表揚。以下是值得贊揚的原因:引入了新的炫酷功能,或者進(jìn)行了復(fù)雜但結(jié)構(gòu)良好的重構(gòu)。
如果 pull request 只包含一個簡單的顏色更改或函數(shù)參數(shù)的添加,那么過度的贊美可能會被誤認(rèn)為是諷刺 。請選擇適當(dāng)?shù)恼Z言表達(dá)。
副作用
盡管你持有善意,或者在代碼審查過程中為項目貢獻(xiàn)良多,有時你的行動可能仍會引發(fā)他人的反感。他們可能按照你的建議進(jìn)行修改,但可能并未對你的審查表示感激。
有些人可能會駁斥你的建議
你的建議可能錯誤,無效,或者觸碰到了作者的自尊心,使他們認(rèn)為修改代碼就等于否定自己。這沒有關(guān)系。然而,如果你認(rèn)為某段代碼可能會導(dǎo)致嚴(yán)重的問題或性能影響,你應(yīng)該考慮邀請其他開發(fā)者一起討論,例如在評論中@他們,引導(dǎo)他們參與討論。更好的做法是,嘗試直接通過電話或面對面的方式進(jìn)行討論。
不要期待你的付出一定會得到回報
你或許為許多代碼審查和批準(zhǔn)做出了貢獻(xiàn),幫助審查了他人的代碼,但當(dāng)你自己的代碼需要審查的時候,不要期待你的新 pull request 一定會受到關(guān)注。
你可能會收獲友情
去年,我為了更好地熟悉某個代碼庫,我對一個新接手的代碼庫進(jìn)行了持續(xù)的代碼審查。我與許多開發(fā)者進(jìn)行了積極的討論,最終,對倉庫中的一些模塊進(jìn)行了改進(jìn)。這是作者和我——這位新來的代碼審查者的共同努力的結(jié)果!我結(jié)識了一些愿意改進(jìn)他們代碼、并始終對新建議和學(xué)習(xí)保持開放態(tài)度的優(yōu)秀人才。季度結(jié)束時,我向他們請求正式反饋,收到了非常積極的回應(yīng)。我們可以稱這種關(guān)系為"聯(lián)系",甚至我愿意稱它為"友誼"。
結(jié)語
在這篇文章中,我們探討了持續(xù)進(jìn)行代碼審查的諸多優(yōu)點。 我推廣的 W3H 方法,就是一種給他人的代碼提供反饋的流程。
在我所工作的 Expedia Group?,我經(jīng)常應(yīng)用這種方法,公司也倡導(dǎo)并正式提出了"有意識的包容"這一價值觀。
本文要點總結(jié)如下:
- 認(rèn)識到審查他人代碼的好處(比如建立聯(lián)系,熟悉新的代碼庫,學(xué)習(xí)新的編碼風(fēng)格等)。
- 建立持續(xù)審查的習(xí)慣。
- 提供超越你團(tuán)隊范圍的反饋。
- 避免過度假設(shè)。
- 不要期待每個人都會同等地關(guān)注你的 pull request。
- 保持友善。
你公司的代碼審查流程是怎樣的?你在工作中是否真正感受到代碼審提高了代碼質(zhì)量?歡迎發(fā)表你的看法。
譯者介紹
劉汪洋,51CTO社區(qū)編輯,昵稱:明明如月,一個擁有 5 年開發(fā)經(jīng)驗的某大廠高級 Java 工程師,擁有多個主流技術(shù)博客平臺博客專家稱號。
原文標(biāo)題:The Importance of Being a Code Reviewer,作者:Carlo Sales























