量閉環(huán):如何讓項目細(xì)節(jié)無可挑剔)
1. 一個詞引發(fā)的思考為什么impeccable值得單獨拿出來聊第一次看到impeccable這個詞被單獨拎出來當(dāng)作項目標(biāo)題我的反應(yīng)是愣了一下。這個詞在英文里是無可挑剔的、完美的意思詞源上來自拉丁語impeccabilisim-否定peccare犯錯字面意思就是不會犯錯的。一個詞本身能成為一個項目標(biāo)題說明它背后承載的東西已經(jīng)超出了詞義本身——它更像是一種標(biāo)準(zhǔn)、一種態(tài)度或者說一種對做到極致的執(zhí)念。我之所以對這個詞敏感是因為在過去幾年做代碼審查和項目復(fù)盤的過程中發(fā)現(xiàn)一個規(guī)律真正讓一個項目從能用變成好用、從交付變成口碑的往往不是某個炫技的功能點而是那些細(xì)節(jié)上挑不出毛病的積累。這個詞恰好精準(zhǔn)地概括了那種狀態(tài)。所以這篇內(nèi)容我想圍繞impeccable這個核心概念聊一聊在技術(shù)項目和產(chǎn)品打磨中如何把無可挑剔從一個形容詞變成一套可執(zhí)行的方法論。不管你是剛?cè)胄械拈_發(fā)者還是帶過幾個項目的老手這套思路都能直接拿去用。關(guān)鍵詞就三個細(xì)節(jié)標(biāo)準(zhǔn)、質(zhì)量閉環(huán)、可復(fù)現(xiàn)的打磨流程。這三個詞貫穿全文也是我這些年踩了無數(shù)坑之后總結(jié)出來的核心。需要說明的是原始輸入里除了標(biāo)題之外沒有更多正文和關(guān)鍵詞信息所以接下來的內(nèi)容是我基于impeccable這個核心概念結(jié)合一線項目經(jīng)驗做的合理延展和補(bǔ)全。所有案例均為虛構(gòu)代稱重點在于方法論和實操細(xì)節(jié)的分享。2. 無可挑剔到底在挑剔什么拆解impeccable的四層含義2.1 第一層功能層面的零缺陷大多數(shù)人理解的無可挑剔第一反應(yīng)就是沒有bug。這沒錯但只是最表層。功能層面的零缺陷指的是在定義的邊界條件內(nèi)所有預(yù)期行為都能正確執(zhí)行。注意這里的關(guān)鍵詞是定義的邊界條件內(nèi)——很多項目的問題不在于代碼寫錯了而在于邊界根本沒定義清楚。我見過一個典型的例子某團(tuán)隊做一個數(shù)據(jù)導(dǎo)出功能開發(fā)階段測試了正常數(shù)據(jù)量幾千條跑得很好。上線后用戶導(dǎo)出了幾十萬條直接內(nèi)存溢出。這不是代碼bug這是邊界定義缺失。后來他們在需求評審階段就加了一條硬性規(guī)則任何涉及數(shù)據(jù)量、并發(fā)數(shù)、超時時間的接口必須在文檔里寫明上下限并且上下限要有測試用例覆蓋。這條規(guī)則執(zhí)行了三個月之后線上事故率下降了將近一半。所以功能層面的無可挑剔核心動作是把正常情況和異常情況都列出來逐條驗證。我習(xí)慣用一個簡單的檢查表檢查維度具體問題是否覆蓋輸入邊界空值、超長、特殊字符、非法格式必須數(shù)據(jù)量級最小值、最大值、超限行為必須并發(fā)場景同時請求、重復(fù)提交、競態(tài)條件必須網(wǎng)絡(luò)異常超時、斷連、重試、冪等必須權(quán)限邊界未登錄、越權(quán)、角色切換必須這張表看起來簡單但真正每條都做到位的項目我見過的不到三成。2.2 第二層體驗層面的無摩擦功能對了不代表體驗好。無摩擦這個詞是我從交互設(shè)計里借來的指的是用戶在使用過程中不會因為設(shè)計問題而產(chǎn)生困惑、猶豫或額外的操作成本。舉個很小的例子一個表單提交按鈕點擊之后如果沒有任何反饋用戶會下意識地再點一次。這多出來的一次點擊就是摩擦。解決方式很簡單——按鈕進(jìn)入loading狀態(tài)、禁用重復(fù)點擊、給出明確的成功或失敗提示。但就是這種小事在很多項目里被忽略。我在做代碼審查時有一個習(xí)慣把自己當(dāng)成第一次使用這個功能的用戶走一遍完整流程記錄每一個讓我停頓超過兩秒的地方。這些停頓點就是摩擦點。常見的摩擦點包括錯誤提示不明確操作失敗vs手機(jī)號格式不正確請檢查后重試、加載狀態(tài)缺失、返回路徑不清晰、關(guān)鍵操作沒有二次確認(rèn)。2.3 第三層代碼層面的可維護(hù)性這一層是給同行看的。你的代碼能不能讓下一個接手的人在半小時內(nèi)看懂核心邏輯能不能在不破壞現(xiàn)有功能的前提下安全地添加新特性這些都是無可挑剔的重要組成部分。我評判代碼可維護(hù)性有個粗暴但有效的標(biāo)準(zhǔn)如果我把某個模塊的注釋全部刪掉一個中等水平的開發(fā)者能不能在20分鐘內(nèi)說清楚這個模塊在干什么。如果不能說明命名、結(jié)構(gòu)或抽象層次有問題。常見的可維護(hù)性殺手包括超長函數(shù)超過80行基本就該拆了、魔法數(shù)字直接寫死的數(shù)值沒有常量化、深層嵌套超過三層if-else就該考慮提前返回或策略模式、隱式依賴函數(shù)內(nèi)部直接引用了外部變量而沒有通過參數(shù)傳入。2.4 第四層協(xié)作層面的可預(yù)期性最后一層最容易被忽視但影響最大。一個無可挑剔的項目在團(tuán)隊協(xié)作層面應(yīng)該是高度可預(yù)期的。什么意思就是任何人拿到這個項目都能清楚地知道代碼在哪里、文檔在哪里、怎么跑起來、怎么部署、出了問題找誰、變更流程是什么。我經(jīng)歷過一個反面案例某項目交接時新接手的同學(xué)花了整整一周才把本地環(huán)境跑起來原因是依賴版本沒有鎖定、環(huán)境變量沒有文檔、數(shù)據(jù)庫初始化腳本缺失。這一周的消耗完全是可以通過規(guī)范避免的??深A(yù)期性的核心是降低信息不對稱。具體做法包括README必須包含五分鐘快速啟動指南、依賴版本必須鎖定lock文件提交到倉庫、環(huán)境變量必須有示例文件.env.example、關(guān)鍵決策必須有記錄ADR架構(gòu)決策記錄。3. 從差不多就行到挑不出毛病一套可落地的打磨流程3.1 建立完成的定義Definition of Done大部分項目質(zhì)量上不去根本原因不是能力不夠而是**完成的標(biāo)準(zhǔn)太模糊**。開發(fā)說做完了測試說還有問題產(chǎn)品說不是我要的——三方對完成的理解完全不一樣。我的做法是在項目啟動階段就和團(tuán)隊一起定義一份完成清單我把它叫做DoDDefinition of Done。這份清單必須具體到可驗證的程度不能是代碼質(zhì)量好這種虛的而應(yīng)該是所有公開函數(shù)有單元測試覆蓋覆蓋率不低于80%這種可以打勾的。一份典型的DoD清單長這樣功能驗收所有需求點有對應(yīng)的驗收用例且全部通過代碼審查至少一人review通過無未解決的評論測試覆蓋核心邏輯單元測試覆蓋率≥80%邊界用例全部覆蓋文檔更新接口文檔、變更日志、部署說明同步更新性能驗證關(guān)鍵接口響應(yīng)時間在預(yù)期范圍內(nèi)需給出具體數(shù)值安全檢查無硬編碼密鑰、無已知高危依賴漏洞回滾方案有明確的回滾步驟并驗證過這份清單的價值在于它把我覺得差不多了變成了清單上每一項都打勾了。主觀判斷變成客觀檢查扯皮的空間就小了。3.2 分層驗證不要等到最后才檢查很多團(tuán)隊的習(xí)慣是開發(fā)完再統(tǒng)一測試這是質(zhì)量事故的溫床。問題發(fā)現(xiàn)得越晚修復(fù)成本越高——這個規(guī)律在軟件工程里被反復(fù)驗證過。我的建議是采用分層驗證策略第一層提交前自檢。開發(fā)者本地跑通所有單元測試用lint工具檢查代碼風(fēng)格確認(rèn)沒有調(diào)試代碼殘留console.log、print、debugger。這一層靠工具自動化配置好pre-commit鉤子就行。第二層合并前審查。代碼審查不只是看代碼對不對更要看設(shè)計合不合理、命名清不清晰、有沒有更好的實現(xiàn)方式。我通常要求審查者至少提出一個改進(jìn)建議哪怕是很小的點這樣能形成持續(xù)改進(jìn)的氛圍。第三層集成驗證。在接近生產(chǎn)的環(huán)境里跑完整的集成測試驗證模塊之間的交互。這一層最容易暴露各自都對合起來就錯的問題。第四層驗收確認(rèn)。由需求提出方按照驗收用例逐條確認(rèn)確保交付物和預(yù)期一致。這四層不是每個項目都要全上但至少要有兩層提交前自檢和合并前審查。這兩層的投入產(chǎn)出比最高。3.3 問題追蹤讓每個缺陷都有歸宿無可挑剔不是說不出現(xiàn)問題而是說出現(xiàn)的問題都被妥善處理了。我見過太多項目測試提了bug開發(fā)說知道了然后就沒有然后了——既沒有修復(fù)也沒有記錄更沒有復(fù)盤。我的做法是建立一個簡單的問題追蹤機(jī)制核心就三個狀態(tài)待處理、處理中、已關(guān)閉。每個問題必須記錄現(xiàn)象描述、復(fù)現(xiàn)步驟、影響范圍、優(yōu)先級、負(fù)責(zé)人。關(guān)閉時必須注明解決方式修復(fù)、設(shè)計如此、無法復(fù)現(xiàn)、延期處理。這里有個經(jīng)驗優(yōu)先級不要超過三檔。高、中、低就夠了。我見過用五檔甚至十檔優(yōu)先級的團(tuán)隊結(jié)果就是所有人都搞不清楚緊急和非常緊急的區(qū)別最后等于沒有優(yōu)先級。3.4 復(fù)盤機(jī)制把教訓(xùn)變成資產(chǎn)每處理完一個有一定影響的問題花15分鐘做個小復(fù)盤。不用搞得很正式就回答三個問題發(fā)生了什么、為什么會發(fā)生、怎么防止再次發(fā)生。關(guān)鍵是第三個問題——怎么防止再次發(fā)生必須落到具體動作上。不能寫加強(qiáng)測試要寫在XX模塊增加XX場景的自動化測試用例。不能寫提高警惕要寫在代碼審查清單里增加XX檢查項。我堅持做復(fù)盤兩年多最大的收獲是積累了一份踩坑清單。每次新項目啟動時我會把這份清單過一遍看看哪些坑可能在這個項目里重現(xiàn)。這份清單現(xiàn)在有四十多條幫團(tuán)隊避免了很多重復(fù)性的問題。4. 那些讓項目差一口氣的隱形陷阱4.1 命名隨意最被低估的技術(shù)債變量叫data、函數(shù)叫handle、文件叫utils——這種命名在小型腳本里無所謂但在需要長期維護(hù)的項目里就是災(zāi)難。命名隨意的直接后果是讀代碼的人需要不斷跳轉(zhuǎn)到定義處才能理解含義閱讀效率大幅下降。我的命名原則很簡單變量名要能回答這是什么函數(shù)名要能回答它做什么。userList比data好fetchActiveUsers比handle好。如果實在想不出好名字往往說明這個變量或函數(shù)的職責(zé)本身就不清晰需要先理清職責(zé)再命名。還有一個常見問題是命名風(fēng)格不統(tǒng)一。同一個項目里有的地方用駝峰有的地方用下劃線有的地方用短橫線。這不是大問題但會給人一種這個項目沒人管的印象。解決辦法是在項目初始化時就配置好lint規(guī)則讓工具強(qiáng)制統(tǒng)一風(fēng)格。4.2 錯誤處理吞掉異常等于埋雷我審查代碼時特別關(guān)注錯誤處理。最常見的反模式是空catch塊——捕獲了異常但什么都不做。這比不捕獲還危險因為不捕獲至少程序會崩潰你能立刻發(fā)現(xiàn)問題空catch會讓程序帶著錯誤狀態(tài)繼續(xù)運行問題可能在很遠(yuǎn)的地方才暴露出來排查難度成倍增加。正確的做法是要么處理要么傳播絕不吞掉。如果當(dāng)前層無法處理這個異常就往上拋如果決定忽略必須寫清楚為什么可以忽略。我要求團(tuán)隊里所有catch塊必須至少包含一行日志記錄注明異常類型和上下文信息。另一個常見問題是錯誤信息不具體。throw new Error(操作失敗)這種信息對排查問題幾乎沒有幫助。好的錯誤信息應(yīng)該包含什么操作失敗了、失敗的原因是什么、可能的解決方向。比如throw new Error(用戶注冊失敗郵箱格式不合法期望格式為xxxyyy.zzz)。4.3 配置硬編碼環(huán)境切換時的噩夢把數(shù)據(jù)庫地址、API密鑰、超時時間直接寫在代碼里開發(fā)階段可能沒問題但一旦需要切換環(huán)境開發(fā)、測試、生產(chǎn)就要改代碼重新部署。更危險的是密鑰硬編碼在代碼里一旦代碼倉庫泄露密鑰就暴露了。我的做法是所有可能隨環(huán)境變化的值一律走配置。配置通過環(huán)境變量或配置文件注入代碼里只引用配置項的鍵名。同時提供一個配置示例文件列出所有需要的配置項和說明但不包含真實值。這里有個細(xì)節(jié)容易被忽略配置項要有默認(rèn)值或啟動時校驗。如果某個必需配置缺失程序應(yīng)該在啟動時就報錯并給出明確提示而不是運行到一半才崩潰。4.4 日志缺失出問題時兩眼一抹黑線上出了問題第一反應(yīng)是查日志。如果日志缺失或者信息不夠排查就像盲人摸象。我見過一些項目日志里只有請求開始和請求結(jié)束中間發(fā)生了什么完全看不到。好的日志應(yīng)該包含幾個要素時間戳、日志級別、請求標(biāo)識、關(guān)鍵參數(shù)、執(zhí)行結(jié)果。請求標(biāo)識特別重要——在并發(fā)場景下沒有請求標(biāo)識就無法把同一個請求產(chǎn)生的多條日志串聯(lián)起來。日志級別也要合理使用DEBUG用于開發(fā)調(diào)試的詳細(xì)信息INFO用于正常的業(yè)務(wù)流程節(jié)點WARN用于可恢復(fù)的異常情況ERROR用于需要立即關(guān)注的問題。我見過把所有信息都打成ERROR的項目結(jié)果真正的錯誤被淹沒在大量噪音里。4.5 依賴失控版本不鎖定埋下的隱患在我機(jī)器上能跑這個經(jīng)典問題很多時候就是依賴版本不一致導(dǎo)致的。沒有鎖定版本的情況下今天安裝的依賴和明天安裝的可能是不同版本行為可能完全不同。解決辦法很直接提交lock文件。不管用的是哪個包管理工具lock文件必須提交到版本控制。同時依賴升級要有計劃、有測試不能隨意升級。我通常建議每月做一次依賴檢查看看有沒有安全更新評估后再決定是否升級。5. 工具與習(xí)慣讓無可挑剔變成肌肉記憶5.1 自動化檢查把標(biāo)準(zhǔn)交給機(jī)器人是有惰性的靠自覺執(zhí)行標(biāo)準(zhǔn)不可靠。我的策略是能自動化的絕不靠人。具體來說代碼風(fēng)格配置lint工具提交時自動檢查不通過就拒絕提交類型檢查如果語言支持靜態(tài)類型開啟嚴(yán)格模式單元測試配置CI流水線測試不通過不允許合并依賴安全定期掃描依賴漏洞有高危漏洞自動告警提交信息配置提交信息格式檢查保證變更日志可自動生成這些工具配置一次長期受益。前期花兩三個小時配置后面能省下幾十個小時的扯皮和返工時間。5.2 代碼審查清單把經(jīng)驗固化下來代碼審查最容易犯的毛病是憑感覺——今天心情好就仔細(xì)看看明天趕進(jìn)度就隨便點個通過。解決辦法是準(zhǔn)備一份審查清單每次審查時逐條過。我的審查清單核心項這個改動解決了什么問題描述是否清晰有沒有更簡單的實現(xiàn)方式邊界條件是否處理異常路徑是否覆蓋命名是否準(zhǔn)確有沒有誤導(dǎo)性的名稱是否有重復(fù)代碼可以抽取測試是否充分測試用例是否有意義文檔和注釋是否需要同步更新有沒有引入新的依賴是否必要這份清單不需要每次全部打勾但至少過一遍能發(fā)現(xiàn)大部分常見問題。5.3 小步提交讓每次變更都可追溯我強(qiáng)烈建議小步提交——每次提交只做一件事提交信息說清楚做了什么、為什么這么做。這樣做的好處是出問題時容易定位回滾一個小提交比回滾一個大提交安全得多、代碼審查更容易審查者一次只需要理解一個邏輯變更、變更歷史更清晰看提交日志就能了解項目演進(jìn)過程。反面案例是一次提交改了二十個文件、涉及五個功能點提交信息寫修復(fù)若干問題。這種提交在出問題時幾乎無法定位回滾也不知道該回滾什么。5.4 定期重構(gòu)別讓債務(wù)滾雪球技術(shù)債和金融債務(wù)一樣越晚還利息越高。我的做法是每次迭代留出10%-20%的時間做重構(gòu)和優(yōu)化不等問題積累到無法收拾再處理。重構(gòu)的時機(jī)判斷當(dāng)你發(fā)現(xiàn)每次加新功能都要改很多老代碼、當(dāng)你發(fā)現(xiàn)改一個地方會莫名其妙影響另一個地方、當(dāng)你發(fā)現(xiàn)新人理解代碼需要超過一周——這些都是該重構(gòu)的信號。重構(gòu)的原則是行為不變。重構(gòu)前后外部可觀察的行為必須完全一致。所以重構(gòu)前要確保有足夠的測試覆蓋重構(gòu)后跑一遍測試確認(rèn)沒有破壞任何功能。6. 一個虛構(gòu)項目的完整打磨記錄6.1 項目背景與初始狀態(tài)為了把上面的方法論串起來我虛構(gòu)一個項目場景來演示。假設(shè)某團(tuán)隊要做一個跨平臺數(shù)據(jù)同步工具核心功能是把A系統(tǒng)的數(shù)據(jù)定期同步到B系統(tǒng)。初始版本由一位開發(fā)者用兩周時間完成功能能跑通但存在一系列問題。初始狀態(tài)的問題清單同步失敗沒有重試機(jī)制、日志只有開始和結(jié)束兩條、配置寫死在代碼里、沒有單元測試、錯誤提示只有同步失敗四個字、大數(shù)據(jù)量時內(nèi)存溢出。6.2 第一輪打磨功能可靠性首先解決可靠性問題。增加重試機(jī)制采用指數(shù)退避策略——第一次失敗等1秒重試第二次等2秒第三次等4秒最多重試5次。為什么用指數(shù)退避而不是固定間隔因為如果失敗原因是對方服務(wù)過載固定間隔重試會加劇對方的壓力指數(shù)退避給系統(tǒng)恢復(fù)的時間。然后處理大數(shù)據(jù)量問題。改為分批處理每批1000條處理完一批再取下一批。批大小怎么定太小會導(dǎo)致請求次數(shù)過多太大仍然有內(nèi)存風(fēng)險。1000條是實測下來比較平衡的值具體項目需要根據(jù)單條數(shù)據(jù)大小調(diào)整。6.3 第二輪打磨可觀測性增加結(jié)構(gòu)化日志每條日志包含時間戳、同步批次號、處理條數(shù)、耗時、成功數(shù)、失敗數(shù)。這樣出問題時看一眼日志就能知道哪個批次出了問題、處理了多少條、失敗原因是什么。同時增加一個簡單的健康檢查接口返回最近一次同步的狀態(tài)和時間。運維人員可以通過這個接口快速判斷同步是否正常不需要登錄服務(wù)器查日志。6.4 第三輪打磨可配置化把所有環(huán)境相關(guān)的配置抽出來源系統(tǒng)地址、目標(biāo)系統(tǒng)地址、同步間隔、批大小、重試次數(shù)、超時時間。通過配置文件注入同時提供配置示例和說明文檔。配置項增加啟動校驗如果必填項缺失或格式不對程序啟動時直接報錯并指出具體是哪個配置項有問題。這比運行到一半才發(fā)現(xiàn)配置錯誤要好得多。6.5 第四輪打磨測試覆蓋補(bǔ)充單元測試覆蓋核心邏輯數(shù)據(jù)轉(zhuǎn)換、分批邏輯、重試判斷、錯誤分類。同時增加集成測試用模擬的源系統(tǒng)和目標(biāo)系統(tǒng)驗證完整同步流程。測試用例特別關(guān)注邊界空數(shù)據(jù)集、單條數(shù)據(jù)、剛好一批的數(shù)據(jù)量、超過一批的數(shù)據(jù)量、源系統(tǒng)超時、目標(biāo)系統(tǒng)返回錯誤。這些邊界用例后來真的發(fā)現(xiàn)了兩個隱藏問題空數(shù)據(jù)集時程序會異常退出、目標(biāo)系統(tǒng)返回特定錯誤碼時重試邏輯沒有生效。6.6 打磨前后的對比維度打磨前打磨后同步失敗處理直接失敗需人工介入自動重試5次指數(shù)退避大數(shù)據(jù)量內(nèi)存溢出分批處理內(nèi)存穩(wěn)定問題排查只有兩條日志結(jié)構(gòu)化日志含批次號和統(tǒng)計環(huán)境切換改代碼重新部署改配置即可測試覆蓋無核心邏輯覆蓋率85%配置錯誤運行時崩潰啟動時校驗并提示這個虛構(gòu)項目從能跑到挑不出毛病總共花了大約三周時間做打磨。投入不小但后續(xù)維護(hù)成本大幅降低線上問題從每周兩三次降到每月一兩次。7. 關(guān)于無可挑剔的幾個認(rèn)知糾偏7.1 無可挑剔不等于過度設(shè)計有人可能會擔(dān)心追求無可挑剔會不會導(dǎo)致過度設(shè)計、拖慢進(jìn)度這個擔(dān)心是合理的但兩者有本質(zhì)區(qū)別。過度設(shè)計是加了不需要的東西無可挑剔是把需要的東西做到位。判斷標(biāo)準(zhǔn)很簡單你加的每一個機(jī)制能不能對應(yīng)到一個真實可能發(fā)生的問題如果答案是理論上可能那大概率是過度設(shè)計如果答案是上周就發(fā)生過或者同類型項目踩過這個坑那就是必要的。比如給一個內(nèi)部工具加多活容災(zāi)大概率是過度設(shè)計但給一個每天處理百萬級數(shù)據(jù)的同步任務(wù)加重試和分批就是必要的。7.2 無可挑剔是過程不是狀態(tài)沒有哪個項目能永遠(yuǎn)無可挑剔。需求在變、環(huán)境在變、依賴在變今天挑不出毛病不代表明天也挑不出。所以無可挑剔不是一次性達(dá)成的終點而是持續(xù)保持的過程。我的理解是它更像是一種衛(wèi)生習(xí)慣而不是一次大掃除。每天花一點時間保持比攢到年底集中清理要輕松得多效果也好得多。7.3 標(biāo)準(zhǔn)要匹配場景給一個存活周期只有兩周的臨時腳本追求無可挑剔是浪費時間給一個要維護(hù)五年的核心系統(tǒng)差不多就行是埋雷。標(biāo)準(zhǔn)要匹配場景這是我一直強(qiáng)調(diào)的。我的粗略判斷標(biāo)準(zhǔn)預(yù)計存活時間少于一個月的能跑就行一個月到半年的基本規(guī)范要有半年以上的按本文的方法論來。當(dāng)然涉及資金、安全、核心數(shù)據(jù)的項目無論存活多久都要高標(biāo)準(zhǔn)。7.4 團(tuán)隊共識比個人英雄主義重要一個人追求無可挑剔沒用必須變成團(tuán)隊共識。我見過技術(shù)很強(qiáng)的開發(fā)者自己代碼寫得很好但團(tuán)隊其他人跟不上結(jié)果整體質(zhì)量還是上不去。推動團(tuán)隊共識的方法先從最容易達(dá)成一致的點入手比如提交前跑通測試形成習(xí)慣后再逐步加碼。不要一上來就推全套規(guī)范那樣阻力太大。每推進(jìn)一步讓團(tuán)隊感受到好處比如線上問題減少了、加班排查的時間少了自然就有動力繼續(xù)。8. 我個人的幾條實操心得第一條把檢查清單放在手邊。我有一份自己的發(fā)布前檢查清單每次上線前逐條過。清單不長就十幾項但幫我避免了很多次差點忘了的情況。清單這東西寫下來和記在腦子里執(zhí)行率完全不一樣。第二條重視第一次出現(xiàn)的問題。同一個問題出現(xiàn)第一次時花時間徹底解決并記錄出現(xiàn)第二次時檢查上次的解決方案為什么沒生效出現(xiàn)第三次時說明流程有問題需要系統(tǒng)性調(diào)整。不要讓同一個問題反復(fù)出現(xiàn)。第三條定期回看自己的舊代碼。每隔幾個月回頭看自己之前寫的代碼如果覺得這寫的什么玩意兒說明進(jìn)步了如果覺得寫得真好要么是自戀要么是沒進(jìn)步?;乜磁f代碼是發(fā)現(xiàn)改進(jìn)點的高效方式。第四條別追求一步到位。從能跑到挑不出毛病是個漸進(jìn)過程每次改進(jìn)一點積累起來就很可觀。想一次做到完美往往導(dǎo)致遲遲無法交付反而得不償失。第五條記錄決策理由。為什么選這個方案而不是那個為什么用這個參數(shù)值這些決策理由當(dāng)時很清楚三個月后可能就忘了。寫下來未來的自己會感謝現(xiàn)在的自己。這些心得沒有什么高深的理論都是日常工作中一點一點積累的。但正是這些不起眼的習(xí)慣讓無可挑剔從一個形容詞變成了可以持續(xù)做到的事情。