拆解為可驗(yàn)證的小步交付)
今天我們來看一個(gè)和“能不能按時(shí)把事做完”直接相關(guān)的方法論Getting things done (in small increments)2022。這個(gè)主題說的不是讓你用更復(fù)雜的時(shí)間管理軟件也不是堆一堆待辦清單而是先把“完成一件事”的方式改掉讓每一步都足夠小、可以驗(yàn)證、可以快速拿到反饋。對于經(jīng)常寫代碼、做批量任務(wù)、維護(hù)倉庫、寫文檔的人來說這套思路最直接的價(jià)值在于你不再需要一口氣憋出幾十個(gè)文件、一個(gè)大改動(dòng)、一次長周期交付而是把最終目標(biāo)拆成若干個(gè)小塊每一塊都能獨(dú)立推進(jìn)、獨(dú)立驗(yàn)證、甚至獨(dú)立發(fā)布。這正好對應(yīng)技術(shù)團(tuán)隊(duì)里常見的小步提交、持續(xù)集成、灰度發(fā)布也和任務(wù)批量處理中的“小批驗(yàn)證”邏輯一致。這篇文章會(huì)把“小增量”拆開講清楚為什么大任務(wù)常常做不完小增量到底小到什么程度怎么拆怎么用工具輔助怎么驗(yàn)證自己確實(shí)在推進(jìn)。如果你正在被長周期任務(wù)、無限拖延、倉庫里長期不合并的分支、批量任務(wù)一次跑完才報(bào)錯(cuò)這些問題困擾這篇值得讀完。1. 核心思路速覽先把這套方法論的規(guī)格擺出來方便快速判斷適不適合你。維度說明方法論類型任務(wù)執(zhí)行、工程效率、項(xiàng)目管理實(shí)踐核心原則小步拆解、可驗(yàn)證成果、短反饋循環(huán)適用對象開發(fā)者、運(yùn)維、研究測試人員、內(nèi)容生產(chǎn)者、技術(shù)管理者主要工具Git、終端、任務(wù)追蹤工具、輕量腳本學(xué)習(xí)成本低核心概念當(dāng)天可以上手硬件需求無普通開發(fā)機(jī)即可見效周期通常數(shù)天到數(shù)周取決于執(zhí)行頻率主要風(fēng)險(xiǎn)任務(wù)拆得不夠小、驗(yàn)證標(biāo)準(zhǔn)缺失、反饋周期太長這里的“工具”不需要指定某個(gè)特定產(chǎn)品。你用 Obsidian、Notion、Todoist、GitHub Projects、Excel、甚至一張 Markdown 清單都可以關(guān)鍵是執(zhí)行節(jié)奏要符合“小增量”三個(gè)特征每個(gè)任務(wù)單元在 1 到 4 小時(shí)內(nèi)可以完成一個(gè)可驗(yàn)證成果。每完成一個(gè)單元不需要等待其他單元也能確認(rèn)“這個(gè)部分確實(shí)有效”。每個(gè)單元之間有清晰的先后依賴關(guān)系不會(huì)越做越亂。2. 為什么“一次性做大任務(wù)”往往做不成技術(shù)工作里最常見的失敗模式不是能力不夠而是任務(wù)粒度太大。大任務(wù)會(huì)帶來四個(gè)問題。第一是認(rèn)知負(fù)荷。一個(gè)任務(wù)包含太多步驟時(shí)大腦很難在開始前把狀態(tài)完整加載出來。你會(huì)有“不知道從哪里動(dòng)手”的感覺于是一直反復(fù)讀資料、一直準(zhǔn)備環(huán)境、一直拖延。這是開發(fā)者在長周期需求上最常見的卡點(diǎn)。第二是心理阻力。一個(gè)需要兩周才能完成的功能每次打開編輯器都像面對一座山。而小步推進(jìn)只需要你面對一個(gè)明確的、短期的、可交付的小塊心理負(fù)擔(dān)會(huì)明顯降低。第三是反饋延遲。大任務(wù)往往要等全部做完才能看到效果。如果某個(gè)底層假設(shè)錯(cuò)了你要到最后一個(gè)星期才發(fā)現(xiàn)返工成本極高。小增量則會(huì)在最早時(shí)間暴露問題因?yàn)槊總€(gè)單元都會(huì)經(jīng)過驗(yàn)證。第四是上下文切換成本。做長周期任務(wù)時(shí)你可能同時(shí)維護(hù)多個(gè)未完成線每次切回來都要重新回憶。小步提交配合清晰記錄能大幅減少這種“重新加載狀態(tài)”的開銷。技術(shù)領(lǐng)域里的具體表現(xiàn)很典型一個(gè)倉庫里長期不合并的大分支、一次生成幾百個(gè)文件后才發(fā)現(xiàn)批量任務(wù)的某個(gè)參數(shù)全錯(cuò)、一篇技術(shù)文章攢到全部寫完才給同學(xué)看結(jié)果結(jié)果方向偏了。這些都是“不必要地放大任務(wù)粒度”的代價(jià)。3. 小增量方法論的核心概念小增量不是說把任務(wù)“碎片化”。碎片化是沒有邏輯地切分而小增量是按照“可驗(yàn)證成果”來切分。一個(gè)任務(wù)單元由幾個(gè)部分組成組成部分作用示例目標(biāo)描述說明這個(gè)單元完成后能得到什么完成批量圖片壓縮腳本輸入條件明確依賴什么才能開始已有待處理圖片目錄、壓縮工具已安裝執(zhí)行步驟具體的操作路徑讀取目錄、逐張壓縮、輸出到新目錄驗(yàn)收標(biāo)準(zhǔn)證明這個(gè)單元成功的證據(jù)壓縮后圖片體積平均下降 60%清晰度可用反饋方式誰、用什么方式確認(rèn)完成本地運(yùn)行腳本查看輸出日志關(guān)鍵區(qū)別在于驗(yàn)收標(biāo)準(zhǔn)必須是可執(zhí)行、可觀察的而不是“感覺差不多”。下面是一個(gè)適用性很廣的任務(wù)拆解模板# 任務(wù)XXX ## 小增量 1準(zhǔn)備和驗(yàn)證環(huán)境 - 目標(biāo)確認(rèn)本機(jī)能跑通最小示例 - 輸入開發(fā)環(huán)境已安裝、示例數(shù)據(jù)已下載 - 步驟 1. 按官方文檔安裝依賴 2. 運(yùn)行官方示例 - 驗(yàn)收示例輸出結(jié)果與文檔一致 - 負(fù)責(zé)人 ## 小增量 2實(shí)現(xiàn)最小處理邏輯 - 目標(biāo)對單個(gè)輸入執(zhí)行核心處理邏輯 - 輸入一份測試素材 - 步驟 1. 編寫核心函數(shù) 2. 用單條輸入跑通 - 驗(yàn)收單條輸入輸出符合預(yù)期 ## 小增量 3擴(kuò)展到批量處理 - 目標(biāo)對目錄內(nèi)全部輸入執(zhí)行批量處理 - 輸入小批量測試數(shù)據(jù)10 個(gè)文件以內(nèi) - 步驟 1. 循環(huán)調(diào)用核心函數(shù) 2. 記錄失敗項(xiàng) - 驗(yàn)收批量運(yùn)行成功失敗項(xiàng)有日志代碼版本管理里小步提交的核心則是“一次提交只做一件事”。一個(gè)典型的提交信息模板# 模板type(scope): description git commit -m feat(compress): add batch image compression如果你發(fā)現(xiàn)一次提交里既有“修復(fù)壓縮算法”又有“調(diào)整界面布局”又有“修改配置文件”這就是典型的提交粒度問題。4. 把方法論落到日常技術(shù)工作和內(nèi)容生產(chǎn)中不同的工作類型小增量的拆法不同。但是底層邏輯都一樣從結(jié)果反推最近一個(gè)可驗(yàn)證的節(jié)點(diǎn)然后只做這個(gè)節(jié)點(diǎn)。4.1 軟件開發(fā)場景把需求拆成以下順序確認(rèn)輸入輸出這個(gè)功能吃什么數(shù)據(jù)、出什么結(jié)果。寫最小用例先定義一個(gè)測試數(shù)據(jù)。實(shí)現(xiàn)最小路徑只要能跑通不看邊界。補(bǔ)充邊界與異常錯(cuò)誤處理、空目錄、斷網(wǎng)情況。接入真實(shí)數(shù)據(jù)小批驗(yàn)證。提交并交給評審。每一步都是小增量。你不需要一步到位寫出完整系統(tǒng)而是像搭積木一樣逐塊推進(jìn)。4.2 批量任務(wù)場景批量處理最容易踩的坑就是“一次性全量跑”。正確做法是先用 1 條數(shù)據(jù)驗(yàn)證算法正確。再用 10 到 50 條數(shù)據(jù)驗(yàn)證穩(wěn)定性。再跑一小批真實(shí)數(shù)據(jù)觀察耗時(shí)和顯存、內(nèi)存占用。最后再做全量并保留失敗的日志。這里有一個(gè)通用的小批處理腳本思路您可以根據(jù)實(shí)際任務(wù)調(diào)整參數(shù)和邏輯import os import logging from pathlib import Path logging.basicConfig( filenamebatch.log, levellogging.INFO, format%(asctime)s %(levelname)s %(message)s, ) input_dir Path(./inputs) output_dir Path(./outputs) output_dir.mkdir(exist_okTrue) # 第一批先跑 10 個(gè)驗(yàn)證流程 files sorted(input_dir.iterdir())[:10] for file_path in files: try: # 這里的寫法只是示例實(shí)際請?zhí)鎿Q為你的核心處理函數(shù) result process_one(file_path) output_path output_dir / file_path.name output_path.write_bytes(result) logging.info(fSUCCESS: {file_path.name}) except Exception as exc: logging.error(fFAILED: {file_path.name} error{exc})跑完第一批先看日志。成功率、單條耗時(shí)、資源占用符合預(yù)期再擴(kuò)展到全量。4.3 技術(shù)寫作場景寫技術(shù)文章也可以用同樣思路寫出核心結(jié)論這篇文章要讓讀者學(xué)會(huì)什么。列出結(jié)構(gòu)大綱只寫標(biāo)題不寫正文。先寫最容易驗(yàn)證的“動(dòng)手步驟”代碼塊和命令先補(bǔ)完。再補(bǔ)背景說明與原理部分。最后統(tǒng)一檢查格式和引用。這里最容易犯的錯(cuò)誤是“等靈感齊了再寫正文”。實(shí)際上先把可驗(yàn)證的代碼跑通文章骨架就穩(wěn)了。5. 如何驗(yàn)證小增量方法有沒有效果推薦用一組簡單的指標(biāo)來觀察自己或團(tuán)隊(duì)的變化。指標(biāo)計(jì)算公式/來源變化趨勢任務(wù)完成率完成的小增量數(shù) / 計(jì)劃的小增量數(shù)應(yīng)逐步提升平均完成時(shí)長單個(gè)小增量從開始到驗(yàn)收的耗時(shí)應(yīng)保持穩(wěn)定或降低提交粒度每次提交涉及的文件數(shù)和行數(shù)應(yīng)更小、更聚焦分支存活時(shí)間從分支創(chuàng)建到合并的天數(shù)應(yīng)顯著縮短返工率因驗(yàn)收不通過而返工的次數(shù)應(yīng)下降批量任務(wù)交付成功率全量任務(wù)一次交付成功的比例應(yīng)上升如果發(fā)現(xiàn)指標(biāo)沒有變好不要急著否定方法。大概率是任務(wù)拆得還不夠小或者根本沒有設(shè)驗(yàn)收標(biāo)準(zhǔn)。另外還可以用 Git 提交歷史來觀察自己的提交粒度。下面的命令可以查看最近提交涉及的文件數(shù)git log --oneline -20 --stat如果你想在項(xiàng)目目錄里自動(dòng)統(tǒng)計(jì)每個(gè)提交的文件變更數(shù)可以用這個(gè)思路git log --prettyformat:%h %s -20 | while read commit msg; do count$(git show --stat --oneline $commit | tail -n 1 | awk {print $1}) echo $commit 文件數(shù): $count 提交信息: $msg done這里的$commit是從前一個(gè)命令讀取的提交哈希實(shí)際終端環(huán)境里可以作為一個(gè)快速檢查腳本使用。如果你的任務(wù)推進(jìn)長期沒有可量化反饋可以先從這類小工具開始把反饋閉環(huán)建起來。6. 常見問題與排查方法小增量的方法論本身不復(fù)雜但實(shí)踐時(shí)容易踩坑。下面整理了一張排查表。問題現(xiàn)象可能原因排查方式解決思路任務(wù)拆完之后還是不想動(dòng)手任務(wù)仍然太大或者入口不清晰看第一個(gè)子任務(wù)是否 30 分鐘內(nèi)可完繼續(xù)拆直到第一個(gè)任務(wù)可以立刻執(zhí)行拆得太碎列表一堆但沒推進(jìn)把“行動(dòng)”拆成了“想法”檢查是否每個(gè)子任務(wù)都有可驗(yàn)證成果刪除只表達(dá)狀態(tài)、不表達(dá)交付的條目小步提交但代碼頻繁沖突分支存活時(shí)間太長觀察從創(chuàng)建到合并的時(shí)長加快合并節(jié)奏頻繁同步主干批量任務(wù)小批成功、全量失敗全量時(shí)存在邊界數(shù)據(jù)或資源超限查看失敗日志分析失敗樣本的共性分批加日志先覆蓋邊界再提升并發(fā)增量推進(jìn)很多但成果感不強(qiáng)缺少對外展示和反饋節(jié)點(diǎn)確認(rèn)每個(gè)小增量完成后是否有記錄/評審為每個(gè)小增量添加展示或演示環(huán)節(jié)任務(wù)推進(jìn)中有新的待辦反復(fù)插入沒有設(shè)置收集箱將臨時(shí)想法記錄到單獨(dú)列表先記錄統(tǒng)一處理不打斷當(dāng)前小增量寫了驗(yàn)收標(biāo)準(zhǔn)但沒法判斷驗(yàn)收標(biāo)準(zhǔn)描述模糊檢查標(biāo)準(zhǔn)是否包含可觀察或可測條件改成“輸出文件存在且日志無 ERROR”類的硬指標(biāo)最典型的問題是第一行拆完之后還是不想動(dòng)手。這種情況不用懷疑自己的自律性而是任務(wù)粒度還不夠細(xì)。一個(gè)真正的小增量應(yīng)該做到“打開工具就知道第一行代碼寫在哪里或者第一個(gè)操作按鈕點(diǎn)哪里”。7. 工程化落地與自動(dòng)化輔助小增量如果只是停留在個(gè)人清單層面執(zhí)行一段后會(huì)逐漸走形。比較穩(wěn)妥的方式是把它變成工程化流程。有幾個(gè)方向可以做。第一個(gè)方向?yàn)槊總€(gè)小增量建立持久化記錄。不要用隨手刪掉的便利貼而是把每一輪任務(wù)記錄成文檔包含日期、目標(biāo)、驗(yàn)收結(jié)果、發(fā)現(xiàn)問題。這樣兩周后可以復(fù)盤找到自己卡住的真實(shí)原因。第二個(gè)方向把“驗(yàn)收”自動(dòng)化。如果你做的是代碼任務(wù)可以在每個(gè)小增量完成后運(yùn)行一次測試命令或靜態(tài)檢查讓機(jī)器告訴你是否通過。常見的通用檢查方式# 示例運(yùn)行項(xiàng)目已有測試 pytest tests/ # 示例檢查代碼格式 ruff check src/ # 示例檢查腳本語法 python -m py_compile main.py需要注意不同項(xiàng)目的檢查命令不同以上只是通用示例。你的項(xiàng)目如果沒有 pytest 或 ruff需要按實(shí)際工具替換。第三個(gè)方向用腳本輔助生成任務(wù)模板。下面是一個(gè)簡單的 Python 腳本可以根據(jù)你輸入的總?cè)蝿?wù)名稱生成一個(gè)包含多個(gè)小增量占位結(jié)構(gòu)的文件方便快速開始。from pathlib import Path task_name input(請輸入總?cè)蝿?wù)名稱: ).strip() filename f{task_name}_task.md content f# 任務(wù){(diào)task_name} ## 小增量 1 - 目標(biāo) - 輸入條件 - 執(zhí)行步驟 - 驗(yàn)收標(biāo)準(zhǔn) - 預(yù)計(jì)耗時(shí) ## 小增量 2 - 目標(biāo) - 輸入條件 - 執(zhí)行步驟 - 驗(yàn)收標(biāo)準(zhǔn) - 預(yù)計(jì)耗時(shí) ## 小增量 3 - 目標(biāo) - 輸入條件 - 執(zhí)行步驟 - 驗(yàn)收標(biāo)準(zhǔn) - 預(yù)計(jì)耗時(shí) filepath Path(filename) filepath.write_text(content, encodingutf-8) print(f已生成任務(wù)拆解模板: {filepath.resolve()})這個(gè)腳本的優(yōu)勢是讓你把精力花在“填寫驗(yàn)收標(biāo)準(zhǔn)”而不是“組織格式”。第一次使用后你會(huì)發(fā)現(xiàn)自己原來對很多任務(wù)的預(yù)期其實(shí)并不清晰寫不出驗(yàn)收標(biāo)準(zhǔn)就是證據(jù)。第四個(gè)方向批量任務(wù)加重試和日志。無論你是在處理圖片、視頻、文檔還是調(diào)用 API只要涉及批量就必須假定會(huì)有一部分失敗。更穩(wěn)的批量流程是小批運(yùn)行、記錄日志、失敗進(jìn)入隊(duì)列、重試有限次數(shù)、最后人工查看剩余失敗項(xiàng)。8. 使用邊界與合規(guī)提醒小增量方法和技術(shù)實(shí)踐結(jié)合時(shí)有兩條邊界必須說清楚。第一不是所有事情都適合“先小步再擴(kuò)大”。比如線上服務(wù)出現(xiàn)了緊急故障你首先要做的是止血而不是拆成五個(gè)小增量慢慢觀察。這時(shí)候的正確做法是快速恢復(fù)、再事后復(fù)盤把修正項(xiàng)拆成小增量補(bǔ)進(jìn)開發(fā)流程。小增量解決的是“從零到一、從一到穩(wěn)定交付”的執(zhí)行問題不是應(yīng)急響應(yīng)的替代品。第二凡是涉及生產(chǎn)環(huán)境、用戶數(shù)據(jù)、版權(quán)素材、人臉信息、聲音信息批量處理和個(gè)人發(fā)布前都要確認(rèn)授權(quán)和合規(guī)邊界。小步發(fā)布不代表可以繞過備份、回滾和灰度驗(yàn)證。即使你只處理了很小一批數(shù)據(jù)只要數(shù)據(jù)來源或結(jié)果使用沒有授權(quán)最小增量也不能覆蓋合規(guī)風(fēng)險(xiǎn)。技術(shù)文章里分享處理腳本時(shí)也建議明確提示“僅用于合法授權(quán)的內(nèi)容和自己擁有的測試數(shù)據(jù)”。第三團(tuán)隊(duì)協(xié)作場景下小步提交是一項(xiàng)紀(jì)律不要為了追求“每天提交很多次”就制造大量無意義提交也不要一個(gè)人在長期分支上偷偷攢大量改動(dòng)而不同步。小增量的收益必須在“及時(shí)合并、及時(shí)評審、及時(shí)同步”的前提下才能體現(xiàn)。9. 最佳實(shí)踐與使用建議基于前面的分析這套方法要真正見效建議從下面幾件事做起。寫任務(wù)清單時(shí)不要以“做什么”為主體而是以“完成什么”為主體。舉例“研究視頻生成參數(shù)”是一個(gè)動(dòng)詞更合適的小增量是“使用測試視頻跑通默認(rèn)參數(shù)生成記錄顯存占用和輸出時(shí)長”。前者沒有終點(diǎn)后者有明確終點(diǎn)。每個(gè)任務(wù)單元限制反饋周期。個(gè)人開發(fā)時(shí)一個(gè)小增量的反饋周期最好不超過一個(gè)工作日團(tuán)隊(duì)協(xié)作時(shí)從完成到評審合并最好不要超過兩到三天。反饋周期越短糾偏成本越低。定期回顧自己的提交記錄和任務(wù)記錄。可以每周抽十分鐘看一下本周完成了多少個(gè)小增量、有多少個(gè)是一次通過、有多少出現(xiàn)了返工。如果返工率高說明拆解時(shí)對輸入條件和驗(yàn)收標(biāo)準(zhǔn)的分析還不夠。給批量任務(wù)預(yù)留重跑機(jī)制。批量處理中的失敗項(xiàng)一定要記錄到日志并支持“只處理失敗項(xiàng)”的重跑模式。最怕的是全量跑完發(fā)現(xiàn)三分之一失敗后沒有任何日志不知道哪些失敗、為什么失敗。不要追求“拆得很漂亮”再動(dòng)手。任務(wù)拆解是執(zhí)行的一部分不是前置儀式。實(shí)際上很多驗(yàn)收標(biāo)準(zhǔn)只有在完成第一個(gè)小增量后才會(huì)變清晰。先拆一個(gè)可以立刻執(zhí)行的單元跑通之后再調(diào)整后面單元的粒度。如果是在團(tuán)隊(duì)里落地建議從一個(gè)小項(xiàng)目開始試點(diǎn)而不是立刻全員鋪開。否則很容易變成“表單填寫大賽”團(tuán)隊(duì)把精力花在寫任務(wù)模板上而不是交付結(jié)果上。小增量的檢驗(yàn)標(biāo)準(zhǔn)永遠(yuǎn)只有一個(gè)是否更快地交付了可驗(yàn)證成果。10. 總結(jié)與下一步“Getting things done (in small increments)”最值得嘗試的點(diǎn)不是它引入了什么新概念而是它把一個(gè)很樸素的常識變成了可操作的執(zhí)行標(biāo)準(zhǔn)一次只做一小塊做完立刻驗(yàn)證驗(yàn)證通過再推進(jìn)下一塊。我建議你從下一個(gè)手頭任務(wù)開始驗(yàn)證不管它是寫代碼、做批量實(shí)驗(yàn)、整理文檔還是處理數(shù)據(jù)先拆成三個(gè)小增量每個(gè)都寫清楚驗(yàn)收標(biāo)準(zhǔn)然后只做第一個(gè)。結(jié)束后記錄一下啟動(dòng)耗時(shí)和完成耗時(shí)和以前“一次性做完”的節(jié)奏對比往往立刻能感覺到差別。最容易踩的坑是拆解時(shí)沒有設(shè)置驗(yàn)收標(biāo)準(zhǔn)。這不是模板問題而是你還沒真正想清楚“什么算完成”。如果一個(gè)任務(wù)寫不出驗(yàn)收標(biāo)準(zhǔn)大概率還需要重新分析輸入條件或結(jié)果形態(tài)。接下來可以繼續(xù)擴(kuò)展的方向有三個(gè)一是把任務(wù)拆解和 Git 提交粒度關(guān)聯(lián)起來每個(gè)小增量對應(yīng)一次提交二是給批量任務(wù)加自動(dòng)日志和失敗重試讓交付更穩(wěn)定三是每周復(fù)用第 5 節(jié)的指標(biāo)做復(fù)盤連續(xù)四周觀察完成率、返工率和分支存活時(shí)間的變化。落到日常行動(dòng)上就是從明天開始把第一個(gè)任務(wù)拆小一點(diǎn)。