昨天完成了 PRD 文件,確定了 DDD + BDD 的混合開發模式。今天要實踐這個策略:用 Event Storming 挖掘領域知識,用 BDD 定義行為場景,最後轉化為精準的 User Story。
記帳是一個領域知識密集但用戶行為簡單的應用。DDD 幫我們理解金錢、週期、預算這些複雜概念,BDD 確保用戶的每個動作都符合預期。
今天的目標:結合兩種方法論的優勢,產出可執行的需求規格。
我和 AI 開始了虛擬的 Event Storming 工作坊。第一步:不管順序,列出所有可能的領域事件。
初始事件風暴(30分鐘):
💰 支出領域
- 支出已記錄 (ExpenseRecorded)
- 支出已分類 (ExpenseCategorized)  
- 支出已修改 (ExpenseModified)
- 分類已學習 (CategoryLearned)
- 重複支出已識別 (DuplicateExpenseDetected)
📊 預算領域
- 預算已設定 (BudgetSet)
- 預算已消耗 (BudgetConsumed)
- 預算已超支 (BudgetExceeded)
- 預算警告已觸發 (BudgetWarningTriggered)
- 預算已重置 (BudgetReset)
🔄 訂閱領域
- 訂閱已識別 (SubscriptionIdentified)
- 訂閱已創建 (SubscriptionCreated)
- 帳單已生成 (BillGenerated)
- 訂閱已續約 (SubscriptionRenewed)
- 訂閱已取消 (SubscriptionCancelled)
🤖 AI 領域
- 模式已識別 (PatternIdentified)
- 信心度已更新 (ConfidenceUpdated)
- 異常已偵測 (AnomalyDetected)
- 建議已生成 (RecommendationGenerated)
📈 報表領域
- 資料已聚合 (DataAggregated)
- 報表已生成 (ReportGenerated)
- 洞察已發現 (InsightDiscovered)
- 趨勢已分析 (TrendAnalyzed)
命令對應表:
| 觸發者 | 命令 | 事件 | 
|---|---|---|
| 用戶 | RecordExpense | ExpenseRecorded | 
| AI分類器 | CategorizeExpense | ExpenseCategorized | 
| 用戶 | CorrectCategory | CategoryLearned | 
| 系統排程 | CheckSubscriptions | BillGenerated | 
| 預算監控器 | CheckBudgetStatus | BudgetWarningTriggered | 
| 分析引擎 | AnalyzeSpending | PatternIdentified | 
發現了四條主要時間軸,彼此交織但各自獨立:
時間軸 1:即時記帳流(Real-time Entry Flow)
用戶輸入 → 文字解析 → AI分類 → 儲存確認 → 
預算檢查 → 模式學習 → 統計更新
時間軸 2:訂閱生命週期(Subscription Lifecycle)
重複偵測 → 訂閱建議 → 用戶確認 → 
週期計算 → 定期生成 → 續約/取消
時間軸 3:預算守護流(Budget Guardian Flow)
預算設定 → 即時追蹤 → 閾值檢查 → 
智慧提醒 → 用戶調整 → 週期重置
時間軸 4:洞察生成流(Insight Generation Flow)
資料累積 → 模式分析 → 異常識別 → 
洞察生成 → 故事化呈現 → 建議行動
Event Storming 過程中浮現的核心業務規則:
規則 1:分類學習規則
規則 2:訂閱識別規則
規則 3:預算彈性規則
規則 4:智慧提醒規則
現在把 Event Storming 發現的領域知識,轉換成 BDD 的 Given-When-Then 場景。
Feature: 快速自然語言記帳
  作為一個懶惰的用戶
  我想要用最簡單的方式記帳
  以便不會因為麻煩而放棄
  Background:
    Given 我已經登入 PocketSmart
    And AI 分類服務正常運作
  Scenario: 極簡輸入 - 只有描述和金額
    Given 我在記帳輸入框
    When 我輸入 "咖啡 120"
    Then 系統應該解析出金額 120 元
    And 描述應該是 "咖啡"
    And AI 應該自動分類為 "飲料"
    And 整個過程應該在 3 秒內完成
  Scenario: 智慧學習 - 記住我的習慣
    Given 我曾經將 "麥當勞" 分類為 "正餐"(而非預設的"速食")
    When 我輸入 "麥當勞 150"
    Then AI 應該分類為 "正餐"
    And 顯示 "根據您的習慣" 提示
  Scenario: 低信心度處理 - 不確定時詢問
    Given 這是我第一次輸入 "美廉社"
    When 我輸入 "美廉社 523"
    And AI 信心度低於 70%
    Then 顯示分類選項 ["日用品", "食材", "其他"]
    And 預選最可能的選項
    And 記錄我的選擇供未來學習
  Scenario: 批量記帳 - 一次記多筆
    Given 我想要補記多筆消費
    When 我輸入:
      """
      早餐 65
      捷運 30
      午餐 120
      """
    Then 系統應該識別出 3 筆消費
    And 分別正確分類
    And 顯示批量記帳成功
Feature: 智慧訂閱識別與管理
  作為一個有很多訂閱的用戶
  我想要系統自動追蹤我的訂閱
  以便了解真實的固定支出
  Scenario: 自動識別訂閱
    Given 我在過去兩個月記錄了:
      | 日期 | 描述 | 金額 |
      | 1/15 | Netflix | 390 |
      | 2/15 | Netflix | 390 |
    When 我輸入 "Netflix 390" 在 3/15
    Then 系統應該提示 "這似乎是訂閱服務"
    And 詢問 "是否設為每月自動記錄?"
    When 我確認是訂閱
    Then 創建月付訂閱 "Netflix"
    And 下次扣款日設為 4/15
  Scenario: 訂閱異常提醒
    Given 我有一個訂閱 "Spotify" 每月 15 號扣款 149 元
    And 現在是 3/20
    And 本月還沒有 Spotify 的記錄
    When 系統執行每日檢查
    Then 發送提醒 "Spotify 本月尚未扣款,是否已取消?"
  Scenario: 訂閱成本透明化
    Given 我有以下訂閱:
      | 名稱 | 月費 | 類型 |
      | Netflix | 390 | 娛樂 |
      | ChatGPT | 600 | 工具 |
      | iCloud | 30 | 工具 |
    When 我查看訂閱總覽
    Then 顯示月總成本 1,020 元
    And 顯示年度成本 12,240 元
    And 按類別顯示佔比圖表
Feature: 智慧預算管理
  作為想要控制支出的用戶
  我想要有彈性的預算管理
  以便在不感到壓力的情況下省錢
  Scenario: 漸進式預算警告
    Given 我的餐飲預算是每月 5,000 元
    And 目前已消費 4,000 元
    When 我記錄一筆餐飲支出 200 元
    Then 顯示黃色提醒 "餐飲預算已使用 84%"
    And 顯示剩餘額度 800 元
    And 提供建議 "剩餘 10 天,建議每日 80 元"
  Scenario: 預算超支協商
    Given 我的娛樂預算是每月 2,000 元
    And 目前已消費 2,000 元
    When 我嘗試記錄 "電影票 350"
    Then 顯示確認對話框:
      """
      娛樂預算已用完,這筆支出會超支 350 元
      [堅持記錄] [改為其他分類] [取消]
      """
    When 我選擇 "堅持記錄"
    Then 記錄支出但標記為超支
    And 月報表中特別標示
  Scenario: 智慧預算建議
    Given 這是我第一次設定預算
    And 我過去 3 個月的消費記錄存在
    When 我點擊 "AI 建議預算"
    Then 基於歷史資料顯示:
      | 類別 | 平均消費 | 建議預算(適中) |
      | 餐飲 | 4,800 | 5,000 |
      | 交通 | 1,200 | 1,500 |
      | 娛樂 | 2,500 | 2,000 |
    And 提供說明 "娛樂建議降低因為上月有演唱會異常支出"
Feature: 個人化消費洞察
  作為想要了解消費習慣的用戶
  我想要有意義的分析報告
  以便做出更好的財務決定
  Scenario: 月度故事化報告
    Given 月底系統生成報告
    When 我查看 3 月報告
    Then 看到故事化描述:
      """
      【3月消費故事】
      本月總支出 24,500 元,比上月減少 8%!
      
      🏆 最大成就:餐飲支出降低 1,200 元
      ⚠️ 注意事項:訂閱服務增加了 Netflix(390元/月)
      💡 發現模式:週五的餐飲支出是平日的 2.3 倍
      
      如果保持這個節奏,年底可以多存 15,000 元!
      """
  Scenario: 異常消費警示
    Given 我平常的單筆餐飲消費都在 200 元以下
    When 我輸入 "聚餐 1,200"
    Then 標記為異常消費
    And 詢問 "這是特殊情況嗎?"
    When 我標記為 "特殊"
    Then 不計入平均消費
    And 在報表中分開顯示
  Scenario: 個人化省錢建議
    Given 系統分析我的消費模式
    When 月中觸發分析
    Then 提供具體可行的建議:
      """
      💰 省錢機會發現:
      
      1. 每週五的下午茶平均 180 元
         → 改為每兩週一次,月省 360 元
      
      2. Netflix 與朋友共享
         → 月省 195 元
      
      3. 早餐從超商改為早餐店
         → 根據歷史資料,平均可省 20 元/次
      
      預估月省總額:1,155 元
      """
結合 DDD 的領域事件和 BDD 的行為場景,我們可以寫出更精準的 User Story,並且包含清晰的驗收條件。
User Story 1.1:自然語言快速記帳
標題: 三秒完成記帳
角色: 懶惰的記帳用戶
故事: 
  As a 懶惰的記帳用戶
  I want to 用一句話完成記帳
  So that 不會因為麻煩而放棄記帳
驗收條件 (BDD):
  Scenario: 基本記帳
    Given 我在記帳頁面
    When 輸入 "拿鐵 120"
    Then 3秒內完成記帳
    And 自動分類為 "飲料"
  
  Scenario: 批量補記
    When 輸入多行文字
    Then 每行都被正確解析
    And 失敗項目單獨標記
領域事件:
  - ExpenseRecorded
  - ExpenseCategorized
  - CategoryLearned
估點: 8
優先級: P0
User Story 1.2:AI 分類學習
標題: 記住我的分類習慣
角色: 有固定消費模式的用戶
故事:
  As a 有固定消費模式的用戶
  I want to 系統記住我的分類偏好
  So that 不用每次都手動選擇
驗收條件 (BDD):
  Scenario: 學習用戶習慣
    Given 我修正過 3 次同類分類
    When 再次輸入相似消費
    Then 自動採用我的分類
    And 顯示 "根據您的習慣"
  
  Scenario: 低信心度處理
    When AI 信心度 < 70%
    Then 提供分類選項
    And 記錄選擇供學習
領域事件:
  - CategoryLearned
  - ConfidenceUpdated
  - PatternIdentified
估點: 5
優先級: P0
User Story 2.1:自動識別訂閱
標題: 發現我的訂閱服務
角色: 訂閱多個服務的用戶
故事:
  As a 訂閱多個服務的用戶
  I want to 系統自動發現訂閱
  So that 清楚知道固定支出
驗收條件 (BDD):
  Scenario: 重複支出識別
    Given 連續2個月相同金額
    When 第3次出現
    Then 提示轉換為訂閱
    
  Scenario: 關鍵字識別
    When 描述含"月費"
    Then 直接建議創建訂閱
領域事件:
  - SubscriptionIdentified
  - SubscriptionCreated
  - BillGenerated
估點: 8
優先級: P1
User Story 2.2:訂閱異常管理
標題: 訂閱異常提醒
角色: 容易忘記取消訂閱的用戶
故事:
  As a 容易忘記的用戶
  I want to 收到訂閱異常提醒
  So that 及時處理訂閱變化
驗收條件 (BDD):
  Scenario: 未扣款提醒
    Given 超過預期扣款日 5 天
    When 系統每日檢查
    Then 發送提醒確認狀態
    
  Scenario: 金額變動提醒
    When 扣款金額與設定不同
    Then 提醒並更新資訊
領域事件:
  - AnomalyDetected
  - SubscriptionCancelled
  - NotificationSent
估點: 5
優先級: P1
User Story 3.1:彈性預算管理
標題: 人性化的預算控制
角色: 想省錢但不想被限制的用戶
故事:
  As a 想控制支出的用戶
  I want to 有彈性的預算管理
  So that 不會因太嚴格而放棄
驗收條件 (BDD):
  Scenario: 漸進式提醒
    Given 預算消耗 80%
    Then 溫和提醒剩餘額度
    
  Scenario: 超支協商
    Given 預算已用完
    Then 詢問是否繼續
    And 可選擇其他分類
領域事件:
  - BudgetConsumed
  - BudgetWarningTriggered
  - BudgetExceeded
估點: 5
優先級: P2
User Story 4.1:故事化月報表
標題: 看得懂的月度報告
角色: 不懂財務但想理財的用戶
故事:
  As a 不懂財務的用戶
  I want to 看到故事化的報告
  So that 真正理解我的消費
驗收條件 (BDD):
  Scenario: 月度故事生成
    Given 月底
    When 生成報告
    Then 用故事描述消費
    And 標出關鍵成就
    And 提供具體建議
領域事件:
  - ReportGenerated
  - InsightDiscovered
  - TrendAnalyzed
估點: 8
優先級: P1
DDD 的事件告訴我們「系統裡會發生什麼」,BDD 的場景告訴我們「用戶期待什麼行為」。兩者結合,我們得到了:
DDD 強調建立通用語言,BDD 的 Gherkin 語法天然就是通用語言。當我說「訂閱已識別」,無論是領域專家、開發者還是測試人員,都理解是什麼意思。
每個 User Story 都有對應的 BDD 場景,每個場景都觸發特定的領域事件。這讓我們的程式碼有了雙重保障:
AI 在這個過程中扮演了多重角色:
經過今天的 DDD + BDD 雙重設計,我們得到了: