戰(zhàn)手冊(cè))
我接到 WorkBuddy 這個(gè)項(xiàng)目時(shí)需求文檔只有一句話做一個(gè)能幫團(tuán)隊(duì)把任務(wù)理清楚的 App。沒(méi)有用戶畫(huà)像沒(méi)有流程圖沒(méi)有競(jìng)品分析甚至沒(méi)人說(shuō)清楚要先做手機(jī)版還是網(wǎng)頁(yè)版。我當(dāng)時(shí)的反應(yīng)是這個(gè)項(xiàng)目如果直接動(dòng)手寫(xiě)代碼大概率會(huì)在兩周后推翻重來(lái)。后來(lái)的進(jìn)展證明這句話背后藏著完整的協(xié)作工具需求也藏著 90 天從零到上線的全部節(jié)奏感。標(biāo)題里的 WorkBuddy FDE就是我在這個(gè)項(xiàng)目中沉淀出來(lái)的實(shí)戰(zhàn)方法論——FDEFeature Driven Engineering特性驅(qū)動(dòng)工程核心思想很簡(jiǎn)單以可交付的功能特性為單位去拆需求、排計(jì)劃、做驗(yàn)收而不是以頁(yè)面、接口或模塊為單位。這篇手冊(cè)適合正在創(chuàng)業(yè)團(tuán)隊(duì)、個(gè)人獨(dú)立開(kāi)發(fā)、或者剛接手模糊需求項(xiàng)目的朋友參考。我會(huì)把從需求澄清到上線復(fù)盤(pán)的所有關(guān)鍵動(dòng)作攤開(kāi)講包括哪些決定省了時(shí)間、哪些坑本來(lái)可以提前避掉。1. 一句話需求背后的真實(shí)問(wèn)題需求澄清比寫(xiě)代碼更費(fèi)勁1.1 原始需求里的三個(gè)關(guān)鍵詞沒(méi)有一個(gè)是清楚的大多數(shù)人在接到模糊需求時(shí)第一反應(yīng)是追問(wèn)細(xì)節(jié)但追問(wèn)的方向往往錯(cuò)了。原始需求里最核心的三個(gè)詞是團(tuán)隊(duì)、任務(wù)、理清楚。團(tuán)隊(duì)是誰(shuí)是三個(gè)人到十個(gè)人的小組織還是上百人的跨職能團(tuán)隊(duì)任務(wù)是什么形態(tài)是待辦清單、看板卡片還是甘特圖里的項(xiàng)目節(jié)點(diǎn)理清楚又是什么標(biāo)準(zhǔn)是每個(gè)人知道自己今天該干什么還是管理者能看到全盤(pán)進(jìn)度這三個(gè)問(wèn)題不解決后面所有設(shè)計(jì)都是空中樓閣。我用了整整兩天去約不同角色聊不做問(wèn)卷只做開(kāi)放式訪談每次大約四十分鐘。訪談對(duì)象分三類(lèi)執(zhí)行任務(wù)的人、分配任務(wù)的負(fù)責(zé)人、跨部門(mén)需要知道進(jìn)度的協(xié)作方。這三類(lèi)角色對(duì)同一個(gè)任務(wù)的感受完全不同。執(zhí)行者關(guān)心的是我今天優(yōu)先做什么、哪些事情快到截止時(shí)間了負(fù)責(zé)人關(guān)心的是誰(shuí)手上任務(wù)積壓、哪條鏈路卡住了協(xié)作方只想知道這東西什么時(shí)候能給我。這輪訪談直接推翻了我最初的假設(shè)。我原本以為 WorkBuddy 的核心是做一個(gè)漂亮的看板后來(lái)發(fā)現(xiàn)大家真正缺的不是看板而是任務(wù)指派之后有沒(méi)有人跟進(jìn)、做完之后有沒(méi)有人知曉。也就是說(shuō)價(jià)值重心不在列表展示而在任務(wù)狀態(tài)變化帶來(lái)的通知與同步。1.2 把模糊目標(biāo)翻譯成可驗(yàn)收的用戶故事在 FDE 的框架里需求澄清的唯一產(chǎn)出不是長(zhǎng)文檔而是一組可驗(yàn)收的用戶故事。每個(gè)用戶故事必須滿足三要素角色、行為、價(jià)值。WorkBuddy 最早期的故事清單是這樣的特性ID用戶故事驗(yàn)收標(biāo)準(zhǔn)優(yōu)先級(jí)F-01作為團(tuán)隊(duì)成員我可以在看板上創(chuàng)建任務(wù)以便記錄待辦事項(xiàng)創(chuàng)建后任務(wù)立即出現(xiàn)在看板刷新不丟失P0F-02作為團(tuán)隊(duì)負(fù)責(zé)人我可以把任務(wù)指派給具體成員以便明確責(zé)任被指派的人能收到實(shí)時(shí)通知P0F-03作為執(zhí)行者我可以勾選完成任務(wù)以便相關(guān)方看到進(jìn)度完成狀態(tài)在看板上實(shí)時(shí)同步P0F-04作為負(fù)責(zé)人我可以按項(xiàng)目查看所有任務(wù)以便掌握整體進(jìn)度項(xiàng)目頁(yè)能列出全部任務(wù)及狀態(tài)P0F-05作為成員我可以給任務(wù)設(shè)置截止時(shí)間以便管理自己的排期到期前推送提醒P1F-06作為協(xié)作方我可以評(píng)論任務(wù)以便討論執(zhí)行細(xì)節(jié)評(píng)論與回復(fù)實(shí)時(shí)可見(jiàn)P1這里的關(guān)鍵是每個(gè)故事后面必須有驗(yàn)收標(biāo)準(zhǔn)否則只是愿望清單。比如創(chuàng)建任務(wù)這件事如果驗(yàn)收標(biāo)準(zhǔn)只是能保存成功那太弱了。我把它定為創(chuàng)建后任務(wù)立即出現(xiàn)在看板刷新不丟失這就逼著后端接口和本地緩存必須同時(shí)工作。FDE 的整個(gè)執(zhí)行單元就是一個(gè)帶驗(yàn)收標(biāo)準(zhǔn)的特性而不是一段代碼、一個(gè)頁(yè)面。1.3 砍需求的三個(gè)原則我們最初列了 24 個(gè)用戶故事最終只保留了 8 個(gè)作為 MVP??车舻墓δ馨?AI 自動(dòng)排期、甘特視圖、第三方日歷同步、多級(jí)子任務(wù)、自定義字段、文件附件預(yù)覽。這些功能并不是沒(méi)有價(jià)值而是在 90 天路徑里會(huì)擠占核心閉環(huán)的驗(yàn)證時(shí)間。砍需求我用了三個(gè)問(wèn)題反復(fù)追問(wèn)。第一這個(gè)特性砍掉后用戶是否還有替代方式完成同樣目標(biāo)如果有那就不是剛需。第二這個(gè)特性能不能在兩個(gè)星期內(nèi)做出端到端閉環(huán)如果做不到說(shuō)明它背后還有沒(méi)想清楚的依賴。第三它是不是直接服務(wù)于那句原始需求里的理清楚如果只是錦上添花就進(jìn) P2留給第二期。這個(gè)決策過(guò)程必須有記錄。我把砍掉的每個(gè)功能都寫(xiě)進(jìn)了一個(gè)暫緩清單標(biāo)注了暫緩原因和重新評(píng)估的觸發(fā)條件。這樣做有兩個(gè)好處一是以后不會(huì)被反復(fù)質(zhì)疑當(dāng)初為什么沒(méi)做這個(gè)二是新需求進(jìn)來(lái)時(shí)能快速判斷該進(jìn)哪個(gè)版本而不是每次都重新討論一遍。2. 90天路徑規(guī)劃里程碑倒排法與每周交付節(jié)奏2.1 上線日期先定再反推每階段該干什么整個(gè) 90 天規(guī)劃最關(guān)鍵的一個(gè)決定是把上線日期當(dāng)作不可變節(jié)點(diǎn)。第 12 周周五必須提交審核而不是差不多就上。有了硬節(jié)點(diǎn)倒排計(jì)劃才有意義。有人會(huì)問(wèn)如果做到一半發(fā)現(xiàn)需求變了怎么辦答案是需求變更不能影響上線日期只能影響功能范圍。這就是我在項(xiàng)目里反復(fù)強(qiáng)調(diào)的日期是錨范圍是變量。具體到階段劃分90 天被我切成四段階段時(shí)間目標(biāo)關(guān)鍵交付物階段一第1-2周驗(yàn)證核心假設(shè)、凍結(jié)MVP范圍可點(diǎn)擊原型、特性清單、技術(shù)選型階段二第3-7周跑通核心閉環(huán)可安裝的內(nèi)部測(cè)試版完成 F-01 到 F-04階段三第8-11周打磨體驗(yàn)、內(nèi)測(cè)與修問(wèn)題穩(wěn)定版本、內(nèi)測(cè)報(bào)告、發(fā)布材料階段四第12周提交審核、灰度發(fā)布、線上監(jiān)控應(yīng)用上架、監(jiān)控看板、告警規(guī)則階段一最反直覺(jué)整個(gè)兩周不寫(xiě)業(yè)務(wù)代碼只做原型。很多人覺(jué)得這是在浪費(fèi)時(shí)間但原型驗(yàn)證的是交互路徑和數(shù)據(jù)結(jié)構(gòu)。我用原型工具把 F-01 到 F-04 的完整流程點(diǎn)了一遍發(fā)現(xiàn)任務(wù)創(chuàng)建到指派這個(gè)鏈路里需要確認(rèn)的字段比想象中多得多。設(shè)計(jì)上多做一天開(kāi)發(fā)階段就能少返工三天。2.2 每周一個(gè)垂直切片而不是先做完整 UI 再做邏輯FDE 最核心的實(shí)踐是垂直切片。第三周交付的必須是能創(chuàng)建任務(wù)、數(shù)據(jù)落到數(shù)據(jù)庫(kù)、再顯示回看板的完整功能而不是只做好看板界面的靜態(tài)頁(yè)面。每個(gè)切片都是一條從數(shù)據(jù)庫(kù)到界面的完整鏈路。第三周做任務(wù)創(chuàng)建第四周做任務(wù)列表第五周做指派與通知第六周做狀態(tài)流轉(zhuǎn)第七周做項(xiàng)目維度匯總。這樣每周五都有一版能演示的東西。垂直切片最大的好處是風(fēng)險(xiǎn)每周暴露。如果某周的數(shù)據(jù)結(jié)構(gòu)設(shè)計(jì)有問(wèn)題當(dāng)周就能發(fā)現(xiàn)而不是等到所有界面做完之后聯(lián)調(diào)時(shí)才炸。我可以用裝修來(lái)類(lèi)比裝修不能先把所有墻刷完再通電通水而是每一面墻做完都要試燈、試插座、試網(wǎng)口??雌饋?lái)多了一道工序但避免了最后一次性排查時(shí)根本不知道哪個(gè)環(huán)節(jié)出問(wèn)題。另一個(gè)容易被忽略的點(diǎn)是垂直切片必須有對(duì)外可見(jiàn)的結(jié)果。我給自己的要求是每周切片完成后找一個(gè)完全沒(méi)參與項(xiàng)目的人來(lái)操作兩分鐘只看他會(huì)不會(huì)用。如果對(duì)方找不到入口說(shuō)明這個(gè)切片還不算真正完成。2.3 里程碑檢查每周五的 15 分鐘驗(yàn)收每周五下午收工前我用三個(gè)問(wèn)題做里程碑檢查。第一個(gè)問(wèn)題這個(gè)切片能被用戶獨(dú)立使用嗎還是說(shuō)中間需要開(kāi)發(fā)者在旁解釋概念才能跑通。第二個(gè)問(wèn)題新用戶不看我演示能自己找到入口并完成核心操作嗎這考驗(yàn)的是交互自然度。第三個(gè)問(wèn)題如果下周我暫時(shí)離開(kāi)項(xiàng)目另一個(gè)人接手這個(gè)代碼能在一天內(nèi)搞清楚當(dāng)前進(jìn)展嗎這個(gè)問(wèn)題直接決定了代碼注釋的密度、數(shù)據(jù)表的命名規(guī)范、以及接口文檔是否更新。這三個(gè)問(wèn)題看起來(lái)簡(jiǎn)單但執(zhí)行起來(lái)很有壓迫感。因?yàn)榈谌齻€(gè)問(wèn)題意味著每個(gè)周五都要把最近的代碼當(dāng)作要交接出去的版本來(lái)整理不能攢到最后。很多項(xiàng)目的混亂不是技術(shù)問(wèn)題而是長(zhǎng)期缺少這種強(qiáng)制性的階段性驗(yàn)收導(dǎo)致每個(gè)模塊看起來(lái)都在做但沒(méi)有一個(gè)模塊真正收口。2.4 90 天里的三個(gè)關(guān)鍵里程碑除了每周驗(yàn)收整個(gè) 90 天里還有三個(gè)必須嚴(yán)肅對(duì)待的關(guān)鍵節(jié)點(diǎn)。第一個(gè)是第 2 周結(jié)束時(shí)的需求凍結(jié)。從第 3 周開(kāi)始不再新增 P0 需求。任何新想法都先進(jìn)暫緩清單等第一個(gè)可用版本上線后再評(píng)估。沒(méi)有需求凍結(jié)90 天路徑就是一句空話因?yàn)樾滦枨髸?huì)不斷稀釋已有排期。第二個(gè)是第 7 周結(jié)束時(shí)的核心閉環(huán)凍結(jié)。F-01 到 F-04 全部完成并且可演示。從第 8 周開(kāi)始只做三類(lèi)事修問(wèn)題、優(yōu)化體驗(yàn)、補(bǔ)齊發(fā)布材料。這個(gè)節(jié)點(diǎn)如果沒(méi)守住后面所有環(huán)節(jié)都會(huì)往后滾。第三個(gè)是第 10 周結(jié)束時(shí)的內(nèi)測(cè)問(wèn)題清零。內(nèi)測(cè)用戶反饋的關(guān)鍵問(wèn)題必須全部關(guān)閉不關(guān)閉的問(wèn)題要明確給出延期理由。否則第 11 周還在處理第 8 周就該解決的問(wèn)題審核和灰度準(zhǔn)備就會(huì)被擠到角落里。3. 技術(shù)選型與架構(gòu)決定 App 能否 90 天上線的關(guān)鍵博弈3.1 架構(gòu)決策的優(yōu)先級(jí)速度大于優(yōu)雅但不等于沒(méi)有架構(gòu)對(duì)于 90 天項(xiàng)目選型首要標(biāo)準(zhǔn)不是技術(shù)最先進(jìn)而是團(tuán)隊(duì)上手速度快、生態(tài)完善、部署簡(jiǎn)單。我在 WorkBuddy 里主動(dòng)放棄了微服務(wù)、容器編排、復(fù)雜消息中間件選型只有一個(gè)原則單機(jī)跑得動(dòng)、后續(xù)能平滑演進(jìn)。過(guò)度設(shè)計(jì)在時(shí)間緊張的項(xiàng)目里是致命的因?yàn)樗鼤?huì)讓每一行代碼都變重。但不做過(guò)度設(shè)計(jì)不等于不設(shè)計(jì)。我見(jiàn)過(guò)很多項(xiàng)目因?yàn)闆](méi)有架構(gòu)約束最后變成一個(gè)大泥球。WorkBuddy 的做法是定三層邊界客戶端只負(fù)責(zé)狀態(tài)展示和用戶交互服務(wù)端只負(fù)責(zé)業(yè)務(wù)規(guī)則和數(shù)據(jù)持久化中間通過(guò)統(tǒng)一 API 通信。這個(gè)邊界能保證任何一層內(nèi)部調(diào)整時(shí)另外兩層不跟著重構(gòu)。3.2 客戶端一套代碼覆蓋雙端減少維護(hù)成本客戶端我選了跨平臺(tái)開(kāi)發(fā)框架而不是原生雙端各寫(xiě)一套。原因很簡(jiǎn)單項(xiàng)目團(tuán)隊(duì)人力有限90 天里要同時(shí)維護(hù)兩套原生代碼幾乎不可能。協(xié)作工具這個(gè)品類(lèi)的 UI 復(fù)雜度屬于中等水平跨平臺(tái)方案完全能覆蓋而且生態(tài)里已經(jīng)有成熟的狀態(tài)管理、路由、網(wǎng)絡(luò)請(qǐng)求和本地存儲(chǔ)方案。這個(gè)選擇的代價(jià)也要提前說(shuō)清楚跨平臺(tái)方案的坑集中在真機(jī)兼容性上尤其是相機(jī)、推送、后臺(tái)任務(wù)這些系統(tǒng)能力。WorkBuddy 里唯一涉及系統(tǒng)能力的模塊是推送通知我為此專(zhuān)門(mén)預(yù)留了額外的真機(jī)測(cè)試時(shí)間。如果項(xiàng)目里要大量調(diào)用傳感器、藍(lán)牙或高性能圖形這條選型思路可能就不適用了。3.3 服務(wù)端從單體開(kāi)始但留好擴(kuò)展點(diǎn)后端最初是單體應(yīng)用加關(guān)系型數(shù)據(jù)庫(kù)所有業(yè)務(wù)邏輯都在一個(gè)服務(wù)里。理由不是單體更好而是我們沒(méi)有足夠證據(jù)在第一天就把服務(wù)邊界劃分正確。服務(wù)拆分的依據(jù)應(yīng)該是獨(dú)立擴(kuò)展需求和獨(dú)立故障域而不是代碼行數(shù)。90 天項(xiàng)目里最怕的就是為了架構(gòu)而架構(gòu)拆出一堆互相調(diào)用的服務(wù)結(jié)果每個(gè)都在裸奔。雖然單體起步我還是預(yù)留了三個(gè)明確的擴(kuò)展點(diǎn)。第一是消息隊(duì)列用來(lái)承接異步事件比如任務(wù)變更后的通知分發(fā)第二是對(duì)象存儲(chǔ)為后續(xù)文件上傳做準(zhǔn)備第三是第三方推送服務(wù)接入的適配層這個(gè)適配層很薄但不提前留好后面硬接會(huì)很痛苦。這三個(gè)擴(kuò)展點(diǎn)讓單體應(yīng)用在業(yè)務(wù)增長(zhǎng)后不至于推倒重來(lái)。3.4 數(shù)據(jù)模型一張任務(wù)表如何撐起協(xié)作邏輯后端數(shù)據(jù)結(jié)構(gòu)我保持了極度克制。沒(méi)有為看板、列表、日歷各建一套表底層只有一張任務(wù)表外加項(xiàng)目和成員兩張輔助表。任務(wù)表的核心字段長(zhǎng)這樣tasks ( id UUID PRIMARY KEY, title TEXT NOT NULL, description TEXT, status TEXT NOT NULL DEFAULT todo, assignee_id UUID REFERENCES users(id), creator_id UUID REFERENCES users(id), project_id UUID REFERENCES projects(id), due_date TIMESTAMP, created_at TIMESTAMP NOT NULL, updated_at TIMESTAMP NOT NULL )狀態(tài)只保留三個(gè)todo、doing、done。很多人喜歡把狀態(tài)設(shè)計(jì)成自由字符串這會(huì)讓報(bào)表統(tǒng)計(jì)和權(quán)限校驗(yàn)變得極難維護(hù)。我還在服務(wù)端加了狀態(tài)機(jī)校驗(yàn)todo 到 doing 到 done 是合法路徑done 不允許直接跳回 todo必須經(jīng)過(guò) doing。這個(gè)限制在初期看起來(lái)有點(diǎn)死板但它保證了任務(wù)完成率這個(gè)核心指標(biāo)不會(huì)被隨意篡改。另一個(gè)容易被忽略的字段是 updated_at。我要求所有更新操作都必須刷新它因?yàn)楹罄m(xù)做離線同步和增量推送時(shí)這個(gè)時(shí)間戳就是沖突判斷的基礎(chǔ)。沒(méi)有它客戶端之間的數(shù)據(jù)合并會(huì)變成一場(chǎng)災(zāi)難。4. 核心功能實(shí)戰(zhàn)任務(wù)看板、實(shí)時(shí)協(xié)作、離線同步的實(shí)現(xiàn)路徑4.1 看板的數(shù)據(jù)結(jié)構(gòu)與狀態(tài)流轉(zhuǎn)看板本質(zhì)上是任務(wù)列表按狀態(tài)分組渲染。技術(shù)上沒(méi)有任何炫酷的地方真正復(fù)雜的是狀態(tài)流轉(zhuǎn)。小組件里點(diǎn)一下完成背后要發(fā)生四件事本地狀態(tài)更新、接口請(qǐng)求、服務(wù)端狀態(tài)機(jī)校驗(yàn)、其他在線成員的界面刷新。這四件事任何一件斷掉用戶都會(huì)覺(jué)得狀態(tài)變了但好像沒(méi)變。內(nèi)測(cè)階段發(fā)生過(guò)一次有意思的事。某個(gè)團(tuán)隊(duì)用戶反復(fù)把任務(wù)從 done 拖回 todo理由是我標(biāo)錯(cuò)了。結(jié)果一天之內(nèi)任務(wù)完成率從 80% 掉到 20%。我們的狀態(tài)機(jī)直接攔住了這條非法路徑之后設(shè)計(jì)上增加了一個(gè)重新打開(kāi)按鈕但操作邊界必須經(jīng)過(guò) doing同時(shí)在任務(wù)動(dòng)態(tài)里記錄了一條由已完成重新打開(kāi)的日志。這個(gè)日志后來(lái)成了團(tuán)隊(duì)復(fù)盤(pán)的重要依據(jù)。狀態(tài)機(jī)不是用來(lái)限制用戶而是用來(lái)保證數(shù)據(jù)的可信度。4.2 實(shí)時(shí)協(xié)作推送和輪詢的取舍第一版實(shí)時(shí)協(xié)作我偷懶用了輪詢客戶端每 5 秒拉一次任務(wù)列表。內(nèi)測(cè)只有 12 個(gè)人在線的時(shí)候服務(wù)器負(fù)載已經(jīng)不好看而且任務(wù)狀態(tài)刷新有明顯延遲。后來(lái)?yè)Q成實(shí)時(shí)通信協(xié)議長(zhǎng)連接加增量消息推送才徹底解決。這里的關(guān)鍵不是技術(shù)本身而是消息體只傳變更字段不傳整個(gè)任務(wù)對(duì)象。比如任務(wù)狀態(tài)從 todo 變成 doing服務(wù)端推送的消息只需要包含任務(wù) ID、變更后的狀態(tài)、操作者 ID 和時(shí)間戳客戶端用這四條信息更新本地狀態(tài)。如果每次都推送完整任務(wù)對(duì)象網(wǎng)絡(luò)流量和前端渲染壓力都會(huì)翻倍。這個(gè)優(yōu)化思路在任何實(shí)時(shí)協(xié)作場(chǎng)景都適用先想清楚最小變更集合是什么。4.3 離線優(yōu)先本地緩存與沖突處理手機(jī) App 必須處理電梯、地鐵、車(chē)庫(kù)這些斷網(wǎng)場(chǎng)景否則用戶就會(huì)在信號(hào)恢復(fù)后看到一個(gè)和自己操作不一致的界面。WorkBuddy 的做法是所有寫(xiě)操作先進(jìn)本地隊(duì)列界面立刻反饋成功網(wǎng)絡(luò)恢復(fù)后按順序同步到服務(wù)端。沖突處理采用最后一次寫(xiě)入覆蓋同時(shí)保留更新日志。這個(gè)方案從技術(shù)上看不是最完美的但它是 90 天里最務(wù)實(shí)的選擇。真要實(shí)現(xiàn)字段級(jí)沖突合并需要一個(gè)完整的版本向量機(jī)制那會(huì)占掉至少兩周開(kāi)發(fā)時(shí)間。對(duì)于任務(wù)協(xié)作這類(lèi)低沖突業(yè)務(wù)最后一次寫(xiě)入覆蓋加上審計(jì)日志已經(jīng)夠用。如果后續(xù)要支持多人同時(shí)編輯同一個(gè)文檔這個(gè)方案就要升級(jí)成基于操作日志的合并。4.4 從內(nèi)測(cè)數(shù)據(jù)反推產(chǎn)品問(wèn)題第 8 周我們開(kāi)始邀請(qǐng)真實(shí)用戶內(nèi)測(cè)數(shù)據(jù)暴露了一個(gè)設(shè)計(jì)盲區(qū)超過(guò) 40% 的任務(wù)沒(méi)有指派負(fù)責(zé)人。原因讓人哭笑不得——?jiǎng)?chuàng)建任務(wù)表單里指派人是非必填項(xiàng)很多用戶順手就跳過(guò)了。但任務(wù)沒(méi)有負(fù)責(zé)人整個(gè)協(xié)作閉環(huán)就斷了一半。我立刻調(diào)整了表單交互只有選擇負(fù)責(zé)人才能提交任務(wù)。后端同時(shí)加了校驗(yàn)強(qiáng)制要求任務(wù)必須有關(guān)聯(lián)成員。這類(lèi)問(wèn)題只有真實(shí)流量下才會(huì)暴露單元測(cè)試寫(xiě)不出來(lái)。這也解釋了為什么我把內(nèi)測(cè)放在第 8 周而不是最后一周數(shù)據(jù)反饋需要時(shí)間才能轉(zhuǎn)化為產(chǎn)品調(diào)整如果第 12 周才第一次讓真人用發(fā)現(xiàn)問(wèn)題也只能帶著問(wèn)題上線。內(nèi)測(cè)問(wèn)題清零不是靠祈禱而是靠提前暴露。5. 上線前的最后兩周測(cè)試、審核與監(jiān)控一樣都不能少5.1 真機(jī)測(cè)試清單不能再只有模擬器能跑跨平臺(tái)方案最大的教訓(xùn)是模擬器永遠(yuǎn)只能驗(yàn)證功能驗(yàn)證不了真實(shí)體驗(yàn)。我整理了一份真機(jī)測(cè)試清單每臺(tái)設(shè)備按清單走一遍測(cè)試項(xiàng)測(cè)試內(nèi)容常見(jiàn)問(wèn)題屏幕適配小屏、劉海屏、全面屏底部按鈕被手勢(shì)條遮擋弱網(wǎng)環(huán)境網(wǎng)絡(luò)切換、斷網(wǎng)恢復(fù)請(qǐng)求超時(shí)無(wú)提示、同步卡死后臺(tái)切換切后臺(tái) 30 分鐘后回前臺(tái)連接狀態(tài)未恢復(fù)導(dǎo)致重復(fù)登錄通知權(quán)限首次彈窗、拒絕后重新開(kāi)啟權(quán)限開(kāi)啟后收不到推送電池消耗長(zhǎng)時(shí)間掛后臺(tái)長(zhǎng)連接未釋放導(dǎo)致耗電異常存儲(chǔ)空間緩存持續(xù)增長(zhǎng)列表圖片緩存無(wú)上限這份清單在第 11 周每天跑一輪。最典型的問(wèn)題是后臺(tái)切換用戶把 App 切到后臺(tái)半個(gè)小時(shí)后回來(lái)長(zhǎng)連接已經(jīng)斷開(kāi)界面還顯示在線狀態(tài)最后是通過(guò)監(jiān)聽(tīng)?wèi)?yīng)用回前臺(tái)事件并主動(dòng)重建連接解決的。這些問(wèn)題在模擬器里一個(gè)都復(fù)現(xiàn)不出來(lái)。5.2 發(fā)布審核與灰度策略發(fā)布審核準(zhǔn)備最容易被忽略的是隱私政策頁(yè)面。我在提交前一晚發(fā)現(xiàn)應(yīng)用商店要求必須有隱私政策和用戶協(xié)議入口差點(diǎn)整周推遲。所以第 11 周第一天就該檢查三件事隱私政策是否可訪問(wèn)、權(quán)限聲明是否與實(shí)際調(diào)用一致、測(cè)試賬號(hào)是否已經(jīng)移除。任何一條不過(guò)審整個(gè) 90 天計(jì)劃都會(huì)崩?;叶炔呗晕矣昧俗詈?jiǎn)單的做法先開(kāi)放報(bào)名制的內(nèi)測(cè)渠道收集崩潰率和反饋審核通過(guò)后只開(kāi)放 10% 的邀請(qǐng)碼觀察三天確認(rèn)崩潰率低于千分之一再全量開(kāi)放。不要一上來(lái)就全面推廣因?yàn)楹蠖朔?wù)容量和監(jiān)控告警都需要時(shí)間驗(yàn)證?;叶炔皇且环N保守姿態(tài)而是給線上系統(tǒng)一個(gè)預(yù)熱期。5.3 線上監(jiān)控崩潰、接口、性能三條線上線不是終點(diǎn)而是另一個(gè)調(diào)試階段的開(kāi)始。我要求崩潰收集服務(wù)在第一個(gè)版本就接入這不算額外成本卻能第一時(shí)間拿到用戶端的崩潰堆棧。沒(méi)有崩潰上報(bào)的發(fā)布等于盲發(fā)。接口層做了兩件事耗時(shí)監(jiān)控和錯(cuò)誤告警。任務(wù)列表接口 P95 耗時(shí)如果超過(guò) 1 秒告警通知立刻發(fā)出來(lái)。頁(yè)面性能用采樣統(tǒng)計(jì)重點(diǎn)看首屏渲染時(shí)間和任務(wù)列表滾動(dòng)幀率。很多項(xiàng)目上線第二天才發(fā)現(xiàn)接口在高峰時(shí)段超時(shí)用戶一兩分鐘內(nèi)就流失了監(jiān)控的價(jià)值不是事后找原因而是讓問(wèn)題在影響擴(kuò)大前被攔住。6. 復(fù)盤(pán) WorkBuddy哪些決策省了時(shí)間哪些坑可以提前避6.1 做對(duì)了的三件事第一需求凍結(jié)時(shí)砍掉了所有 P1 以下功能。當(dāng)時(shí)的暫緩清單現(xiàn)在回頭看有一半功能已經(jīng)不需要做了另外一半放進(jìn)二期后明顯做得更從容??承枨蟛皇菧p少價(jià)值而是為真正重要的特性爭(zhēng)取空間。第二堅(jiān)持每周垂直切片讓每個(gè)相關(guān)方每周都有東西可看。這個(gè)節(jié)奏帶來(lái)的直接好處是沒(méi)有任何一個(gè)模塊在最后階段突然返工。因?yàn)槊總€(gè)模塊交付已經(jīng)超過(guò)四周即使有問(wèn)題也已經(jīng)提前暴露并修復(fù)。第三從第一天就接入了崩潰收集服務(wù)而不是產(chǎn)品穩(wěn)定之后補(bǔ)。這是我做過(guò)成本最低、收益最高的決定。因?yàn)楹竺娴拿枯唭?nèi)測(cè)都能直接看到真實(shí)崩潰情況不用每次等用戶截圖手動(dòng)描述問(wèn)題。6.2 應(yīng)該更早做的兩件事第一用戶訪談應(yīng)該提前到需求調(diào)研第一天而不是第二周才開(kāi)始。前面兩天我陷入了一種自我感覺(jué)良好的狀態(tài)以為已經(jīng)理解需求。直到訪談完第一組真實(shí)用戶才發(fā)現(xiàn)我的假設(shè)至少有三處是錯(cuò)的。越早接觸真實(shí)用戶錯(cuò)誤假設(shè)的成本越低。第二真機(jī)測(cè)試應(yīng)該在第四周就開(kāi)始逐步進(jìn)行而不是集中到最后兩周。跨平臺(tái)框架的兼容問(wèn)題通常在具體設(shè)備上才會(huì)出現(xiàn)早測(cè)一臺(tái)就早一點(diǎn)暴露問(wèn)題。我最初擔(dān)心版本未穩(wěn)定測(cè)了也白測(cè)實(shí)際教訓(xùn)是功能每完成一個(gè)切片就該立刻拿到不同類(lèi)型的手機(jī)上跑一遍哪怕只是看界面布局和基礎(chǔ)交互。6.3 復(fù)制這套打法的最小行動(dòng)清單如果你也準(zhǔn)備啟動(dòng)一個(gè)從模糊需求到上線的 App 項(xiàng)目我建議你至少做到這六件事。第一拿到一句話需求后先用訪談拆分角色不要急著列功能。第二把功能定義成帶驗(yàn)收標(biāo)準(zhǔn)的用戶故事用 FDE 的思路控制范圍。第三把上線日期設(shè)為硬錨點(diǎn)需求變更只能改范圍不能改日期。第四按周交付垂直切片每周五做三問(wèn)驗(yàn)收。第五第 8 周就讓真實(shí)用戶上手用數(shù)據(jù)反推產(chǎn)品調(diào)整。第六上線前兩周集中處理隱私政策、權(quán)限聲明、真機(jī)測(cè)試、灰度策略、崩潰上報(bào)這五件事缺一不可。這套打法不一定適合所有團(tuán)隊(duì)——如果你們有足夠資源同時(shí)鋪開(kāi)多個(gè)功能那節(jié)奏可以更激進(jìn)。但如果你和我一樣只有有限的人力和 90 天窗口那么克制范圍、固定節(jié)奏、提前暴露風(fēng)險(xiǎn)就是最穩(wěn)妥的路。WorkBuddy 項(xiàng)目已經(jīng)上線運(yùn)行回頭看那段從一句話需求到應(yīng)用商店上架的旅程最值得留住的不是最終代碼而是過(guò)程中反復(fù)驗(yàn)證的那套判斷標(biāo)準(zhǔn)什么時(shí)候該堅(jiān)持什么時(shí)候該砍掉。