階模型,從能跑到會(huì)設(shè)計(jì))
開(kāi)頭可以直接這樣寫(xiě)如果你在技術(shù)社區(qū)混過(guò)一段時(shí)間大概見(jiàn)過(guò)不少“xxcode”風(fēng)格的項(xiàng)目名。我今天想聊的“t3code”是我自己發(fā)起并跑通的一個(gè)編程能力進(jìn)階計(jì)劃代號(hào)里的 T3 代表 Three Tiers三層也就是把寫(xiě)代碼這件事拆成三個(gè)層級(jí)來(lái)刻意訓(xùn)練——從“能跑通”到“寫(xiě)得穩(wěn)”再到“設(shè)計(jì)得好”。整個(gè)計(jì)劃的核心目的只有一個(gè)把小白的“抄代碼”習(xí)慣升級(jí)成能獨(dú)立解決實(shí)際問(wèn)題的工程能力。這個(gè)內(nèi)容適合三類(lèi)人剛學(xué)完語(yǔ)法但不知道怎么下手做項(xiàng)目的新手、能寫(xiě)功能但代碼總被人說(shuō)“不夠好”的初中級(jí)開(kāi)發(fā)者以及想帶新人但苦于沒(méi)有系統(tǒng)訓(xùn)練方案的團(tuán)隊(duì)負(fù)責(zé)人。我把從立項(xiàng)到落地的完整思路、訓(xùn)練方法、踩坑記錄都整理出來(lái)了盡量做到每個(gè)人看完都能照著搭一套自己的版本。1. 項(xiàng)目整體設(shè)計(jì)與思路拆解1.1 為什么叫 t3code三層能力模型怎么來(lái)的先說(shuō)第一個(gè)問(wèn)題為什么不是“t1code”“t2code”而是 t3。起因其實(shí)很樸素。我在實(shí)際帶人和面試的過(guò)程中發(fā)現(xiàn)大多數(shù)開(kāi)發(fā)者的代碼能力問(wèn)題不是單點(diǎn)缺失而是結(jié)構(gòu)性斷層。有的人語(yǔ)法滾瓜爛熟但一接到需求就開(kāi)始慌有的人框架用得很溜但遇到?jīng)]見(jiàn)過(guò)的場(chǎng)景就完全沒(méi)思路還有的人能解決問(wèn)題但代碼質(zhì)量全憑心情別人根本沒(méi)法維護(hù)。所以我把“代碼能力”拆成了三個(gè)可獨(dú)立訓(xùn)練、又有先后依賴(lài)的層級(jí)T1語(yǔ)法與調(diào)試基礎(chǔ)層能讀懂代碼、寫(xiě)出可運(yùn)行的代碼遇到報(bào)錯(cuò)能獨(dú)立定位。T2工程與框架應(yīng)用層能組織代碼結(jié)構(gòu)、接入第三方依賴(lài)、配合團(tuán)隊(duì)協(xié)作。T3設(shè)計(jì)思維與架構(gòu)層能對(duì)問(wèn)題建模、做技術(shù)選型、設(shè)計(jì)出可擴(kuò)展的方案。這個(gè)模型是我對(duì)“會(huì)寫(xiě)代碼”這件事的重新定義。它參考了學(xué)習(xí)領(lǐng)域的“技能分層”理論也和計(jì)算機(jī)教育里“程序構(gòu)造”的思路一脈相承但做了更適合工程實(shí)踐的簡(jiǎn)化和落地。有了這個(gè)模型整個(gè) t3code 項(xiàng)目的訓(xùn)練體系就有了骨架——每一層對(duì)應(yīng)明確的訓(xùn)練模塊、產(chǎn)出物和過(guò)關(guān)標(biāo)準(zhǔn)而不是籠統(tǒng)地說(shuō)“多寫(xiě)多練”。1.2 三層結(jié)構(gòu)背后的核心邏輯很多人會(huì)問(wèn)分層訓(xùn)練和平時(shí)自己學(xué)有什么本質(zhì)區(qū)別區(qū)別在于“反饋的針對(duì)性”。初學(xué)者最常見(jiàn)的誤區(qū)是遇到一個(gè)問(wèn)題就懷疑自己全都很差然后從頭到尾復(fù)習(xí)一遍浪費(fèi)時(shí)間還挫敗感強(qiáng)。分層之后問(wèn)題可以被準(zhǔn)確定位——是語(yǔ)法不熟還是工程結(jié)構(gòu)不清楚抑或是建模能力不足修起來(lái)就有了方向。打個(gè)比方這就像學(xué)羽毛球。如果你的揮拍動(dòng)作有問(wèn)題光靠天天打比賽是糾正不了的必須回到基礎(chǔ)動(dòng)作做專(zhuān)項(xiàng)訓(xùn)練。代碼能力也一樣。語(yǔ)法不熟的時(shí)代去讀再多設(shè)計(jì)模式的書(shū)都是空中樓閣工程能力沒(méi)建立的時(shí)候硬去啃架構(gòu)也只會(huì)學(xué)到一堆名詞。t3code 的訓(xùn)練路徑嚴(yán)格遵循“先下后上”的原則T1 沒(méi)過(guò)關(guān)不進(jìn)入 T2T2 的產(chǎn)出物達(dá)不到質(zhì)量線也不碰 T3 的內(nèi)容。這不是為了卡進(jìn)度而是我實(shí)踐中發(fā)現(xiàn)跨層訓(xùn)練的效率極低。比如讓一個(gè)連 Ant Design 組件都還不熟的前端新人直接去畫(huà)系統(tǒng)架構(gòu)圖畫(huà)出來(lái)的東西大概率沒(méi)法落地還會(huì)打擊自信。2. 核心細(xì)節(jié)解析與實(shí)操要點(diǎn)2.1 T1 階段不是學(xué)語(yǔ)法是訓(xùn)練“調(diào)試反應(yīng)速度”T1 階段的訓(xùn)練目標(biāo)很明確拿到一段代碼能讀懂它在做什么自己寫(xiě)一個(gè)功能能在合理時(shí)間內(nèi)調(diào)通。但它不是傳統(tǒng)意義上的“學(xué)語(yǔ)法課”而是刻意訓(xùn)練兩件事——讀代碼的速度和調(diào)試的直覺(jué)。我在 t3code 里給 T1 設(shè)計(jì)了三個(gè)固定動(dòng)作。第一個(gè)是“逐行注釋”每天找一段 100 行以?xún)?nèi)的開(kāi)源代碼或項(xiàng)目?jī)?nèi)代碼不遺漏每一條語(yǔ)句地寫(xiě)注釋寫(xiě)清楚這一行做了什么、為什么要寫(xiě)這一行。第二個(gè)是“報(bào)錯(cuò)復(fù)盤(pán)”每次遇到 bug不許直接改代碼必須先把報(bào)錯(cuò)信息、猜測(cè)原因、驗(yàn)證路徑寫(xiě)進(jìn)一個(gè)文檔里然后才動(dòng)手修。第三個(gè)是“計(jì)時(shí)重寫(xiě)”挑一個(gè)小功能先正常寫(xiě)一遍隔半小時(shí)后關(guān)掉原文件靠記憶和思路重新寫(xiě)對(duì)比兩次的差異。這三個(gè)動(dòng)作背后的道理其實(shí)很樸素。我現(xiàn)實(shí)中見(jiàn)過(guò)太多人代碼寫(xiě)不出來(lái)就去看答案看懂了就覺(jué)得自己會(huì)了等到自己動(dòng)手時(shí)還是空白。T1 真正的過(guò)關(guān)標(biāo)準(zhǔn)不是“能寫(xiě)出某個(gè)練習(xí)題”而是“拿到一個(gè)沒(méi)見(jiàn)過(guò)的 bug能獨(dú)立地用二分法縮小定位范圍”。二分法怎么練就是每次報(bào)錯(cuò)只查一個(gè)變量、只改一處代碼不許一次猜三處。這個(gè)習(xí)慣我在 T1 階段反復(fù)強(qiáng)調(diào)因?yàn)樗呛竺嫠泄こ棠芰Φ牡鬃?.2 T2 階段從寫(xiě)“功能”到寫(xiě)“工程”T2 階段解決的核心矛盾是“功能能跑”和“工程可維護(hù)”之間的距離。很多開(kāi)發(fā)者寫(xiě)代碼時(shí)只關(guān)注當(dāng)前需求不考慮別人怎么看、以后怎么改結(jié)果一周后自己看自己的代碼都費(fèi)勁。T2 階段我引入了一個(gè)強(qiáng)制約束所有訓(xùn)練項(xiàng)目都必須包含 README、目錄結(jié)構(gòu)設(shè)計(jì)、接口文檔這三樣?xùn)|西缺一不可。目錄結(jié)構(gòu)設(shè)計(jì)是整個(gè) T2 階段最值得花時(shí)間的部分。我的訓(xùn)練要求是接到一個(gè)新需求時(shí)先別急著寫(xiě)第一個(gè)函數(shù)而是花 20% 的時(shí)間設(shè)計(jì)代碼放哪里。組件往 components 放業(yè)務(wù)邏輯抽 hooks 或 services配置集中到 config公共類(lèi)型集中到 types——這些寫(xiě)在任何公司規(guī)范里的內(nèi)容只有親手拆過(guò)、重寫(xiě)過(guò)、經(jīng)歷過(guò)后才會(huì)真正長(zhǎng)在自己身上。框架選型也是 T2 的核心話題。我見(jiàn)過(guò)太多人做小項(xiàng)目時(shí)選了一個(gè)“很潮但很重”的技術(shù)棧結(jié)果花了大量時(shí)間處理框架本身的問(wèn)題而不是業(yè)務(wù)問(wèn)題。t3code 在 T2 階段的選型原則只有一條團(tuán)隊(duì)內(nèi)已經(jīng)有人熟練使用、社區(qū)案例夠多、你能找到足夠參考資料的優(yōu)先。把“喜歡”放在“熟悉”前面是新手做技術(shù)選型最容易踩的坑后面具體問(wèn)題章節(jié)里我會(huì)展開(kāi)說(shuō)。2.3 T3 階段建模能力和“刪代碼”的勇氣到了 T3 階段重點(diǎn)已經(jīng)不在代碼本身而在代碼之前的設(shè)計(jì)。我給 T3 定的訓(xùn)練主題是“建模與取舍”。具體來(lái)說(shuō)是拿到一個(gè)模糊需求后先把它轉(zhuǎn)化為清晰的數(shù)據(jù)模型和狀態(tài)流轉(zhuǎn)模型再做技術(shù)方案設(shè)計(jì)。這個(gè)階段的實(shí)操要求很特別設(shè)計(jì)一個(gè)方案時(shí)必須同時(shí)給出兩版以上的備選方案并寫(xiě)一份簡(jiǎn)單的對(duì)比文檔。對(duì)比維度包括實(shí)現(xiàn)成本、維護(hù)風(fēng)險(xiǎn)、擴(kuò)展性、團(tuán)隊(duì)熟悉度。為什么必須寫(xiě)文檔因?yàn)榭陬^說(shuō)“我覺(jué)得可以”很容易但寫(xiě)成文字要面對(duì)的是邏輯漏洞和不嚴(yán)謹(jǐn)?shù)谋硎?。這個(gè)習(xí)慣幫我在真實(shí)項(xiàng)目里避了很多雷比如有一次我本來(lái)想用一套很“優(yōu)雅”的微服務(wù)方案寫(xiě)對(duì)比文檔時(shí)發(fā)現(xiàn)維護(hù)成本完全劃不來(lái)最后老老實(shí)實(shí)合并成了一個(gè)模塊。T3 還有另一個(gè)訓(xùn)練叫“刪代碼”。每隔一段時(shí)間強(qiáng)制自己刪掉一個(gè)模塊的舊實(shí)現(xiàn)用更簡(jiǎn)介的重構(gòu)思路重新實(shí)現(xiàn)并且保證功能不變。這個(gè)訓(xùn)練聽(tīng)著很反直覺(jué)但特別有用。它能逼著你審視當(dāng)初那些“當(dāng)時(shí)趕進(jìn)度先這么寫(xiě)”的爛賬也能鍛煉你對(duì)代碼的“所有權(quán)意識(shí)”——敢于動(dòng)自己的代碼才談得上掌控代碼。2.4 三個(gè)階段的過(guò)關(guān)標(biāo)準(zhǔn)與核心產(chǎn)出物為了讓訓(xùn)練不流于形式t3code 給每個(gè)階段都設(shè)定了明確產(chǎn)出物和過(guò)關(guān)標(biāo)準(zhǔn)。我在執(zhí)行的時(shí)候每個(gè)階段都用一個(gè)表格盯進(jìn)度這里分享給大家可以直接照著用。階段核心訓(xùn)練產(chǎn)出物過(guò)關(guān)標(biāo)準(zhǔn)預(yù)計(jì)周期T1100 段逐行注釋筆記、30 份報(bào)錯(cuò)復(fù)盤(pán)文檔能在 20 分鐘內(nèi)獨(dú)立定位一個(gè)陌生模塊的 bug4~6 周T23 個(gè)完整小項(xiàng)目含 README、結(jié)構(gòu)設(shè)計(jì)、接口文檔新需求的代碼結(jié)構(gòu)不需要讓別人幫忙“搬文件”6~8 周T32 個(gè)設(shè)計(jì)對(duì)比文檔、1 個(gè)重構(gòu)復(fù)盤(pán)報(bào)告面對(duì)模糊需求能獨(dú)立給出帶取舍依據(jù)的技術(shù)方案持續(xù)進(jìn)行我自己執(zhí)行的時(shí)候每個(gè)階段都要把產(chǎn)出物給其他伙伴過(guò)目讓他們挑毛病。沒(méi)有外部視角的過(guò)關(guān)都是自嗨這一點(diǎn)在新手剛開(kāi)始訓(xùn)練時(shí)尤其致命。3. 實(shí)操過(guò)程與核心環(huán)節(jié)實(shí)現(xiàn)3.1 完整實(shí)操流程一個(gè)從零到一的項(xiàng)目周期t3code 的完整實(shí)操流程我一般分成五步走每一步都有明確的出口條件。第一步是“定靶子”也就是選一個(gè)訓(xùn)練用的真實(shí)項(xiàng)目。我的建議是千萬(wàn)別選“網(wǎng)上爛大街的電商系統(tǒng)”要選你自己真正有需求的東西。比如我當(dāng)時(shí)選了一個(gè)自己用的家庭記賬工具需求非常明確又不會(huì)有“抄標(biāo)準(zhǔn)答案”的空間。第二步是“設(shè)計(jì)草稿”動(dòng)手畫(huà)頁(yè)面草圖、列功能清單、定義核心數(shù)據(jù)表結(jié)構(gòu)。這一步對(duì)應(yīng)的是三層模型里的設(shè)計(jì)思維部分。第三步才是“搭骨架”初始化項(xiàng)目、搭好目錄結(jié)構(gòu)、配好開(kāi)發(fā)環(huán)境。第四步是“塞功能”按優(yōu)先級(jí)逐步實(shí)現(xiàn)每一個(gè)功能點(diǎn)每完成一個(gè)就提交一次代碼。第五步是“復(fù)盤(pán)重構(gòu)”把整個(gè)項(xiàng)目回看一遍找出冗余邏輯和結(jié)構(gòu)不合理的地方動(dòng)手重構(gòu)。這個(gè)流程看起來(lái)平平無(wú)奇但它把傳統(tǒng)“想到哪寫(xiě)到哪”的開(kāi)發(fā)方式徹底扭轉(zhuǎn)了。我見(jiàn)過(guò)太多新手寫(xiě)項(xiàng)目第一天就開(kāi)寫(xiě)寫(xiě)到一半發(fā)現(xiàn)結(jié)構(gòu)不對(duì)全部推翻然后心態(tài)爆炸。按照這個(gè)流程走至少能保證每一步都有確定的產(chǎn)出不會(huì)因?yàn)橹型久月范速M(fèi)大量時(shí)間。3.2 參數(shù)計(jì)算與選擇過(guò)程以訓(xùn)練周期和每日投入設(shè)計(jì)為例很多人會(huì)問(wèn)t3code 每天要花多少時(shí)間訓(xùn)練周期怎么定我在這里說(shuō)一個(gè)計(jì)算公式按“有效編碼時(shí)間”而不是“坐在電腦前的時(shí)間”來(lái)算。有效編碼時(shí)間 每天實(shí)際產(chǎn)出代碼或文檔的時(shí)間排除了刷視頻、查無(wú)關(guān)資料、發(fā)呆的時(shí)間。我制定計(jì)劃的基準(zhǔn)是每周有效編碼時(shí)間不低于 12 小時(shí)否則 T1 階段會(huì)被拉得很長(zhǎng)。舉個(gè)例子假設(shè)你每天能保證 2 小時(shí)有效編碼時(shí)間每周就是 14 小時(shí)。T1 階段需要完成 100 段逐行注釋和 30 份報(bào)錯(cuò)復(fù)盤(pán)按經(jīng)驗(yàn)平均每段注釋約 15 分鐘、每份復(fù)盤(pán)約 30 分鐘來(lái)看大概需要 100×0.25 30×0.5 40 小時(shí)。代入每周 14 小時(shí)就是大約 3 周。但因?yàn)檫€要穿插實(shí)際編程練習(xí)所以我一般會(huì)留一倍余量把計(jì)劃定到 5~6 周。這個(gè)計(jì)算的意義在于讓訓(xùn)練目標(biāo)變成可量化、可調(diào)整的工程計(jì)劃而不是“我最近要加油學(xué)編程”這種口號(hào)。我還會(huì)在每個(gè)周末做一次“偏差分析”算一算實(shí)際投入時(shí)間和計(jì)劃差多少是因?yàn)榧影噙€是因?yàn)榉中南轮茉趺囱a(bǔ)。這套時(shí)間管理的方法本身也是工程能力的實(shí)戰(zhàn)訓(xùn)練。3.3 實(shí)操現(xiàn)場(chǎng)記錄一個(gè)典型的 t3code 周末訓(xùn)練日我這里記錄一個(gè)具體的周末訓(xùn)練日讓大家感受一下 t3code 實(shí)際執(zhí)行起來(lái)是什么狀態(tài)。上午 9 點(diǎn)到 12 點(diǎn)我拿出一個(gè)向外開(kāi)源組件庫(kù)的源碼挑了一個(gè) 300 行左右的表單組件做逐行注釋訓(xùn)練。這個(gè)過(guò)程中發(fā)現(xiàn)了幾個(gè)平時(shí)沒(méi)注意的細(xì)節(jié)比如組件內(nèi)部對(duì)輸入值做剪裁的邊界處理這在普通業(yè)務(wù)代碼里幾乎不會(huì)自己主動(dòng)寫(xiě)。下午 2 點(diǎn)到 4 點(diǎn)進(jìn)入報(bào)錯(cuò)復(fù)盤(pán)環(huán)節(jié)。當(dāng)時(shí)在做記賬工具的標(biāo)簽篩選功能接口一直返回?cái)?shù)據(jù)格式不對(duì)。我沒(méi)有直接去改代碼而是先寫(xiě)了一段猜測(cè)是不是時(shí)間字段在傳輸中被轉(zhuǎn)成 UTC 格式了接著通過(guò)打印日志拿到服務(wù)端實(shí)際返回的原始數(shù)據(jù)確認(rèn)了時(shí)間字段被序列化時(shí)丟失了時(shí)區(qū)信息。整個(gè)定位過(guò)程花了約 40 分鐘比直接瞎改快多了。下午 4 點(diǎn)到 6 點(diǎn)做的是 T3 階段的“刪代碼”訓(xùn)練。我重構(gòu)了記賬工具里分類(lèi)統(tǒng)計(jì)模塊的邏輯把原來(lái) 200 多行重復(fù)的聚合代碼刪到 80 行用了幾個(gè)通用的地圖函數(shù)抽象掉重復(fù)邏輯。重構(gòu)完后跑了一遍全量測(cè)試用例確認(rèn)功能沒(méi)有回退。這個(gè)訓(xùn)練日下來(lái)產(chǎn)出物包括一份注釋筆記、一份復(fù)盤(pán)文檔、一次重構(gòu)記錄獲得感非常實(shí)。3.4 工具鏈配置建議把環(huán)境搭建在“可復(fù)現(xiàn)”的基礎(chǔ)上t3code 這個(gè)項(xiàng)目要想順利跑下去工具鏈的配置很關(guān)鍵。我的建議是三件套Git 做版本管理、Taskfile 或腳本做任務(wù)自動(dòng)化、Markdown 做文檔沉淀。這三樣?xùn)|西對(duì)應(yīng)的都是真實(shí)工作流里每天都在用的能力但很多自學(xué)的人很容易跳過(guò)去。Git 我這里單獨(dú)強(qiáng)調(diào)一下。t3code 要求每次訓(xùn)練都必須提交 commit而且 commit message 必須寫(xiě)清楚“我為什么要改這個(gè)”。這不僅僅是習(xí)慣問(wèn)題它強(qiáng)迫你在寫(xiě)完每一段代碼之后做一個(gè)簡(jiǎn)短的回顧這段代碼的出現(xiàn)是為了解決什么問(wèn)題有太多人寫(xiě)代碼是“寫(xiě)完了就忘了上一秒在想什么”有了提交記錄你回頭看的時(shí)候就能搞清楚自己的思路演進(jìn)過(guò)程。環(huán)境搭建還涉及一個(gè)很多人忽略的點(diǎn)依賴(lài)管理的可復(fù)現(xiàn)性。我建議每個(gè)訓(xùn)練項(xiàng)目從第一天就使用鎖文件管理依賴(lài)版本無(wú)論你用的是 npm、pip 還是 Go Modules。這能避免一個(gè)經(jīng)典尷尬——三周后打開(kāi)自己的項(xiàng)目發(fā)現(xiàn)跑不起來(lái)了因?yàn)槟硞€(gè)依賴(lài)悄悄升級(jí)了大版本。給自己搭一個(gè)好環(huán)境本身就是這個(gè)項(xiàng)目訓(xùn)練內(nèi)容的一部分。4. 常見(jiàn)問(wèn)題與排查技巧實(shí)錄4.1 問(wèn)題一每天都很忙訓(xùn)練計(jì)劃總是被打斷怎么辦這是我收到過(guò)最多的求助。上班的人加班頻繁上課的人有課業(yè)壓力每天 2 小時(shí)的有效編程時(shí)間對(duì)很多人來(lái)說(shuō)確實(shí)是奢求。我的處理辦法是給計(jì)劃增加“彈性保護(hù)”規(guī)則每周有效編碼時(shí)間的底線是 8 小時(shí)只要不連續(xù)兩周低于這個(gè)線計(jì)劃順延而不是取消。實(shí)際操作中我還會(huì)把訓(xùn)練單元拆到“30 分鐘一檔”。比如 30 分鐘可以做半段逐行注釋、10 分鐘可以寫(xiě)一份報(bào)錯(cuò)復(fù)盤(pán)的提綱、20 分鐘可以畫(huà)一張數(shù)據(jù)結(jié)構(gòu)草圖。不要小看碎片時(shí)間的積累我統(tǒng)計(jì)過(guò)碎片時(shí)間加起來(lái)經(jīng)常比整塊時(shí)間還多。關(guān)鍵在于把訓(xùn)練內(nèi)容做成“開(kāi)箱即用”的最小單元而不是一定要等一個(gè)完整的下午才動(dòng)手。4.2 問(wèn)題二學(xué)了就忘練過(guò)的內(nèi)容過(guò)兩周就模糊了遺忘問(wèn)題分兩種。一種是練得不夠深大腦覺(jué)得不重要自然就丟了。另一種是缺少“提取練習(xí)”——你只是在重復(fù)輸入沒(méi)有主動(dòng)回憶和應(yīng)用。針對(duì)第一種我調(diào)整了訓(xùn)練密度每個(gè)知識(shí)點(diǎn)必須在三個(gè)不同的訓(xùn)練任務(wù)里出現(xiàn)才算通過(guò)針對(duì)第二種我在 t3code 里加了“隨機(jī)抽查”機(jī)制每周隨機(jī)挑一個(gè)已經(jīng)過(guò)完關(guān)的舊知識(shí)點(diǎn)現(xiàn)場(chǎng)做一個(gè)小題或口頭解釋。這里有個(gè)很容易被忽略的現(xiàn)象大量遺忘發(fā)生在“學(xué)會(huì)”之后的第一周。所以我的抽查規(guī)則特別設(shè)置了“1 周后必查”。具體做法是每周日把本周學(xué)過(guò)、但本周確定不再使用的三個(gè)知識(shí)點(diǎn)列出來(lái)對(duì)著空白文檔默寫(xiě)一遍思路。這比臨到面試前再突擊效果好出一個(gè)數(shù)量級(jí)。4.3 問(wèn)題三我知道要結(jié)構(gòu)化但一寫(xiě)代碼還是控制不住亂寫(xiě)這個(gè)問(wèn)題非常典型也很真實(shí)。其實(shí)問(wèn)題不是你不會(huì)結(jié)構(gòu)化而是你在動(dòng)手時(shí)沒(méi)有給“結(jié)構(gòu)化”留出強(qiáng)制空間。我的解法是用“先寫(xiě)計(jì)劃后寫(xiě)碼”的硬規(guī)則每個(gè)功能開(kāi)工前先在文檔里寫(xiě)一個(gè)關(guān)于文件組織、函數(shù)拆分和接口設(shè)計(jì)的小計(jì)劃然后才能寫(xiě)代碼。我自己寫(xiě)代碼時(shí)發(fā)現(xiàn)這個(gè)計(jì)劃大約占 10 分鐘但它能幫我省掉之后至少半小時(shí)的重命名和搬文件時(shí)間。另外一個(gè)小技巧是“命名即設(shè)計(jì)”。每次給變量、函數(shù)命名都要在一個(gè)句子里說(shuō)清楚它是干什么的如果一句話說(shuō)不清楚多半設(shè)計(jì)有問(wèn)題。比如“handleValue”這個(gè)名字就非常糟糕因?yàn)楦墒裁吹亩紱](méi)說(shuō)出來(lái)改成“parseAmountWithPrecision”一下就清楚了。這種小技巧看似不起眼積累起來(lái)就是工程代碼和玩具代碼的最大區(qū)別。4.4 問(wèn)題四遇到卡住忍不住想搜答案怎么辦卡住時(shí)搜答案是人之常情但我在訓(xùn)練中給自己立了一個(gè)規(guī)矩必須先有“已嘗試記錄”才能去搜。也就是把已經(jīng)試過(guò)的方案寫(xiě)出來(lái)一條條列清楚再把問(wèn)題描述精確到某一個(gè)函數(shù)、某一個(gè)報(bào)錯(cuò)。這其實(shí)就是值得一提的“橡皮鴨調(diào)試法”的延伸——向別人求助前先把問(wèn)題講給一個(gè)假想的同事聽(tīng)。很多時(shí)候講著講著答案自己就冒出來(lái)了。如果講完還是沒(méi)頭緒再去搜答案此時(shí)的收益也是不一樣的。因?yàn)槟隳X子里已經(jīng)有一個(gè)問(wèn)題模型看到別人的解決方案時(shí)能分辨出思路差異在哪里而不是單純的“復(fù)制 - 粘貼 - 跑通 - 忘了”。我發(fā)現(xiàn)帶著問(wèn)題模型去閱讀資料記的深度完全不一樣。5. 避坑總結(jié)與效率提升技巧5.1 三個(gè)容易讓項(xiàng)目前功盡棄的坑第一個(gè)坑是“理論收集癥”。有人學(xué)設(shè)計(jì)模式把每種模式的 UML 圖畫(huà)得漂漂亮亮但從未在一個(gè)真實(shí)項(xiàng)目里用過(guò)其中三個(gè)以上。t3code 的規(guī)則是凡是沒(méi)在代碼里寫(xiě)過(guò)二十遍以上的概念都不算學(xué)過(guò)。設(shè)計(jì)模式、算法、函數(shù)式技巧一律以代碼量和重構(gòu)次數(shù)為準(zhǔn)。第二個(gè)坑是“單一訓(xùn)練過(guò)度”。連續(xù)兩周只做逐行注釋不做實(shí)際功能開(kāi)發(fā)會(huì)導(dǎo)致手生。我的節(jié)奏是訓(xùn)練日里開(kāi)發(fā)與練習(xí)的比例保持在 3:2開(kāi)發(fā)是主節(jié)奏專(zhuān)項(xiàng)練習(xí)是穿插的輔奏。第三個(gè)坑是“復(fù)盤(pán)形式化”。復(fù)盤(pán)如果只是把代碼重看一遍效率非常低。真正有用的復(fù)盤(pán)要回答三個(gè)問(wèn)題這里為什么寫(xiě)得繞我當(dāng)時(shí)的錯(cuò)誤假設(shè)是什么如果重來(lái)一次我會(huì)在哪一步停下來(lái)重新思考分析“當(dāng)時(shí)決策的心智過(guò)程”比分析代碼本身更有價(jià)值。5.2 進(jìn)一步提升效率的三個(gè)技巧給我?guī)?lái)最大效率提升的技巧是“批量刻意練習(xí)”。比如想搞懂閉包就找 20 道閉包相關(guān)的小練習(xí)在一個(gè)半天里集中做完而不是每天做一兩道、連著做兩周。批量練習(xí)能讓大腦形成對(duì)同一模式的強(qiáng)記憶效果和“少量多餐”完全不同。第二個(gè)技巧是“公開(kāi)輸出”。t3code 訓(xùn)練過(guò)程中我產(chǎn)出的筆記、復(fù)盤(pán)文檔、設(shè)計(jì)對(duì)比整理之后發(fā)到了技術(shù)社區(qū)。為了讓外人看懂我被迫補(bǔ)充了大量背景信息、術(shù)語(yǔ)解釋和思路推導(dǎo)這些補(bǔ)充過(guò)程本身就是很好的二次學(xué)習(xí)。而且讀者的提問(wèn)還能提供新的反饋角度。第三個(gè)技巧是“結(jié)對(duì)互評(píng)”。找一個(gè)同樣在訓(xùn)練的朋友每周互相檢查一次對(duì)方的訓(xùn)練產(chǎn)出物。自己看自己的代碼總有盲區(qū)但看別人的代碼卻能一眼發(fā)現(xiàn)結(jié)構(gòu)問(wèn)題?;ピu(píng)不需要兩個(gè)人水平一樣教學(xué)相長(zhǎng)的效果在“你發(fā)現(xiàn)他有問(wèn)題”的過(guò)程中就產(chǎn)生了。5.3 t3code 的后續(xù)擴(kuò)展思路t3code 這套三層能力模型其實(shí)不只適用于個(gè)人開(kāi)發(fā)者。我和團(tuán)隊(duì)小伙伴試過(guò)把它改造成新人入職的“成長(zhǎng)導(dǎo)航”把勝任力模型換成 t3 層級(jí)每個(gè)新成員入職第一個(gè)月按 T1 標(biāo)準(zhǔn)帶教第二個(gè)月開(kāi)始走 T2 項(xiàng)目效果比傳統(tǒng)“丟到項(xiàng)目里自生自滅”好很多。它本質(zhì)上是一個(gè)訓(xùn)練理念而不是一個(gè)固定課程。后面我又在考慮把每個(gè)層級(jí)細(xì)分成“語(yǔ)言無(wú)關(guān)”和“語(yǔ)言相關(guān)”兩條線。比如 T1 里調(diào)試能力是通用的但瀏覽器調(diào)試器和后端斷點(diǎn)調(diào)試的工具操作細(xì)節(jié)并不一樣T3 里領(lǐng)域建模的思路是相通的但不同業(yè)務(wù)領(lǐng)域的建模套路各有差異。這個(gè)細(xì)化還沒(méi)有完全跑通如果后面有進(jìn)展我再來(lái)補(bǔ)充。說(shuō)實(shí)話t3code 到現(xiàn)在也談不上什么了不起的項(xiàng)目它只是一套樸素的訓(xùn)練框架。最值錢(qián)的不是框架本身而是“把混沌的能力目標(biāo)拆成可執(zhí)行動(dòng)作”這件事。拆解出來(lái)的每個(gè)動(dòng)作單獨(dú)看都簡(jiǎn)單得可笑但組合在一起并連續(xù)執(zhí)行三個(gè)月后我發(fā)現(xiàn)它把很多曾經(jīng)覺(jué)得“很玄”的事情變成了“按步驟做就好了”的日常。如果你也在糾結(jié)自己為什么寫(xiě)了三年代碼還在原地踏步不妨也試著把自己的能力拆成三到四層然后只盯著最底層那個(gè)問(wèn)題修先修一個(gè)月看看。