Post

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

參考資料

This post is licensed under CC BY 4.0 by the author.