INVEST 原則 - 用來檢查 Story 是否夠好
在敏捷開發中,我們常會遇到這樣的問題:
Story 看起來拆了很多,但實際上還是估不出點、交不出去、無法驗收
這時問題很可能不是「拆錯了」,而是「這些 Story 的品質根本不夠好」
這篇文章會介紹一個經典檢查法:INVEST 原則
INVEST 是什麼?
INVEST 是由 Bill Wake 提出的一個縮寫,用來描述「一個好的 User Story」應該具備的 6 個特徵:
- Independent(獨立)
- Negotiable(可協商)
- Valuable(有價值)
- Estimable(可以估算)
- Small(夠小)
- Testable(可驗收)
Agile 團隊花很多時間在溝通與理解 User Story,是值得的投資。INVEST 提供了一組判斷故事品質的共通語言
Independent(獨立)
好的 Story 應該能獨立被開發、測試與交付,不依賴其他 Story
如果完成這則 Story,產品就能增加一點點可交付的價值,那就算是獨立的
範例一:忘記密碼流程
原本:
- 使用者要先有登入功能才能做忘記密碼功能
- 忘記密碼流程依賴登入頁面出現錯誤才進行
這樣設計會讓「忘記密碼」的實作時程被「登入」綁住
改寫後:
- 「As a 使用者,我可以透過 email 發送重設密碼連結」
- 「As a 使用者,我可以點選忘記密碼按鈕進入密碼重設頁」
這兩個 Story 可以先做,不必等登入功能完成,各自有價值、可測試與驗收
範例二:訂閱通知 vs 設定通知時間
原本:
- 使用者要先訂閱通知,才能設定通知時間
- 所以只能做成一個大 Story
這種方式會讓驗收卡在某一方功能尚未完成
改寫後:
- 「As a 使用者,我可以訂閱每日通知」
- 「As a 使用者,我可以設定每日通知的時間」
雖然兩者邏輯相關,但設計得好可以讓前者先上線,後者作為 enhancement
每個 Story 都能獨立帶來用戶價值
技術上有依賴 ≠ 價值上無法交付
有些功能在開發順序上確實會有「前後依賴」,例如顯示單一資料 → 顯示清單 → 加入篩選與排序功能
這些稱為 sequential dependencies(順序性依賴)
但只要每個功能都能獨立交付對使用者有價值的部分,它仍然是好的 Story
也就是說:即使做到一半被迫停工,只完成前幾個 Story,產品依然能交付,而不是完全沒用
這就是 INVEST 原則中「獨立(Independent)」想強調的價值
Negotiable(可協商)
User Story 不是規格書,而是對話的起點
它應該是 留有空間給團隊討論的需求草稿,而不是開發被命令去做的詳細指令
一個好 Story 是可以討論「怎麼實作」、而不是「一定要這樣實作」
這樣團隊能在限制內找到最有效的方法,而不是被過度規格綁住
範例:
- ❌ 不可協商的 Story:「每天早上 8 點,推播 3 則優惠訊息給所有使用者」
這樣的寫法把實作方式寫死了,沒有討論空間
- ✅ 可協商的 Story:「As a 行銷人員,我希望可以定期推播優惠訊息給使用者,以提升活動參與率」
這樣寫法保留「目的是什麼」,讓團隊能討論:
- 是用 email 還是 app 推播?
- 一天幾則比較好?頻率怎麼控制?
- 有沒有要根據使用者偏好調整內容?
Valuable(有價值)
敏捷團隊的目標很簡單:在現有的時間和資源限制內提供最大的價值
因此價值是 INVEST 模型中最重要的
每一個 Story 都應該能為使用者、顧客或產品負責人創造某種價值
如果做完沒有人受益、或沒有人關心,那就不是好 Story,而是浪費資源
範例:
- ✅ 「我可以下載報表」是有價值的(能完成某任務)
- ❌ 「重構 error log system」雖然有技術價值
- ✅ 要轉成:「As a 消費者,我可以在產品的任何地方收到一致且清晰的錯誤訊息,以便知道如何解決問題」才是對使用者有意義的 Story
- ✅ 或是:「As a Support 工程師,我希望用戶能夠在應用程式的任何地方收到一致且清晰的訊息,以便他們無需致電支援人員即可解決問題」
蛋糕切法的比喻
常見錯誤:我們很容易用「系統結構」來拆功能,例如:
- 先做資料庫欄位
- 再做 API
- 最後才做 UI 顯示
但這樣會讓「有價值的交付」被延後,因為每一層自己沒價值,要等到全部做好才有意義
「整個 Story 就像一個多層蛋糕(資料層、邏輯層、UI 層)」
當我們橫向拆,只做其中一層,就像只吃到蛋糕的餅乾底部,對顧客來說沒什麼味道
我們真正該做的是:
「直向切蛋糕」- 讓每一個 Story 包含一點資料、一點邏輯、一點顯示,讓使用者能完整體驗某個功能
這樣的 Story 才有機會提早帶來價值,獲得早期回饋
範例
- ❌ 錯誤拆法(技術導向):
- 實作 DB schema
- 實作 REST API
- 建 UI 畫面
- ✅ 正確拆法(價值導向):
- 使用者可以查詢商品列表,並看到名稱與價格
這樣你就能:
- 提早測試資料流是否正確
- 先獲得部分功能回饋
- 每個 Story 都是「可以 demo、可以交付」的單位
Estimable(可以估算)
一個好的 Story,團隊應該能大致估得出工作量,才能安排進 Sprint
如果大家無法估點,通常代表:
- 太大 → 要拆小
- 太模糊 → 要釐清內容
- 有未知 → 可以先做 Spike Item
為什麼「能估點」這麼重要?
估點不是為了要多準,而是為了讓團隊 對這個故事有共識
當大家能一起說出:「我們大概知道這是什麼,要花多少 effort」,表示:
- 任務內容夠明確
- 驗收標準有方向
- 不會開發到一半才發現漏洞
小提醒
無法估點 ≠ 團隊技術差,
而是代表這個 Story 可能「寫得不夠好」
遇到不能估的情況,我們不用硬猜,而是可以退一步問自己:
- 這是不是太大了?能不能分開?
- 有沒有什麼條件還沒說清楚?
- 有哪些風險是現在不知道的?
只要先釐清問題點,很多「無法估」的故事,都可以變成可預測的工作單位
實務建議
如果 Story 不確定、風險高,也可以先安排:
- 技術 Spike Item
- UX Spike Item
這些也可以放進 Sprint 裡,幫助團隊把未知變已知
所以 估點的本質不是猜工作量,而是確認「我們知道自己在做什麼」
Small(夠小)
Story 要小,小到能在一個 Sprint 內完成,甚至理想情況是 1 ~ 3 天內可搞定
從 Lean (精實) 的觀點來看,小 Story 有兩大好處:
- Increased Throughput 增加吞吐量:小故事通得快 → 回饋快 → 品質高
- Decreased Complexity 降低複雜度:小功能少錯誤,測試與驗收都更容易
Testable(可驗收)
若 Story 沒辦法測試,那它也無法進入 Sprint
寫 Story 時要問:「做完後,我能怎麼知道它完成了?」
避免模糊詞:
- ❌ 「UX 要流暢」、「系統要穩定」、「表單填寫方便」
- ✅ 「表單填錯會顯示紅框,並顯示錯誤訊息」
越明確的 Story → 越能寫測試、越能驗收、越不會吵架
結語:用 INVEST 幫你自動過濾壞 Story
每次寫完一個 Story,都可以問自己:
- 它能單獨開發嗎?(I)
- 有留下實作空間嗎?(N)
- 對使用者有價值嗎?(V)
- 能估點嗎?(E)
- Sprint 內做得完嗎?(S)
- 做完可以驗收嗎?(T)
能回答越多「是」,這個 Story 就越值得被放進 Sprint