審工程化:用open-code-review構(gòu)建高效自動(dòng)化評(píng)審體系)
代碼評(píng)審這事兒做了這么多年我見(jiàn)過(guò)太多團(tuán)隊(duì)把 Review 做成“走過(guò)場(chǎng)”。打開(kāi) Pull Request 頁(yè)面掃一眼標(biāo)題鼠標(biāo)滾輪滑到最底部點(diǎn)一下 Approve完事。你以為你在做質(zhì)量保障實(shí)際上你只是在給流水線蓋章。真正的問(wèn)題——邏輯缺陷、邊界遺漏、可維護(hù)性隱患——全都被“看起來(lái)能跑”這個(gè)標(biāo)準(zhǔn)放過(guò)去了。所以當(dāng)我看到 open-code-review 這類項(xiàng)目時(shí)第一反應(yīng)是終于有人把“評(píng)審”這件事本身當(dāng)成一個(gè)工程問(wèn)題來(lái)對(duì)待了。這不是一個(gè)簡(jiǎn)單的“給代碼挑毛病”的工具它是一整套把代碼評(píng)審流程化、自動(dòng)化、數(shù)據(jù)化的開(kāi)放方案。它能幫你解決三件事第一把評(píng)審從“憑感覺(jué)”變成“按規(guī)則”第二把評(píng)審質(zhì)量從“依賴某個(gè)人厲害”變成“依賴系統(tǒng)兜底”第三把評(píng)審產(chǎn)生的知識(shí)從“散落在評(píng)論里”變成“沉淀到流程里”。適合誰(shuí)用適合那些 PR 數(shù)量多、團(tuán)隊(duì)規(guī)模在 5 到 50 人之間、覺(jué)得評(píng)審很重但不敢砍掉的團(tuán)隊(duì)也適合想推動(dòng)工程效能改進(jìn)的技術(shù) Leader 和一線程序員。1. 內(nèi)容整體設(shè)計(jì)與思路拆解1.1 傳統(tǒng)評(píng)審為什么越做越敷衍我踩過(guò)不少坑也幫別人填過(guò)不少坑。傳統(tǒng)評(píng)審流于形式原因繞不開(kāi)這幾個(gè)首先評(píng)審時(shí)機(jī)太晚。很多團(tuán)隊(duì)是等代碼全部寫完、測(cè)試跑完、才發(fā)起評(píng)審。這時(shí)候修改成本已經(jīng)很高評(píng)審人就算發(fā)現(xiàn)設(shè)計(jì)層面的問(wèn)題也沒(méi)人愿意推翻重來(lái)。最后評(píng)審?fù)嘶伞疤岢鲂?wèn)題、修修補(bǔ)補(bǔ)”的雞毛蒜皮環(huán)節(jié)大問(wèn)題帶病上線。其次評(píng)審帶寬被浪費(fèi)。每個(gè)人都在看每一行代碼沒(méi)有分層、沒(méi)有重點(diǎn)。結(jié)果就是審計(jì)邏輯沒(méi)人細(xì)看變量命名被反復(fù)討論。真正值得花時(shí)間的核心路徑審查反而被淹沒(méi)在格式和風(fēng)格的噪音里。最關(guān)鍵的是評(píng)審沒(méi)有閉環(huán)。評(píng)論提了改不改看心情Review 通過(guò)后討論里的要點(diǎn)沒(méi)人歸納成知識(shí)庫(kù)同樣的錯(cuò)誤下個(gè)迭代繼續(xù)犯。評(píng)審變成了一次性消耗品而不是團(tuán)隊(duì)能力的增量。1.2 open-code-review 的核心設(shè)計(jì)目標(biāo)基于上面這些痛點(diǎn)open-code-review 在設(shè)計(jì)上定了幾條硬性原則一切規(guī)則前置。能自動(dòng)化檢查的東西比如格式、靜態(tài)檢查、基礎(chǔ)單測(cè)覆蓋盡量在提交階段就攔下來(lái)不要浪費(fèi)評(píng)審人的注意力。評(píng)審要有層級(jí)。按改動(dòng)風(fēng)險(xiǎn)分路徑小改動(dòng)走輕量通道核心改動(dòng)走多人會(huì)審。讓評(píng)審人的時(shí)間花在刀刃上。過(guò)程必須透明可查。誰(shuí)提的評(píng)論、誰(shuí)解決的、阻塞了多久、合入后有沒(méi)有引發(fā)線上問(wèn)題全部沉淀成數(shù)據(jù)。沒(méi)有數(shù)據(jù)就沒(méi)有改進(jìn)。反饋必須閉環(huán)。每個(gè)評(píng)審意見(jiàn)要么被解決、要么被顯式拒絕不能懸空。高頻問(wèn)題反哺到檢查單和自動(dòng)化規(guī)則里讓團(tuán)隊(duì)越評(píng)越輕松。1.3 整體架構(gòu)上分為幾層從落地角度我把 open-code-review 的架構(gòu)拆成四層平時(shí)跟團(tuán)隊(duì)講也是這么講的入口層對(duì)接 Git 平臺(tái)的 Webhook 和 API捕捉 MR/PR 的創(chuàng)建、更新、評(píng)論、合入事件。這層是“感知系統(tǒng)”保證不管代碼從哪兒來(lái)都能進(jìn)入評(píng)審軌道。規(guī)則層這里是最花心思的地方。包括文件路徑匹配規(guī)則、評(píng)審人自動(dòng)分配策略、檢查單模板、風(fēng)險(xiǎn)分級(jí)標(biāo)準(zhǔn)。規(guī)則可以寫在配置文件里也可以做成在線可視化配置。執(zhí)行層跑自動(dòng)化檢查、收集元數(shù)據(jù)、觸發(fā)機(jī)器人評(píng)論、跟蹤評(píng)論解決狀態(tài)。這層是“手腳”負(fù)責(zé)把規(guī)則變成具體動(dòng)作。沉淀層評(píng)審記錄、耗時(shí)統(tǒng)計(jì)、缺陷類型分類、知識(shí)庫(kù)索引。這層是“大腦”讓每次評(píng)審都在為下一次評(píng)審積累經(jīng)驗(yàn)。注意這套分層不是一次建成的。我建議先跑通入口層和執(zhí)行層有了一定數(shù)據(jù)量之后再建設(shè)規(guī)則層和沉淀層。一上來(lái)想做得大而全大概率項(xiàng)目會(huì)爛尾。2. 核心細(xì)節(jié)解析與實(shí)操要點(diǎn)2.1 按風(fēng)險(xiǎn)分級(jí)而不是事無(wú)巨細(xì)一把抓這是整個(gè)方案里我最想強(qiáng)調(diào)的一個(gè)點(diǎn)。很多團(tuán)隊(duì)推行代碼評(píng)審失敗的原因就是不分場(chǎng)景、一律全套流程。改一個(gè)文案要走和核心支付鏈路一模一樣的評(píng)審流程時(shí)間長(zhǎng)了誰(shuí)都會(huì)煩。open-code-review 的做法是把變更分成三類低風(fēng)險(xiǎn)變更文檔、前端樣式、文案調(diào)整、單文件小改動(dòng)。這類走輕量通道一個(gè) Reviewer 即可重點(diǎn)看邏輯對(duì)錯(cuò)不做多人討論。常規(guī)變更涉及業(yè)務(wù)邏輯、接口調(diào)整、單模塊內(nèi)的功能開(kāi)發(fā)。需要兩位 Reviewer并且要按模塊匹配熟悉度。高風(fēng)險(xiǎn)變更跨模塊重構(gòu)、數(shù)據(jù)庫(kù)變更、鑒權(quán)邏輯、支付/訂單等核心鏈路。這類必須多人會(huì)審甚至需要提前組織方案評(píng)審會(huì)議。風(fēng)險(xiǎn)分級(jí)不是拍腦袋定的我建議團(tuán)隊(duì)坐下來(lái)拉一次歷史故障清單把過(guò)去三個(gè)月出過(guò)線上問(wèn)題或接近出問(wèn)題的變更類型列出來(lái)對(duì)照著定級(jí)。這樣做出來(lái)的分級(jí)規(guī)則團(tuán)隊(duì)成員才會(huì)服氣。2.2 自動(dòng)化門禁要卡在評(píng)審之前評(píng)審人最怕的事情是打開(kāi)一個(gè) 2000 行的 PR里面還有一半代碼沒(méi)過(guò)靜態(tài)檢查。open-code-review 把自動(dòng)化門禁放在評(píng)審人介入之前目標(biāo)很簡(jiǎn)單讓評(píng)審人第一眼看到的是一個(gè)“干凈的變更”。具體來(lái)說(shuō)一個(gè) PR 要進(jìn)入人工評(píng)審環(huán)節(jié)必須先過(guò)這幾道閘靜態(tài)檢查零新增告警。這里注意是“新增”存量告警可以單獨(dú)建技術(shù)債清單不要阻塞在新代碼評(píng)審里。單元測(cè)試通過(guò)且覆蓋率不降。新代碼必須有對(duì)應(yīng)測(cè)試核心模塊的覆蓋率閾值要單獨(dú)設(shè)置。依賴安全掃描通過(guò)。引入的新依賴如果有已知高危漏洞直接打回。變更描述完整。改了什么、為什么改、測(cè)試了哪些場(chǎng)景這些信息不齊評(píng)審人沒(méi)法下手。門檻卡嚴(yán)之后評(píng)審人的效率會(huì)大幅提升。我在團(tuán)隊(duì)里跑了一段時(shí)間之后發(fā)現(xiàn)評(píng)審?fù)ㄟ^(guò)的平均時(shí)間從 28 小時(shí)降到了 11 小時(shí)主要就是因?yàn)樵u(píng)審人不用浪費(fèi)時(shí)間在低級(jí)問(wèn)題上。2.3 評(píng)論規(guī)范與機(jī)器人協(xié)作評(píng)審意見(jiàn)本身的表達(dá)方式直接影響評(píng)審質(zhì)量。我剛帶團(tuán)隊(duì)的時(shí)候經(jīng)??吹接腥嗽u(píng)論“這里寫得不OK”這種評(píng)論基本沒(méi)有價(jià)值。open-code-review 在評(píng)論環(huán)節(jié)做了兩個(gè)約束結(jié)構(gòu)化評(píng)論模板。每條評(píng)論必須包含問(wèn)題類型邏輯錯(cuò)誤、性能隱患、可維護(hù)性、安全性、嚴(yán)重程度阻塞/建議/可選、復(fù)現(xiàn)或理解上下文。這樣被評(píng)審人處理起來(lái)效率高后續(xù)統(tǒng)計(jì)缺陷類型也有數(shù)據(jù)基礎(chǔ)。機(jī)器人自動(dòng)匯總。評(píng)審機(jī)器人會(huì)把零散的評(píng)論按文件位置、嚴(yán)重程度聚合在每次代碼更新后給出總覽“目前還有 2 個(gè)阻塞問(wèn)題未解決分布在 core/auth.py 和 api/order.py其余 5 個(gè)建議項(xiàng)可以延后處理?!边@套機(jī)制跑起來(lái)之后最大的變化是評(píng)論的“對(duì)話感”消失了取而代之的是“工單感”。每一條意見(jiàn)都像一個(gè)清晰的任務(wù)處理完一個(gè)勾掉一個(gè)評(píng)審體驗(yàn)立刻清爽了很多。2.4 異步評(píng)審為主同步討論用于關(guān)鍵節(jié)點(diǎn)不少團(tuán)隊(duì)把評(píng)審做成開(kāi)會(huì)這其實(shí)是效率黑洞。代碼評(píng)審應(yīng)該以異步為主——各看各的在 PR 評(píng)論區(qū)討論。但純異步也有問(wèn)題高風(fēng)險(xiǎn)變更如果只靠評(píng)論區(qū)來(lái)回交流方案層面很容易無(wú)法收斂。open-code-review 的實(shí)踐是劃分場(chǎng)景純異步評(píng)審常規(guī)變更。每個(gè)評(píng)審人在自己時(shí)間窗口內(nèi)完成審查評(píng)論區(qū)是唯一的討論場(chǎng)所要求“問(wèn)題不過(guò)夜、評(píng)論不積壓”。同步會(huì)審高風(fēng)險(xiǎn)變更在代碼評(píng)審之前先做設(shè)計(jì)評(píng)審。重點(diǎn)看整體方案看接口設(shè)計(jì)、數(shù)據(jù)流向、異常處理策略這部分的討論產(chǎn)物會(huì)作為評(píng)審附件掛到 PR 描述里。這種做法背后的邏輯很簡(jiǎn)單代碼評(píng)審解決的是“代碼對(duì)不對(duì)”的問(wèn)題而同步會(huì)審解決的是“方向?qū)Σ粚?duì)”的問(wèn)題。方向錯(cuò)了代碼再對(duì)也沒(méi)用。把這兩個(gè)問(wèn)題混在一起評(píng)審效率一定是最低的。3. 實(shí)操過(guò)程與核心環(huán)節(jié)實(shí)現(xiàn)3.1 項(xiàng)目初始化與規(guī)則注冊(cè)落地 open-code-review 的第一步是把基礎(chǔ)設(shè)施搭好。我以最常見(jiàn)的 GitLab / GitHub 環(huán)境為例講一下核心環(huán)節(jié)怎么做。先定義倉(cāng)庫(kù)的配置文件比如.code-review.yml這是整套方案的“憲法”review: # 風(fēng)險(xiǎn)分級(jí)路徑 risk_rules: high: paths: - core/** - payment/** - db/migrations/** min_reviewers: 3 require_design_review: true middle: paths: - api/** - services/** min_reviewers: 2 low: paths: - docs/** - styles/** - tests/** min_reviewers: 1 # 自動(dòng)化門禁 gates: static_check: true unit_test: true coverage_threshold: 80 security_scan: true配置文件寫好后注冊(cè) Webhook讓 PR 的創(chuàng)建和更新事件推送到 open-code-review 的服務(wù)端。服務(wù)端解析配置、進(jìn)行分級(jí)然后調(diào)用 Git 平臺(tái)的 API 自動(dòng)指派評(píng)審人、發(fā)布機(jī)器人評(píng)審意見(jiàn)。這里有一個(gè)非常關(guān)鍵的細(xì)節(jié)評(píng)審人的自動(dòng)指派不要只看“誰(shuí)有空”要看“誰(shuí)最了解這塊代碼”。建議通過(guò) Git 歷史文件所有者git blame 或 CHANGES 文件來(lái)計(jì)算代碼歸屬再匹配評(píng)審人。否則分配的評(píng)審人大概率只能提出泛泛的格式建議抓不住核心邏輯問(wèn)題。3.2 一個(gè)完整的評(píng)審閉環(huán)長(zhǎng)什么樣我把一次完整的評(píng)審流程描述出來(lái)方便你對(duì)照自己的團(tuán)隊(duì)流程找差距第一步開(kāi)發(fā)者提交 MR變更描述模板自動(dòng)展開(kāi)。包括背景、改動(dòng)清單、影響面、測(cè)試記錄、自測(cè)結(jié)果。描述不完整會(huì)被機(jī)器人標(biāo)記。第二步自動(dòng)化門禁啟動(dòng)。通常五分鐘內(nèi)完成靜態(tài)檢查、測(cè)試、覆蓋率比對(duì)。任意一項(xiàng)不通過(guò)MR 狀態(tài)被標(biāo)記為 blocked系統(tǒng)不會(huì)分配人工評(píng)審人。第三步門禁通過(guò)后系統(tǒng)按風(fēng)險(xiǎn)等級(jí)分配評(píng)審人。評(píng)審人收到通知在自己的時(shí)間窗口內(nèi)審查代碼。每一條評(píng)論都結(jié)構(gòu)化記錄到數(shù)據(jù)庫(kù)中。第四步開(kāi)發(fā)者回應(yīng)評(píng)論??梢灾苯釉谠u(píng)論區(qū)回復(fù)“已修改”修改后推送新 commit機(jī)器人自動(dòng)標(biāo)記該評(píng)論為“已解決待驗(yàn)證”。如果開(kāi)發(fā)者不同意意見(jiàn)必須選擇“拒絕”并填寫理由。第五步所有阻塞級(jí)評(píng)論解決后評(píng)審人點(diǎn)擊 ApproveMR 才有權(quán)限合入。合入前系統(tǒng)還會(huì)檢查一遍測(cè)試狀態(tài)防止合入窗口期有人代碼破壞。這套閉環(huán)跑穩(wěn)定之后團(tuán)隊(duì)評(píng)審的紀(jì)律性會(huì)變得非常強(qiáng)。新人也知道怎么參與評(píng)審了因?yàn)槊恳徊蕉加心0濉⒂刑崾?、有記錄?.3 檢查單體系建設(shè)把經(jīng)驗(yàn)變成流程檢查單是 open-code-review 里非常關(guān)鍵的一環(huán)。我見(jiàn)過(guò)太多團(tuán)隊(duì)評(píng)審質(zhì)量靠“個(gè)人能力”組里有大神在就穩(wěn)大神走了就垮。檢查單解決了這個(gè)問(wèn)題它把隱性知識(shí)顯性化。前端變更檢查單示例狀態(tài)更新是不是用了不可變方式組件卸載后有沒(méi)有清理副作用關(guān)鍵交互有沒(méi)有埋點(diǎn)和異常上報(bào)新增依賴的體積是否可接受后端變更檢查單示例接口入?yún)⒂袥](méi)有做邊界校驗(yàn)數(shù)據(jù)查詢有沒(méi)有潛在 N1事務(wù)邊界是否正確異常路徑有沒(méi)有回滾關(guān)鍵路徑有沒(méi)有日志和監(jiān)控指標(biāo)基礎(chǔ)設(shè)施變更檢查單示例配置變更是否兼容回滾是否有容量評(píng)估權(quán)限變更是否走最小授權(quán)檢查單不是一成不變的。我建議每季度review一次把過(guò)去一季度線上事故復(fù)盤出的經(jīng)驗(yàn)、評(píng)審中出現(xiàn)的高頻問(wèn)題加入檢查單。這樣一個(gè)季度一個(gè)季度地迭代檢查單會(huì)越來(lái)越貼合團(tuán)隊(duì)的真實(shí)情況評(píng)審質(zhì)量也隨之上一個(gè)臺(tái)階。有新人加入團(tuán)隊(duì)的時(shí)候我直接讓他先讀檢查單比看文檔高效得多。3.4 反饋循環(huán)評(píng)審數(shù)據(jù)怎么反哺開(kāi)發(fā)和項(xiàng)目規(guī)劃光跑流程不沉淀數(shù)據(jù)等于白做。open-code-review 會(huì)把每一次評(píng)審的數(shù)據(jù)都存下來(lái)包括評(píng)審時(shí)長(zhǎng)、評(píng)論數(shù)、問(wèn)題類型分布、問(wèn)題解決時(shí)長(zhǎng)、哪類問(wèn)題最容易被漏掉等等。這些數(shù)據(jù)最直接的一個(gè)用途是指導(dǎo)技術(shù)架構(gòu)改進(jìn)。比如數(shù)據(jù)統(tǒng)計(jì)顯示“數(shù)據(jù)庫(kù)查詢類”的問(wèn)題反復(fù)出現(xiàn)那就應(yīng)該考慮在數(shù)據(jù)訪問(wèn)層引入統(tǒng)一的查詢規(guī)范甚至用代碼生成代替手寫 SQL。統(tǒng)計(jì)顯示“緩存失效”類問(wèn)題占比較高那就需要review一下團(tuán)隊(duì)常用的緩存模式找出易錯(cuò)設(shè)計(jì)并改進(jìn)。另一個(gè)用途是影響排期。評(píng)審中積累的“技術(shù)債”類建議可以按照發(fā)生頻率和影響面排進(jìn)迭代計(jì)劃、專項(xiàng)治理而不是讓它們永遠(yuǎn)停留在評(píng)論區(qū)里吃灰。我在團(tuán)隊(duì)就是這么做的——每個(gè)月花半天時(shí)間把上個(gè)月的評(píng)審數(shù)據(jù)快速過(guò)一遍挑出三個(gè)最高頻的問(wèn)題點(diǎn)作為下個(gè)月技術(shù)改進(jìn)的重點(diǎn)。4. 常見(jiàn)問(wèn)題與排查技巧實(shí)錄4.1 評(píng)審變成了“挑刺大會(huì)”團(tuán)隊(duì)氛圍變差推行嚴(yán)格評(píng)審后最常遇到的問(wèn)題就是對(duì)抗心態(tài)。開(kāi)發(fā)者覺(jué)得自己寫的代碼被找茬評(píng)審人覺(jué)得自己是警察。這個(gè)現(xiàn)象的本質(zhì)是團(tuán)隊(duì)的反饋模型出了問(wèn)題。我解決這個(gè)問(wèn)題的手段很直接把“提意見(jiàn)”改成“提問(wèn)題”。同樣看到一段邏輯復(fù)雜、很難讀懂的代碼不許說(shuō)“這段代碼該重構(gòu)”要說(shuō)“我沒(méi)太看懂這段邏輯會(huì)不會(huì)存在 XX 情況沒(méi)處理”前者是指責(zé)后者是請(qǐng)你講解。這個(gè)變化最初靠制度約束后來(lái)靠文化滲透。open-code-review 可以在評(píng)論模板里加上“提問(wèn)式表達(dá)”的提示如果評(píng)論以“你應(yīng)該”“這樣不對(duì)”這類指責(zé)式開(kāi)頭機(jī)器人會(huì)提醒一次。慢慢地大家發(fā)現(xiàn)用提問(wèn)的方式表達(dá)意見(jiàn)被接受的概率高很多而且討論質(zhì)量也提升了。另外一個(gè)細(xì)節(jié)評(píng)審?fù)ㄟ^(guò)后如果代碼上線出了問(wèn)題不要把責(zé)任推到評(píng)審人頭上。一旦開(kāi)了這個(gè)頭以后所有人都只給“安全”的通過(guò)意見(jiàn)該提的深層問(wèn)題反而不提了。評(píng)審是集體負(fù)責(zé)制事后復(fù)盤只問(wèn)流程哪里可以改進(jìn)不追究個(gè)人責(zé)任這個(gè)底線一定要守住。4.2 高風(fēng)險(xiǎn)變更沒(méi)人能審核心開(kāi)發(fā)者成了瓶頸小團(tuán)隊(duì)經(jīng)常遇到這種情況系統(tǒng)里真正懂核心模塊的就那一個(gè)人所有高風(fēng)險(xiǎn)的變更都得等他評(píng)審。這個(gè)人一天之內(nèi)被阻塞的 MR 堵到懷疑人生。這個(gè)問(wèn)題的解法不是“逼核心開(kāi)發(fā)者打點(diǎn)所有時(shí)間”而是讓他從“評(píng)審所有代碼”變成“評(píng)審評(píng)審意見(jiàn)”核心做法是把經(jīng)驗(yàn)前置和授權(quán)結(jié)合。具體來(lái)說(shuō)把核心模塊的評(píng)審檢查單做細(xì)盡量把核心開(kāi)發(fā)者的決策邏輯沉淀到規(guī)則里。然后讓資深開(kāi)發(fā)者對(duì)普通評(píng)審人的評(píng)審結(jié)果進(jìn)行抽檢、backup review而不是參與每一單評(píng)審。這種模式下核心開(kāi)發(fā)者可以把時(shí)間花在建立規(guī)則上而不是消耗在一次又一次重復(fù)的 Review 里。等規(guī)則足夠完善普通評(píng)審人也能處理大部分常規(guī)評(píng)審核心開(kāi)發(fā)者只需要把關(guān)小部分真正復(fù)雜的設(shè)計(jì)問(wèn)題。4.3 緊急修復(fù)繞過(guò)評(píng)審帶病上線“線上故障火速修復(fù)先上再說(shuō)后續(xù)補(bǔ)評(píng)審”這個(gè)話術(shù)是不是很耳熟如果這個(gè)口子經(jīng)常開(kāi)那就不是應(yīng)急方案而是在瓦解整個(gè)評(píng)審體系。open-code-review 對(duì)于這種情況的設(shè)計(jì)理念是不堵但是要留下記錄。緊急修復(fù)可以走 hotfix 通道只需一人評(píng)審或者由運(yùn)營(yíng)/值班負(fù)責(zé)人確認(rèn)但合入后系統(tǒng)會(huì)強(qiáng)制創(chuàng)建一個(gè)“補(bǔ)評(píng)審”任務(wù)并把修復(fù)代碼與對(duì)應(yīng)的線上問(wèn)題關(guān)聯(lián)起來(lái)。補(bǔ)評(píng)審如果在規(guī)定時(shí)間內(nèi)沒(méi)有完成自動(dòng)升級(jí)給技術(shù)負(fù)責(zé)人。這樣做的目的很明確緊急情況下允許流程簡(jiǎn)化但不允許問(wèn)題被掩蓋。事后補(bǔ)評(píng)審產(chǎn)生的意見(jiàn)同樣會(huì)進(jìn)入數(shù)據(jù)統(tǒng)計(jì)、知識(shí)沉淀的管道。從這個(gè)角度來(lái)說(shuō)hotfix 不是評(píng)審體系的漏洞反而是體系的一部分。4.4 評(píng)審意見(jiàn)長(zhǎng)期掛起沒(méi)有結(jié)論評(píng)審評(píng)論提了開(kāi)發(fā)者改了一輪后來(lái)某些評(píng)論就被遺忘了?;蛘唛_(kāi)發(fā)者覺(jué)得某些建議不合理又沒(méi)有明確的拒絕機(jī)制掛在那邊最后不了了之。這是評(píng)審執(zhí)行層面最常見(jiàn)的管理漏洞。我踩過(guò)這個(gè)坑之后規(guī)定了三條硬規(guī)則第一條所有阻塞級(jí)評(píng)論必須顯式解決不能被默默無(wú)視。第二條所有被拒絕的評(píng)論必須有理由。第三條擱置超過(guò) 48 小時(shí)的評(píng)論系統(tǒng)自動(dòng)提醒雙方如果再過(guò)一個(gè)工作日還沒(méi)有處理自動(dòng)抄送技術(shù)負(fù)責(zé)人。這三條規(guī)則一經(jīng)執(zhí)行評(píng)論掛起的情況基本絕跡了。另外附帶一個(gè)小技巧要把“評(píng)審意見(jiàn)”和“閑聊”區(qū)分開(kāi)。非阻塞性建議、個(gè)人偏好或者是夸獎(jiǎng)的話不進(jìn)入評(píng)論臺(tái)賬。否則每一條都要求“解決”反而會(huì)給開(kāi)發(fā)者帶來(lái)不必要的負(fù)擔(dān)。5. 代碼評(píng)審的技術(shù)監(jiān)督與度量維度5.1 哪些指標(biāo)值得看哪些指標(biāo)會(huì)騙人沒(méi)有度量就沒(méi)有改進(jìn)但度量的指標(biāo)如果選錯(cuò)了很容易變成數(shù)字游戲。我在實(shí)踐過(guò)程中把評(píng)審指標(biāo)分成三組每一組都有明確的使用場(chǎng)景。效率指標(biāo)評(píng)審等待時(shí)間、評(píng)審耗時(shí)、每輪修改輪次。這類指標(biāo)反映的是流程順暢度。如果一個(gè) MR 平均要修改五六輪才通過(guò)那多半不是開(kāi)發(fā)者能力問(wèn)題而是評(píng)審意見(jiàn)本身不夠清晰、或者需求本身就不明確需要從更早的環(huán)節(jié)去調(diào)整。質(zhì)量指標(biāo)漏檢率評(píng)審?fù)ㄟ^(guò)后線上問(wèn)題發(fā)生比例、缺陷類型分布、每千行代碼評(píng)審評(píng)論數(shù)。這類指標(biāo)用于評(píng)估評(píng)審體系本身的效果。漏檢率是最重要的指標(biāo)如果漏檢率長(zhǎng)期偏高說(shuō)明評(píng)審重點(diǎn)不對(duì)或者評(píng)審人能力覆蓋不夠。協(xié)作指標(biāo)參與評(píng)審人數(shù)、評(píng)論被解決率、評(píng)審人回復(fù)時(shí)長(zhǎng)。這類指標(biāo)用于判斷團(tuán)隊(duì)協(xié)作的健康度。如果一個(gè)模塊長(zhǎng)期只有同一個(gè)人評(píng)審這個(gè)模塊的能力備份就是缺失的要提前預(yù)防風(fēng)險(xiǎn)。提醒千萬(wàn)不要把指標(biāo)用于績(jī)效考核。一旦評(píng)審數(shù)據(jù)跟績(jī)效掛鉤團(tuán)隊(duì)就會(huì)出現(xiàn)兩個(gè)極端——要么互相放過(guò)、你好我好要么互相苛刻、把評(píng)論條數(shù)刷上去。這兩種情況都會(huì)毀掉評(píng)審體系的真正價(jià)值。指標(biāo)是用來(lái)發(fā)現(xiàn)問(wèn)題的不是用來(lái)定罪的。5.2 變更是最小單位把代碼質(zhì)量問(wèn)題定位到模塊如果只看匯總數(shù)據(jù)你很難知道哪一塊需要改進(jìn)。open-code-review 的做法是把所有評(píng)審數(shù)據(jù)按模塊或者目錄進(jìn)行拆分統(tǒng)計(jì)。拿一個(gè)典型的服務(wù)端項(xiàng)目舉例數(shù)據(jù)拆完之后你會(huì)發(fā)現(xiàn)order-service模塊的評(píng)審評(píng)論密度是其他模塊的 3 倍評(píng)論類型集中在“事務(wù)處理”“狀態(tài)流轉(zhuǎn)”這個(gè)模塊的線上問(wèn)題率也比其他模塊高。這幾條數(shù)據(jù)放在一起結(jié)論就非常清晰這個(gè)模塊設(shè)計(jì)復(fù)雜度高、實(shí)現(xiàn)重復(fù)率高、關(guān)鍵路徑缺乏統(tǒng)一抽象。那接下來(lái)就不是繼續(xù)找開(kāi)發(fā)者的溝通問(wèn)題了而是在架構(gòu)層面考慮重構(gòu)方案。有了這種模塊級(jí)的定位能力評(píng)審系統(tǒng)就成了團(tuán)隊(duì)技術(shù)決策的“醫(yī)療報(bào)告”。不只是看到表面數(shù)據(jù)還能定位病灶在哪個(gè)系統(tǒng)、哪個(gè)模塊這對(duì)大團(tuán)隊(duì)尤其重要。5.3 從評(píng)審數(shù)據(jù)到知識(shí)庫(kù)的自動(dòng)化沉淀評(píng)審中產(chǎn)生的高質(zhì)量討論不應(yīng)該只停留在 MR 評(píng)論區(qū)。我在 open-code-review 里做了個(gè)機(jī)制當(dāng)一個(gè)評(píng)審評(píng)論的討論超過(guò)一定輪次、或者被多次標(biāo)記為“高價(jià)值”系統(tǒng)會(huì)提示評(píng)論發(fā)起人選擇是否沉淀到團(tuán)隊(duì)知識(shí)庫(kù)中。沉淀的內(nèi)容會(huì)經(jīng)過(guò)簡(jiǎn)短的整理比如把問(wèn)題描述、示例代碼、解決辦法、關(guān)聯(lián)鏈接匯總成一條知識(shí)文檔。這樣做的好處是團(tuán)隊(duì)在遇到類似問(wèn)題的時(shí)候能夠檢索到以前踩過(guò)的坑和提煉出的解決方案而不需要重新討論一遍或者靠老員工的記憶。幾個(gè)月后知識(shí)庫(kù)就變成了團(tuán)隊(duì)最寶貴的資產(chǎn)——每一頁(yè)都是真實(shí)的問(wèn)題、真實(shí)的決策、真實(shí)的經(jīng)驗(yàn)。6. 落地經(jīng)驗(yàn)和最后的建議6.1 先小范圍試點(diǎn)不要一刀切全部推行如果你打算在團(tuán)隊(duì)里落地 open-code-review我強(qiáng)烈建議不要搞“全團(tuán)隊(duì)同時(shí)切換”。最穩(wěn)妥的做法是選一個(gè)業(yè)務(wù)相對(duì)獨(dú)立、成員配合意愿較高的小組先試點(diǎn)跑兩周到一個(gè)月。試點(diǎn)期間重點(diǎn)關(guān)注三件事第一配置的規(guī)則是否符合實(shí)際業(yè)務(wù)場(chǎng)景、有沒(méi)有明顯不合理的條目第二開(kāi)發(fā)者和評(píng)審人的反饋尤其是哪些流程讓人覺(jué)得繁瑣、哪些檢查沒(méi)有必要第三自動(dòng)化門禁的誤傷率比如覆蓋率卡得太死導(dǎo)致大量無(wú)用的補(bǔ)測(cè)試工作。試點(diǎn)穩(wěn)定后再逐步擴(kuò)大范圍。我在多個(gè)團(tuán)隊(duì)實(shí)踐下來(lái)第一稿配置通常都是偏嚴(yán)的往往需要調(diào)低某些規(guī)則的閾值或放寬低風(fēng)險(xiǎn)變更的路徑才能讓整體流程變得順暢。6.2 培養(yǎng)“評(píng)審人”而不是“審批人”最后想分享一個(gè)認(rèn)知層面的轉(zhuǎn)變。open-code-review 這套體系跑起來(lái)之后我發(fā)現(xiàn)最根本的改變不是流程自動(dòng)化而是團(tuán)隊(duì)里每一個(gè)人的角色認(rèn)知。代碼評(píng)審不是“審批”不是“找茬”更不是“走個(gè)過(guò)場(chǎng)”的行政流程。它實(shí)際上是每個(gè)參與者提升技術(shù)能力、對(duì)齊團(tuán)隊(duì)標(biāo)準(zhǔn)、降低線上風(fēng)險(xiǎn)最有效的日常場(chǎng)景。所以當(dāng)你推動(dòng)這套體系落地時(shí)要反復(fù)向團(tuán)隊(duì)傳遞一個(gè)態(tài)度寫代碼的人不是在“應(yīng)付評(píng)審”而是在“獲得第二雙眼睛”來(lái)審視自己的工作做評(píng)審的人不只是在“把關(guān)”而是在“從別人的代碼里學(xué)習(xí)”。有了這個(gè)共識(shí)工具層面的問(wèn)題都是容易解決的制度層面的問(wèn)題才是真正的挑戰(zhàn)。根據(jù)我的實(shí)踐經(jīng)驗(yàn)一套好的評(píng)審體系最終應(yīng)該達(dá)到這個(gè)狀態(tài)新人來(lái)了翻一翻檢查單和知識(shí)庫(kù)就能了解團(tuán)隊(duì)的規(guī)范和技術(shù)注意點(diǎn)開(kāi)發(fā)者提交 MR 時(shí)不再抱著“希望別被挑刺”的心態(tài)而是知道有人會(huì)看到自己沒(méi)看到的風(fēng)險(xiǎn)技術(shù)負(fù)責(zé)人則可以通過(guò)數(shù)據(jù)清晰掌握系統(tǒng)的健康程度和團(tuán)隊(duì)的成長(zhǎng)進(jìn)度。這才是開(kāi)放、高效、有生命力的評(píng)審文化也是 open-code-review 真正期待帶來(lái)的改變。