評(píng)審實(shí)戰(zhàn):如何通過區(qū)分問題類型與優(yōu)化溝通方式高效指導(dǎo)新人)
1. 先搞清楚“評(píng)審?fù)降堋钡降自趯徥裁础霸u(píng)審?fù)降艿膬蓚€(gè)問題”這個(gè)標(biāo)題聽起來(lái)像是一個(gè)技術(shù)團(tuán)隊(duì)內(nèi)部的導(dǎo)師帶教場(chǎng)景。它不是一個(gè)具體的工具或框架而是一個(gè)關(guān)于技術(shù)評(píng)審和新人指導(dǎo)的實(shí)戰(zhàn)經(jīng)驗(yàn)總結(jié)。對(duì)于帶過團(tuán)隊(duì)、做過導(dǎo)師或者經(jīng)常需要參與代碼、設(shè)計(jì)、方案評(píng)審的人來(lái)說這個(gè)主題非常接地氣。很多人以為評(píng)審就是“找茬”或者“提幾個(gè)意見就完事了”。但實(shí)際帶人時(shí)你會(huì)發(fā)現(xiàn)評(píng)審的核心價(jià)值往往不在于指出一兩個(gè)具體的語(yǔ)法錯(cuò)誤而在于通過問題引導(dǎo)徒弟建立正確的思考框架和工作習(xí)慣。這兩個(gè)問題很可能就是導(dǎo)師在無(wú)數(shù)次評(píng)審中發(fā)現(xiàn)新人最容易反復(fù)踩坑、最影響成長(zhǎng)效率的關(guān)鍵點(diǎn)。所以這篇文章不是講某個(gè)技術(shù)的參數(shù)怎么調(diào)而是講如何通過評(píng)審這個(gè)動(dòng)作高效地傳遞經(jīng)驗(yàn)、規(guī)避風(fēng)險(xiǎn)、并培養(yǎng)徒弟獨(dú)立解決問題的能力。如果你正在帶新人或者你的工作經(jīng)常需要你給別人提意見那這篇文章里提到的思路和具體操作應(yīng)該能幫你省下不少溝通成本也讓你的反饋更有建設(shè)性。2. 第一個(gè)問題是“結(jié)果不對(duì)”還是“路徑錯(cuò)了”徒弟提交了一段代碼、一個(gè)設(shè)計(jì)圖或者一份方案文檔。你第一眼看到的結(jié)果可能就有問題。新手導(dǎo)師最容易犯的錯(cuò)誤是直接跳到結(jié)果層去批評(píng)“這個(gè)功能跑不通”、“這個(gè)性能不達(dá)標(biāo)”、“這個(gè)界面丑”。但更有價(jià)值的評(píng)審會(huì)先區(qū)分問題性質(zhì)這到底是最終“結(jié)果”本身錯(cuò)了還是達(dá)成結(jié)果的“思考路徑和方法”錯(cuò)了2.1 結(jié)果性錯(cuò)誤直接給答案不如給檢查清單結(jié)果性錯(cuò)誤通常比較明確比如代碼編譯報(bào)錯(cuò)、運(yùn)行崩潰、邏輯錯(cuò)誤導(dǎo)致輸出不符合預(yù)期。設(shè)計(jì)明顯違背設(shè)計(jì)規(guī)范、顏色字體混亂、交互流程斷掉。方案遺漏了核心需求、技術(shù)選型存在硬傷如用關(guān)系型數(shù)據(jù)庫(kù)存海量日志。對(duì)于這類問題我一般不會(huì)直接說“你這里寫錯(cuò)了應(yīng)該改成XXX”。因?yàn)橹苯咏o答案徒弟只學(xué)會(huì)了這個(gè)具體問題的解法下次換一個(gè)場(chǎng)景可能還會(huì)錯(cuò)。我的做法是提供一個(gè)排查清單或思考框架。比如面對(duì)一段跑不通的代碼我會(huì)問“你跑的時(shí)候報(bào)錯(cuò)信息是什么完整的堆??戳藛帷薄澳阍囘^用調(diào)試器跟一下或者在最可疑的地方加打印日志嗎”“這個(gè)函數(shù)的輸入在你調(diào)試的時(shí)候真的和你想象的一樣嗎”“你查過這個(gè)API的官方文檔嗎確認(rèn)過它的前置條件和返回值了嗎”通過這些問題我把“debug”這個(gè)動(dòng)作拆解成了可執(zhí)行的步驟。徒弟下次再遇到問題就會(huì)先按這個(gè)順序去自查而不是直接跑來(lái)問我。這就是在傳遞“漁”而非“魚”。2.2 路徑性錯(cuò)誤糾正思維習(xí)慣才能治本路徑性錯(cuò)誤更隱蔽也更關(guān)鍵。它指的是雖然這次的結(jié)果可能湊合能用但達(dá)成這個(gè)結(jié)果的思考過程、工作方法有嚴(yán)重缺陷長(zhǎng)期來(lái)看會(huì)埋下大坑。比如盲目復(fù)制粘貼從網(wǎng)上或舊項(xiàng)目里抄了一段代碼但完全沒理解上下文和邊界條件導(dǎo)致在新環(huán)境里水土不服。過度設(shè)計(jì)/過早優(yōu)化一個(gè)簡(jiǎn)單的內(nèi)部工具卻用上了最復(fù)雜的微服務(wù)架構(gòu)和設(shè)計(jì)模式。缺乏邊界思維只考慮了“happy path”一切正常的情況沒考慮網(wǎng)絡(luò)超時(shí)、數(shù)據(jù)為空、用戶非法輸入等異常場(chǎng)景。不寫測(cè)試/不做驗(yàn)證功能寫完就直接說“好了”沒有任何自測(cè)或單元測(cè)試。評(píng)審時(shí)遇到這類問題重點(diǎn)就不在于修改當(dāng)前的產(chǎn)出物了。我會(huì)把評(píng)審會(huì)變成一次小的“復(fù)盤”或“設(shè)計(jì)討論”。我會(huì)問“你是怎么想到用這個(gè)方案的有沒有考慮過更簡(jiǎn)單的做法”“如果輸入的數(shù)據(jù)量增大10倍你這段代碼哪里會(huì)先出問題”“這個(gè)功能上線前你自己會(huì)怎么驗(yàn)證它是對(duì)的能演示給我看嗎”這些問題旨在暴露他思考過程中的盲區(qū)。通過討論引導(dǎo)他去建立“先理解后復(fù)用”、“先跑通再優(yōu)化”、“先考慮主干再處理異?!薄ⅰ伴_發(fā)完必須自驗(yàn)”等一系列好的工作習(xí)慣。糾正了路徑以后他產(chǎn)出正確結(jié)果的概率才會(huì)大幅提升。3. 第二個(gè)問題是“他沒聽懂”還是“我沒講清”評(píng)審?fù)杲o出了修改意見但徒弟改出來(lái)的第二版、第三版還是不盡人意。這時(shí)候很多導(dǎo)師會(huì) frustration覺得“這人理解能力有問題”或者“不上心”。但根據(jù)我的經(jīng)驗(yàn)至少有一半的情況問題出在溝通反饋的方式上。我們的評(píng)審意見可能本身是模糊的、矛盾的或者缺乏上下文的。3.1 模糊的指令 vs. 清晰的驗(yàn)收標(biāo)準(zhǔn)我們經(jīng)常說一些正確的“廢話”比如“這個(gè)代碼要優(yōu)化一下。”“這個(gè)設(shè)計(jì)不夠優(yōu)雅?!薄靶阅茉偬嵘嵘??!边@些反饋對(duì)于新人來(lái)說等于沒有反饋。他不知道具體要做什么做到什么程度才算“優(yōu)化”、“優(yōu)雅”、“提升”。我要求自己給出的每一條修改意見都必須盡量符合“SMART”原則具體、可衡量、可達(dá)成、相關(guān)、有時(shí)限中的前兩條。比如模糊“優(yōu)化一下數(shù)據(jù)庫(kù)查詢?!鼻逦斑@條SQL語(yǔ)句在測(cè)試環(huán)境查100條數(shù)據(jù)花了2秒目標(biāo)是在相同條件下降到200毫秒以內(nèi)。可以嘗試從加索引、優(yōu)化WHERE條件、或者減少SELECT的字段數(shù)這幾個(gè)方向入手改完后我們?cè)儆猛瑯拥臄?shù)據(jù)測(cè)一次?!蹦:斑@個(gè)錯(cuò)誤處理太簡(jiǎn)陋了?!鼻逦斑@個(gè)網(wǎng)絡(luò)請(qǐng)求目前只處理了成功的情況。需要補(bǔ)充處理1. 網(wǎng)絡(luò)超時(shí)比如30秒無(wú)響應(yīng)2. HTTP狀態(tài)碼非200如404、5003. 返回的JSON解析失敗。每種情況至少要在日志里留下明確的錯(cuò)誤碼和簡(jiǎn)要信息?!苯o出清晰的驗(yàn)收標(biāo)準(zhǔn)徒弟才知道靶心在哪改起來(lái)有方向你復(fù)查起來(lái)也省力。3.2 缺乏上下文的“金科玉律”有時(shí)候我們給出的意見是基于長(zhǎng)期經(jīng)驗(yàn)形成的“最佳實(shí)踐”但直接拋出去徒弟會(huì)覺得很教條。比如“這里一定要用StringBuilder不要用字符串拼接”如果不說原因徒弟可能只是機(jī)械地改了但下次在另一個(gè)不關(guān)鍵的場(chǎng)景比如只拼接兩三次字符串他可能又會(huì)忘記。他會(huì)覺得這條規(guī)則很“玄學(xué)”。所以我在給出這類“規(guī)則性”意見時(shí)一定會(huì)附帶簡(jiǎn)短的上下文和原因“在循環(huán)體內(nèi)做字符串拼接用號(hào)會(huì)產(chǎn)生大量臨時(shí)對(duì)象影響性能。StringBuilder是專門為這種場(chǎng)景設(shè)計(jì)的內(nèi)存效率更高。當(dāng)然如果只是固定拼接兩三個(gè)字符串在外面用號(hào)更直觀也沒問題?!薄斑@個(gè)配置不要寫死在代碼里要放到配置文件。因?yàn)橐院蟛渴鸬綔y(cè)試、生產(chǎn)環(huán)境這個(gè)值很可能不一樣硬編碼會(huì)導(dǎo)致每次都要改代碼、重新編譯?!苯忉屃恕盀槭裁础币?guī)則就不再是冰冷的禁令而成了有道理、可被理解、甚至可被靈活運(yùn)用的知識(shí)。徒弟也更容易記住并應(yīng)用到其他場(chǎng)景。4. 把評(píng)審變成一個(gè)可重復(fù)的“培養(yǎng)流程”評(píng)審不能是隨機(jī)的、即興的。對(duì)于帶徒弟尤其是初級(jí)新人我傾向于把它變成一個(gè)結(jié)構(gòu)化的、有準(zhǔn)備的例行活動(dòng)。這樣對(duì)雙方都更高效。4.1 評(píng)審前讓徒弟帶著“上下文”來(lái)我不會(huì)讓徒弟直接把代碼或文檔扔過來(lái)就說“師兄/姐幫我看一下”。那樣我切入成本太高。我要求他在發(fā)起評(píng)審請(qǐng)求時(shí)必須附帶一個(gè)簡(jiǎn)短的“自評(píng)說明”哪怕只有幾句話。這個(gè)說明要包括核心改動(dòng)這次提交主要想實(shí)現(xiàn)什么功能解決了什么問題實(shí)現(xiàn)思路你大概是怎么做的例如用了哪個(gè)庫(kù)、主要算法邏輯是什么已知問題你自己覺得哪里可能還有問題或者哪里沒把握測(cè)試情況你自己是怎么測(cè)試的結(jié)果如何這個(gè)動(dòng)作逼著他在提交前先自己過一遍腦子進(jìn)行了一次自我評(píng)審。很多時(shí)候他在寫這個(gè)說明的過程中自己就能發(fā)現(xiàn)一些問題。同時(shí)這份說明給了我巨大的上下文讓我能快速抓住重點(diǎn)不用從零開始理解他的代碼。4.2 評(píng)審中聚焦核心分層討論正式評(píng)審時(shí)我會(huì)遵循一個(gè)討論順序避免東一榔頭西一棒子目標(biāo)對(duì)齊層先確認(rèn)我們理解的目標(biāo)是一致的。有時(shí)徒弟做著做著會(huì)偏離原始需求。架構(gòu)/設(shè)計(jì)層整體方案有沒有大問題模塊劃分是否清晰擴(kuò)展性如何關(guān)鍵實(shí)現(xiàn)層核心算法、關(guān)鍵流程、外部依賴的使用是否正確、高效代碼規(guī)范/細(xì)節(jié)層命名、注釋、錯(cuò)誤處理、日志打印等。測(cè)試與部署層是否有足夠的測(cè)試配置、依賴是否清晰這個(gè)順序很重要。如果架構(gòu)就有問題那么討論代碼細(xì)節(jié)的命名規(guī)范是毫無(wú)意義的。我會(huì)明確告訴徒弟“我們現(xiàn)在在討論第二層的問題第三層的細(xì)節(jié)我們先記下來(lái)等大方向定了再回頭看?!?.3 評(píng)審后明確行動(dòng)項(xiàng)并跟蹤閉環(huán)評(píng)審會(huì)議結(jié)束時(shí)最忌諱的就是“嗯大概明白了我去改改”。這樣大概率會(huì)漏項(xiàng)或者改偏。我的習(xí)慣是當(dāng)場(chǎng)用文檔如會(huì)議紀(jì)要、Issue評(píng)論、共享文檔列出明確的行動(dòng)項(xiàng)Action Items。每個(gè)行動(dòng)項(xiàng)包括內(nèi)容具體要修改什么。基于前面講的“清晰指令”負(fù)責(zé)人誰(shuí)來(lái)做。通常是徒弟驗(yàn)收標(biāo)準(zhǔn)怎么算改好了。截止時(shí)間什么時(shí)候完成。然后我會(huì)和徒弟約定一個(gè)簡(jiǎn)單的跟蹤方式比如改完后在文檔里標(biāo)記完成或者再次發(fā)起一個(gè)輕量的代碼審查。確保每一個(gè)評(píng)審意見都落地閉環(huán)了。這不僅保證了問題被解決也讓徒弟養(yǎng)成“凡事有交代件件有著落”的職業(yè)習(xí)慣。5. 導(dǎo)師自己容易踩的坑心態(tài)與邊界最后說說作為導(dǎo)師在評(píng)審時(shí)自己要注意的幾個(gè)心態(tài)問題這些坑我也都踩過。第一個(gè)坑追求“完美”而非“通過”。新手導(dǎo)師容易陷入細(xì)節(jié)想把徒弟的代碼改成自己心中的“藝術(shù)品”。這會(huì)導(dǎo)致評(píng)審時(shí)間無(wú)限拉長(zhǎng)徒弟也備受打擊。要記住評(píng)審的首要目標(biāo)是確保代碼/方案“正確且可維護(hù)”而不是“完美”。一些不影響正確性、可讀性和可維護(hù)性的個(gè)人風(fēng)格問題可以適當(dāng)放寬或者作為后續(xù)改進(jìn)建議提出不要 blocking。第二個(gè)坑變成“我來(lái)寫”而不是“你來(lái)改”??吹酵降軐懙貌缓靡恢本椭苯由鲜指拇a或者把重寫好的代碼發(fā)給他。這剝奪了他學(xué)習(xí)和思考的過程。正確的做法是用提問引導(dǎo)他自己找到修改方向或者在他修改的過程中提供實(shí)時(shí)答疑。他的代碼最終必須由他自己的手改出來(lái)。第三個(gè)坑忽視正向反饋。評(píng)審不能只提問題。當(dāng)徒弟某處設(shè)計(jì)得不錯(cuò)、考慮得很周全、或者相比上次有顯著進(jìn)步時(shí)一定要明確指出來(lái)給予肯定。正向激勵(lì)和負(fù)面批評(píng)同樣重要甚至更重要。它能幫助徒弟建立信心明確知道什么是對(duì)的、好的從而形成正向循環(huán)。第四個(gè)坑沒有隨著徒弟成長(zhǎng)而調(diào)整評(píng)審重心。對(duì)剛?cè)肼毜耐降茉u(píng)審要細(xì)側(cè)重基礎(chǔ)規(guī)范和思維養(yǎng)成。當(dāng)他逐漸上手后評(píng)審重心就要轉(zhuǎn)移到架構(gòu)設(shè)計(jì)、性能邊界、技術(shù)選型等更高層次的問題上。如果他已經(jīng)開始獨(dú)立負(fù)責(zé)模塊那么評(píng)審可能就更像是“技術(shù)方案討論會(huì)”以同步信息和風(fēng)險(xiǎn)識(shí)別為主。導(dǎo)師的介入方式和深度需要?jiǎng)討B(tài)調(diào)整。說到底評(píng)審?fù)降艿墓ぷ骷夹g(shù)能力只占一部分更多是溝通和引導(dǎo)的藝術(shù)。把這兩個(gè)核心問題——“結(jié)果vs路徑”、“表達(dá)vs理解”——處理好了你就能從一個(gè)單純的“代碼審查者”變成一個(gè)真正的“成長(zhǎng)加速器”。這個(gè)過程對(duì)徒弟是學(xué)習(xí)對(duì)導(dǎo)師自己何嘗不是一次管理能力和技術(shù)視野的錘煉。