Ticket 設計派工方法論
方法論概述
這裡嘗試以 Ticket 設計和派工機制,解決大型開發任務的協作效率問題,特別是工作日誌臃腫和實作偏差風險。
但是這篇方法論太長了,之後會分拆成多個方法論方便閱讀
適用場景:
- 多人協作開發
- 大型功能模組開發
- 需要精細進度追蹤的專案
- 需要即時 review 機制的團隊
核心目標:
- 建立量化的 Ticket 拆分標準
- 定義完整的 Ticket 生命週期
- 建立即時 Review 機制
- 避免工作日誌臃腫
方法論版本:v1.0.0
第一章:Ticket 機制核心原則
1.1 Ticket vs 工作日誌的定位差異
Ticket 定義:
Ticket 是「最小可交付單元」(Minimal Deliverable Unit),代表一個可以獨立完成、驗收和追蹤的最小任務單位。
核心特徵:
- 獨立性:可以獨立執行和驗收
- 原子性:不可再分割為更小的可交付單元
- 可驗證性:有明確的完成標準
- 複雜度限制:基於職責、檔案、測試、行數的量化標準
工作日誌定義:
工作日誌是記錄整個開發過程的完整文檔,包含設計決策、實作細節、問題分析和解決方案。
核心特徵:
- 完整性:記錄所有決策和過程
- 追溯性:提供歷史記錄和演進軌跡
- 知識傳承:為後續開發者提供上下文
定位差異總結:
| 維度 | Ticket | 工作日誌 |
|---|---|---|
| 範圍 | 單一具體任務 | 整個功能模組或版本 |
| 粒度 | 最小可交付單元(單一職責或少數相關職責) | 完整開發週期(數天到數週) |
| 目的 | 任務執行和驗收 | 知識記錄和傳承 |
| 更新頻率 | 執行中持續更新 | 階段性更新 |
| 文件大小 | 100-200 行 | 500-6000 行 |
| 適用場景 | 協作開發、進度追蹤 | 決策記錄、技術傳承 |
互補關係:
Ticket 和工作日誌是互補關係:
- Ticket 負責「執行層面」:將大任務拆分為可管理的小單元
- 工作日誌 負責「記錄層面」:記錄決策過程和演進軌跡
- 主版本日誌 負責「總覽層面」:提供任務總覽和 Ticket 索引
1.2 Ticket 機制的三大目標
目標 1:可追溯性(Traceability)
定義:每個 Ticket 都有明確的來源和目標,可以追溯到需求、設計文件或問題報告。
實現方式:
- Ticket 必須包含「參考文件」欄位,連結到需求規格或設計文件
- Ticket 必須包含「背景」欄位,說明為什麼需要這個 Ticket
- 主版本日誌維護完整的 Ticket 索引
範例:
1### 參考文件
2- v0.12.7-design-decisions.md #決策1
3- docs/app-requirements-spec.md #UC-01
4
5### 背景
6根據 UC-01 需求,需要建立書籍資訊豐富化服務的介面契約效益:
- 開發者清楚知道「為什麼」要做這個任務
- PM 可以追蹤每個 Ticket 的需求來源
- 後續維護者可以理解設計意圖
目標 2:可驗收性(Verifiability)
定義:每個 Ticket 都有明確、可驗證的完成標準,避免主觀判斷。
實現方式:
- Ticket 必須包含「驗收條件」欄位,列出所有可驗證的條件
- 驗收條件必須是客觀可檢查的(檔案存在、測試通過、功能運作)
- Review 時逐項檢查驗收條件
範例:
1### 驗收條件
2- [ ] 介面檔案建立在 `lib/domains/import/services/` 目錄
3- [ ] `enrichBook` 方法簽名完整且明確
4- [ ] 輸入輸出類型定義清楚
5- [ ] 包含完整的文檔註解
6- [ ] dart analyze 0 錯誤效益:
- 避免「看起來完成了」但實際未達標準
- 提供明確的驗收依據
- 減少 review 時的主觀爭議
目標 3:可協作性(Collaborability)
定義:多個開發者可以並行執行不同的 Ticket,互不阻塞。
實現方式:
- Ticket 拆分時考慮依賴關係,最小化依賴
- 明確標註 Ticket 間的依賴關係(必須先完成 / 可並行)
- 使用 Interface-Driven 開發,內層未完成也可開發外層
範例:
1### 依賴 Ticket
2- Ticket #1: 定義 IBookInfoEnrichmentService 介面(必須先完成)
3- Ticket #3: 撰寫 EnrichmentProgress 測試(可並行)效益:
- 多人可同時開發不同模組
- 減少等待時間
- 提升開發效率
1.3 基於 Clean Architecture 的 Ticket 設計哲學
Clean Architecture 核心原則回顧
依賴方向規則:
- 外層依賴內層,內層不依賴外層
- 所有依賴都指向內層(Domain)
分層定義:
- Entities(Domain):核心業務邏輯
- Use Cases(Application):應用業務規則
- Interface Adapters(Presentation/Infrastructure):轉接層
- Frameworks & Drivers(External):外部實作
Ticket 設計對應 Clean Architecture
原則 1:Interface 定義優先於具體實作
每個功能模組的開發順序:
- 先定義 Interface(Ticket 類型:Interface 定義)
- 再實作具體邏輯(Ticket 類型:具體實作)
範例:
1Ticket #1: 定義 IBookRepository 介面
2 ↓
3Ticket #2: 實作 SQLiteBookRepository(依賴 #1)好處:
- 外層可依賴 Interface 先行開發(使用 Mock)
- 內層實作延後,不阻塞外層開發
- 符合 Dependency Inversion Principle
原則 2:測試驅動 Ticket 拆分
每個實作 Ticket 都應該有對應的測試 Ticket:
- Interface 定義 Ticket → 定義契約
- 測試撰寫 Ticket → 驗證契約
- 具體實作 Ticket → 實現契約
- 整合驗證 Ticket → 確認整合
範例:
1Ticket #1: 定義 IBookRepository 介面
2 ↓
3Ticket #2: 撰寫 BookRepository 測試
4 ↓
5Ticket #3: 實作 SQLiteBookRepository
6 ↓
7Ticket #4: 整合測試驗證好處:
- 測試先行,確保需求清晰
- 實作以測試為目標,不過度設計
- 整合驗證確保模組間正確協作
原則 3:分層拆分 Ticket
基於 Clean Architecture 分層,將任務拆分為不同層次的 Ticket:
Domain 層 Ticket:
- 定義 Entity
- 定義 Value Object
- 定義 Domain Event
- 定義 Repository Interface
Application 層 Ticket:
- 定義 Use Case Interface
- 實作 Use Case Interactor
- 定義 Input/Output Port
Infrastructure 層 Ticket:
- 實作 Repository
- 實作 External Service
- 實作 Database Mapper
Presentation 層 Ticket:
- 實作 Controller/Presenter
- 實作 ViewModel
- 實作 UI Component
好處:
- 職責清晰,不跨層混合
- 符合 Clean Architecture 分層原則
- 易於並行開發
1.4 Ticket 機制與 TDD 階段的關係
TDD 階段回顧
- Phase 1:功能設計(設計 Interface、規劃架構)
- Phase 2:測試設計(撰寫測試案例)
- Phase 3:實作執行(實作功能、通過測試)
- Phase 4:重構優化(改善品質、消除技術債務)
Ticket 與 TDD 階段對應
Phase 1 產出的 Ticket:
Phase 1 設計階段產出「Interface 定義 Ticket」:
- 定義 Domain Interface
- 定義 Use Case Interface
- 定義 Input/Output Port
特徵:
- 無具體實作,只有介面簽名
- 明確定義輸入輸出
- 建立契約規範
Phase 2 產出的 Ticket:
Phase 2 測試設計階段產出「測試撰寫 Ticket」:
- 撰寫 Entity 測試
- 撰寫 Use Case 測試
- 撰寫 Repository 測試
特徵:
- 測試先行,定義預期行為
- 覆蓋所有 Interface 方法
- 包含正常流程和異常處理
Phase 3 產出的 Ticket:
Phase 3 實作階段產出「具體實作 Ticket」:
- 實作 Entity 邏輯
- 實作 Use Case Interactor
- 實作 Repository
特徵:
- 以測試通過為目標
- 最小可行實作
- 100% 測試通過
Phase 4 產出的 Ticket:
Phase 4 重構階段產出「品質改善 Ticket」:
- 重構複雜邏輯
- 消除程式異味
- 改善錯誤處理
特徵:
- 保持測試通過
- 改善程式品質
- 不新增功能
Ticket 機制支援 TDD 流程
支援 1:明確的階段產出
每個 TDD Phase 都產出對應的 Ticket 類型,職責清晰。
支援 2:可並行執行
Phase 1 完成後,多個開發者可並行執行 Phase 2-3 的不同 Ticket。
支援 3:即時 Review
每完成一個 Ticket 觸發 review,確保品質。
第二章:Ticket 拆分標準
2.1 量化指標定義
為了確保 Ticket 拆分的一致性和可操作性,定義以下 4 個量化指標。
核心原則**:**基於客觀的工作內容評估
- 職責數量:最客觀,不受個人能力影響- 程式碼行數:可量化,可驗證- 檔案數量:架構層級指標- 測試數量:品質保證指標
指標 1:職責數量(Responsibilities)(最優先)
定義:Ticket 需要完成的獨立職責數量。
標準:
- 簡單 Ticket:1 個明確職責
- 中等 Ticket:2-3 個相關職責
- 複雜 Ticket:3-5 個相關職責
- 超過 5 個職責:必須拆分
識別方式:
- 每個「需要實作的功能點」算一個職責
- 每個「需要驗證的邊界條件」算一個職責
- 每個「需要處理的錯誤情境」算一個職責
範例:
- 簡單(1 職責):定義 SelectionManager 介面方法簽名
- 中等(2-3 職責):
- 職責 1: 實作 toggleSelection 方法
- 職責 2: 實作 clearSelection 方法
- 職責 3: 通知狀態變更(ChangeNotifier)
- 複雜(3-5 職責):
- 職責 1: Repository CRUD 實作
- 職責 2: Data Mapper 轉換
- 職責 3: 錯誤處理
- 職責 4: Cache 管理
- 職責 5: 單元測試
為什麼職責是第一指標:
- 最客觀:不受個人能力影響- 最穩定:不受環境和參考資料影響- 最易溝通:PM 和工程師都能理解
指標 2:程式碼行數(Lines of Code)
定義:Ticket 涉及的程式碼修改行數(新增 + 修改 + 刪除)。
標準:
- 簡單 Ticket:< 30 行
- 中等 Ticket:30-50 行
- 複雜 Ticket:50-100 行
- 超過 100 行:必須拆分
測量方式:
- 使用
git diff --stat統計 - 包含新增、修改、刪除的行數總和
- 不包含空行和註解
範例:
- 簡單:定義 Interface(~20 行)
- 中等:實作 Value Object(~40 行)
- 複雜:實作 Repository(~80 行)
指標 3:涉及檔案數(Files)
定義:Ticket 需要修改的檔案數量。
標準:
- 簡單 Ticket:1 個檔案
- 中等 Ticket:2-3 個檔案
- 複雜 Ticket:3-5 個檔案
- 超過 5 個檔案:必須拆分
測量方式:
- 計算
git diff --name-only的檔案數 - 包含新建檔案
- 不包含測試檔案(測試檔案另計)
範例:
- 簡單:新建一個 Interface 檔案(1 個)
- 中等:修改 Entity 和 Repository Interface(2 個)
- 複雜:實作 Use Case,修改 Interactor、Input Port、Output Port(3 個)
指標 4:測試用例數(Tests)
定義:Ticket 對應的測試用例數量。
標準:
- 簡單 Ticket:1-3 個測試
- 中等 Ticket:3-5 個測試
- 複雜 Ticket:5-10 個測試
- 超過 10 個測試:必須拆分
測量方式:
- 計算 test 檔案中的測試方法數
- 包含單元測試和整合測試
- 每個
test('...', () {...})算一個
範例:
- 簡單:測試 Value Object 的建立和驗證(2 個測試)
- 中等:測試 Repository 的 CRUD 操作(4 個測試)
- 複雜:測試 Use Case 的正常流程和異常處理(8 個測試)
2.2 任務複雜度評估方法
基於 4 個量化指標,定義任務複雜度評估方法:
複雜度等級定義:
| 等級 | 職責 | 檔案 | 測試 | 行數 | 描述 |
|---|---|---|---|---|---|
| 簡單 | 1 個 | 1 個 | 1-3 個 | < 30 行 | 單一職責,單一檔案 |
| 中等 | 2-3 個 | 2-3 個 | 3-6 個 | 30-70 行 | 少數職責,少數檔案 |
| 複雜 | 3-5 個 | 3-5 個 | 6-10 個 | 70-100 行 | 多職責,多檔案 |
| 需拆分 | > 5 個 | > 5 個 | > 10 個 | > 100 行 | 任一指標超標必須拆分 |
評估方法:
步驟 1:初步評估
- 根據任務描述,估算 4 個指標
- 取最高的複雜度等級作為初步評估結果
步驟 2:複雜度確認
- 如果初步評估為「需拆分」,必須拆分
- 如果初步評估為「複雜」,檢查是否可拆分為「簡單」或「中等」
- 如果初步評估為「中等」或「簡單」,可直接建立 Ticket
步驟 3:拆分決策
- 優先拆分為「簡單」Ticket(單一職責、單一檔案)
- 無法拆分為「簡單」時,拆分為「中等」Ticket(2-3 職責)
- 避免建立「複雜」Ticket(3-5 職責),除非無法再拆分
2.3 基於 Clean Architecture 分層的拆分策略
基於 Clean Architecture 的分層原則,定義 4 種標準拆分策略:
策略 1:Interface 定義 Ticket
目的:定義一個介面及其輸入輸出契約。
範圍:
- 定義 Interface 簽名
- 定義輸入參數類型
- 定義回傳類型
- 撰寫文檔註解
範例:
1## Ticket #1: 定義 IBookRepository 介面
2
3### 目標
4建立 `IBookRepository` 介面,定義書籍資料存取的契約
5
6### 步驟
71. 在 `lib/domains/library/repositories/` 建立 `i_book_repository.dart`
82. 定義 `getBookByIsbn` 方法簽名
93. 定義 `saveBook` 方法簽名
104. 定義 `deleteBook` 方法簽名
115. 撰寫文檔註解
12
13### 驗收條件
14- [ ] Interface 檔案建立在正確位置
15- [ ] 3 個方法簽名完整且明確
16- [ ] 輸入輸出類型定義清楚
17- [ ] 包含完整的文檔註解
18- [ ] dart analyze 0 錯誤策略 2:具體實作 Ticket
目的:實作一個類別的核心邏輯。
範圍:
- 實作類別邏輯
- 實現介面方法
- 處理異常
- 確保測試通過
範例:
1## Ticket #2: 實作 SQLiteBookRepository
2
3### 目標
4實作 `SQLiteBookRepository`,提供書籍資料的 SQLite 儲存
5
6### 步驟
71. 建立 `SQLiteBookRepository` 類別
82. 實作 `getBookByIsbn` 方法
93. 實作 `saveBook` 方法
104. 實作 `deleteBook` 方法
115. 處理 SQLite 異常
126. 確保所有測試通過
13
14### 驗收條件
15- [ ] 實作所有 IBookRepository 方法
16- [ ] 異常處理完整(Database Exception)
17- [ ] 單元測試 100% 通過
18- [ ] dart analyze 0 錯誤
19
20### 依賴 Ticket
21- Ticket #1: 定義 IBookRepository 介面(必須先完成)策略 3:測試驗證 Ticket
目的:撰寫一組相關的測試用例。
範圍:
- 撰寫單元測試
- 覆蓋正常流程
- 覆蓋異常處理
- 確保測試通過
範例:
1## Ticket #3: 撰寫 BookRepository 測試
2
3### 目標
4撰寫 `BookRepository` 的完整測試用例
5
6### 步驟
71. 建立測試檔案 `book_repository_test.dart`
82. 撰寫 `getBookByIsbn` 測試(正常流程 + 不存在情況)
93. 撰寫 `saveBook` 測試(新增 + 更新)
104. 撰寫 `deleteBook` 測試(存在 + 不存在)
115. 確保所有測試通過
12
13### 驗收條件
14- [ ] 測試檔案建立在 `test/unit/domains/library/repositories/`
15- [ ] 至少 6 個測試用例
16- [ ] 覆蓋正常流程和異常處理
17- [ ] 所有測試 100% 通過
18
19### 依賴 Ticket
20- Ticket #1: 定義 IBookRepository 介面(必須先完成)策略 4:整合連接 Ticket
目的:連接兩個模組並驗證整合。
範圍:
- 連接 Use Case 和 Repository
- 實作依賴注入
- 撰寫整合測試
- 驗證端到端流程
範例:
1## Ticket #4: 整合 BookRepository 到 GetBookUseCase
2
3### 目標
4將 `BookRepository` 整合到 `GetBookUseCase`,實現完整流程
5
6### 步驟
71. 修改 `GetBookInteractor` 注入 `IBookRepository`
82. 在 `execute` 方法中呼叫 `repository.getBookByIsbn`
93. 處理 Repository 異常
104. 撰寫整合測試驗證端到端流程
115. 確保所有測試通過
12
13### 驗收條件
14- [ ] `GetBookInteractor` 正確注入 `IBookRepository`
15- [ ] 端到端流程正常運作
16- [ ] 整合測試 100% 通過
17- [ ] 異常處理完整
18
19### 依賴 Ticket
20- Ticket #2: 實作 SQLiteBookRepository(必須先完成)2.4 Code Smell 品質閘門檢測
本節整合 v0.12.G.2「Code Smell 檢查清單」到 Ticket 設計流程,實現「設計階段就能發現 Code Smell」的品質管理策略。
整合目標:
- 在 Ticket 設計階段執行 Code Smell 檢測
- 降低修正成本(設計階段 vs 實作後修正)
- 提供明確的 Ticket 設計品質標準
- 實現預防勝於治療的品質管理
引用方法論:
- 引用 v0.12.G.1「層級隔離派工方法論」的五層架構和單層修改原則
- 引用 v0.12.G.2「Code Smell 檢查清單」的 C 類 Code Smell 檢測方法
2.4.1 品質閘門機制概述
品質閘門定義:
品質閘門(Quality Gate)是 Ticket 設計階段的強制檢查點,確保 Ticket 符合 Code Smell 品質標準後才能進入執行階段。
1Ticket 設計流程整合品質閘門:
2
3Phase 1: 功能設計(lavender-interface-designer)
4 ↓
5 1. 撰寫 Ticket 清單
6 2. 定義驗收條件
7 3. 規劃步驟和檔案
8 ↓
9【品質閘門檢測】← 新增檢測點
10 ├─ C1. God Ticket 檢測
11 ├─ C2. Incomplete Ticket 檢測
12 └─ C3. Ambiguous Responsibility 檢測
13 ↓
14 通過 → Phase 2: 測試驗證
15 未通過 → 修正 Ticket → 重新檢測檢測時機:
| 檢測時機 | 說明 | 執行者 |
|---|---|---|
| Ticket 撰寫完成後 | 所有 Ticket 的內容(背景、目標、步驟、驗收條件)都已撰寫完成 | lavender-interface-designer |
| 分派執行前 | 在將 Ticket 分派給開發者執行前,必須先通過品質閘門 | lavender-interface-designer |
| PM 審查前 | PM 審查時,品質閘門檢測報告是重要參考依據 | lavender-interface-designer |
檢測執行者:
責任歸屬: lavender-interface-designer(TDD Phase 1 功能設計專家)
檢測職責:
- 對每個 Ticket 執行 C1/C2/C3 檢測
- 記錄檢測結果到工作日誌
- 檢測失敗時執行修正
- 提供品質閘門報告給 PM
阻斷機制:
1檢測結果處理:
2
3所有 Ticket 都通過 C1/C2/C3?
4 ├─ Yes → 提交給 PM 審查
5 │ └─ PM 批准 → 分派給開發者執行
6 │
7 └─ No → 阻止進入 Phase 2
8 ├─ 記錄檢測失敗原因
9 ├─ 執行修正(拆分/補充/重新定義)
10 └─ 重新檢測(直到通過)阻斷原則:
- 強制阻斷: 任何 Ticket 未通過 C1/C2/C3 檢測,禁止進入 Phase 2
- 修正優先: 發現問題後立即修正,不延後處理
- 完整記錄: 所有檢測過程和修正過程都記錄到工作日誌
品質閘門價值:
| 價值維度 | 說明 | 效益 |
|---|---|---|
| 及早發現 | 設計階段就能發現 Code Smell | 修正成本降低 80% |
| 標準化 | 提供統一的檢測標準 | 避免主觀判斷 |
| 可追溯 | 完整的檢測記錄 | 提升品質可見性 |
| 預防性 | 預防問題進入實作階段 | 減少返工時間 |
2.4.2 C1. God Ticket 檢測
定義(引用 v0.12.G.2 第 2.3.1 節 God Ticket 定義):
God Ticket 是指單一 Ticket 修改過多檔案和層級,範圍失控,違反「單層修改原則」(引用 v0.12.G.1 第 3.1 節)。
量化檢測指標:
| 指標 | 良好設計 | 需要檢查 | God Ticket(必須拆分) |
|---|---|---|---|
| 檔案數量 | 1-3 個(合格) | 4-6 個(需檢查) | > 10 個(超標) |
| 層級跨度 | 1 層(合格) | 2 層(需檢查) | > 2 層(超標) |
| 預估工時 | 2-4 小時(合格) | 4-8 小時(需檢查) | > 16 小時(超標) |
組合邏輯(Phase 2 補充說明):
1判斷標準:任一項目超標 = God Ticket(需要拆分)
2
3範例:
4
5- 檔案數 = 8 個(未超標)、層級跨度 = 3 層(超標) → God Ticket
6- 檔案數 = 12 個(超標)、層級跨度 = 1 層(未超標) → God Ticket
7- 檔案數 = 5 個(未超標)、層級跨度 = 2 層(未超標)、工時 = 20 小時(超標) → God Ticket
8
9只要有任何一個指標超標,就判定為 God Ticket,必須拆分。檢測方法(Ticket 設計階段):
步驟 1: 列出 Ticket 涉及的檔案清單
從 Ticket 的「步驟」章節中提取所有檔案路徑:
1範例 Ticket 步驟:
2
31. 建立 Rating Value Object(`lib/domain/value_objects/rating_value.dart`)
42. 建立 Rating Entity(`lib/domain/entities/rating.dart`)
53. 更新 Book Entity(`lib/domain/entities/book.dart`)
64. 定義 IRatingRepository(`lib/domain/repositories/i_rating_repository.dart`)
7...
8
9提取檔案清單:
10
11- lib/domain/value_objects/rating_value.dart
12- lib/domain/entities/rating.dart
13- lib/domain/entities/book.dart
14- lib/domain/repositories/i_rating_repository.dart
15...步驟 2: 計算檔案數量
1統計檔案數量(不包含測試檔案):
2 ├─ 1-3 個 → 良好設計
3 ├─ 4-6 個 → 需要檢查(評估是否可拆分)
4 ├─ 7-10 個 → 建議拆分
5 └─ > 10 個 → God Ticket(強制拆分)步驟 3: 判斷層級跨度
使用 v0.12.G.1 第 6.2 節「檔案路徑分析法」判斷每個檔案所屬層級:
1檔案路徑 → 層級對應規則:
2
3Layer 1(UI):
4- lib/presentation/widgets/
5- lib/presentation/pages/
6
7Layer 2(Behavior):
8- lib/presentation/controllers/
9- lib/presentation/providers/
10- lib/presentation/view_models/
11
12Layer 3(UseCase):
13- lib/application/use_cases/
14- lib/application/services/
15
16Layer 4(Domain Events/Interfaces):
17- lib/domain/events/
18- lib/domain/repositories/ (介面)
19- lib/domain/services/ (介面)
20
21Layer 5(Domain Implementation):
22- lib/domain/entities/
23- lib/domain/value_objects/
24- lib/infrastructure/repositories/ (實作)
25- lib/infrastructure/services/ (實作)計算層級跨度:
1範例:
2檔案清單:
3
4- lib/presentation/widgets/rating_widget.dart → Layer 1
5- lib/presentation/controllers/rating_controller.dart → Layer 2
6- lib/application/use_cases/rate_book_use_case.dart → Layer 3
7- lib/domain/entities/rating.dart → Layer 5
8
9層級跨度 = max(5) - min(1) = 4 層(超標)→ God Ticket判斷標準:
1 ├─ 1 層(單層修改)→ 良好設計
2 ├─ 2 層(Facade 整合)→ 需要檢查(可能可接受)
3 └─ > 2 層(跨多層修改)→ God Ticket(強制拆分)步驟 4: 評估預估工時
根據 Ticket 的「步驟」章節複雜度評估:
1評估依據:
2
31. 步驟數量:
4 ├─ < 10 項 → 簡單任務(2-4 小時)
5 ├─ 10-20 項 → 中等任務(4-8 小時)
6 └─ > 20 項 → 複雜任務(> 8 小時)
7
82. 步驟複雜度:
9 ├─ 單純檔案建立或方法定義 → 簡單(x1.0 係數)
10 ├─ 包含邏輯實作和測試 → 中等(x1.5 係數)
11 └─ 包含多層整合和異常處理 → 複雜(x2.0 係數)
12
133. 計算公式:
14 預估工時 = 步驟數量 × 平均每步驟時間 × 複雜度係數
15
16範例:
17
18- 15 個步驟 × 30 分鐘 × 1.5 係數 = 11.25 小時(需檢查)
19- 25 個步驟 × 30 分鐘 × 2.0 係數 = 25 小時(超標)→ God Ticket判斷標準:
1 ├─ 2-4 小時 → 良好設計
2 ├─ 4-8 小時 → 需要檢查
3 ├─ 8-16 小時 → 建議拆分
4 └─ > 16 小時 → God Ticket(強制拆分)檢測失敗處理:
1God Ticket 檢測失敗 → 執行拆分策略
2
3步驟 1: 選擇拆分策略
4 優先策略: 按層級拆分(引用 v0.12.G.1 第 3.1 節單層修改原則)
5 次要策略: 按職責拆分
6 最終策略: 按功能模組拆分
7
8步驟 2: 執行拆分(引用 v0.12.G.1 第 5.4 節 Ticket 拆分指引)
9 範例:14 個檔案、4 層 → 拆分為 5 個 Ticket(每層級 1 個)
10
11步驟 3: 重新檢測
12 對拆分後的每個 Ticket 重新執行 C1 檢測
13 確保所有 Ticket 都通過標準拆分策略決策樹:
1God Ticket 拆分決策:
2
3檔案數量 > 10 或 層級跨度 > 2?
4 └─ Yes → 按層級拆分(優先)
5 ├─ Layer 5: Domain 層 Ticket
6 ├─ Layer 4: Domain 介面層 Ticket
7 ├─ Layer 3: UseCase 層 Ticket
8 ├─ Layer 2: Behavior 層 Ticket
9 └─ Layer 1: UI 層 Ticket
10
11預估工時 > 16 小時?
12 └─ Yes → 按職責拆分(次要)
13 ├─ 職責 1: 資料建模 Ticket
14 ├─ 職責 2: 業務邏輯 Ticket
15 ├─ 職責 3: 介面整合 Ticket
16 └─ 職責 4: UI 呈現 Ticket
17
18職責數量 > 5?
19 └─ Yes → 按功能模組拆分(最終)
20 ├─ 模組 A: 核心功能 Ticket
21 ├─ 模組 B: 輔助功能 Ticket
22 └─ 模組 C: 整合驗證 Ticket檢測範例(完整流程):
原始 Ticket(違反 C1 標準):
1## Ticket: 新增「書籍評分」完整功能
2
3### 背景
4根據 UC-03 需求,需要新增書籍評分功能。
5
6### 目標
7實作書籍評分的完整功能,包含 UI、邏輯、資料儲存。
8
9### 步驟
101. 建立 Rating Value Object(`lib/domain/value_objects/rating_value.dart`)
112. 建立 Rating Entity(`lib/domain/entities/rating.dart`)
123. 更新 Book Entity(`lib/domain/entities/book.dart`)
134. 定義 IRatingRepository(`lib/domain/repositories/i_rating_repository.dart`)
145. 實作 RatingRepositoryImpl(`lib/infrastructure/repositories/rating_repository_impl.dart`)
156. 建立 Rating 資料表(`lib/infrastructure/database/rating_table.dart`)
167. 定義 RateBookUseCase 介面(`lib/application/use_cases/i_rate_book_use_case.dart`)
178. 實作 RateBookUseCase(`lib/application/use_cases/rate_book_use_case.dart`)
189. 定義 GetBookRatingUseCase 介面(`lib/application/use_cases/i_get_book_rating_use_case.dart`)
1910. 實作 GetBookRatingUseCase(`lib/application/use_cases/get_book_rating_use_case.dart`)
2011. 更新 BookDetailController(`lib/presentation/controllers/book_detail_controller.dart`)
2112. 建立 RatingController(`lib/presentation/controllers/rating_controller.dart`)
2213. 建立 RatingWidget(`lib/presentation/widgets/rating_widget.dart`)
2314. 更新 BookDetailWidget(`lib/presentation/widgets/book_detail_widget.dart`)
2415. 撰寫測試C1 檢測執行:
1步驟 1: 列出檔案清單
2 檔案數量 = 14 個
3
4步驟 2: 計算檔案數量
5 14 個 > 10 個 → God Ticket
6
7步驟 3: 判斷層級跨度
8 檔案層級分布:
9 - Layer 5: rating_value.dart, rating.dart, book.dart (3 個)
10 - Layer 5: rating_repository_impl.dart, rating_table.dart (2 個)
11 - Layer 4: i_rating_repository.dart (1 個)
12 - Layer 3: i_rate_book_use_case.dart, rate_book_use_case.dart (2 個)
13 - Layer 3: i_get_book_rating_use_case.dart, get_book_rating_use_case.dart (2 個)
14 - Layer 2: book_detail_controller.dart, rating_controller.dart (2 個)
15 - Layer 1: rating_widget.dart, book_detail_widget.dart (2 個)
16
17 層級跨度 = 5 - 1 = 4 層(超標)→ God Ticket
18
19步驟 4: 評估預估工時
20 步驟數量 = 15 項
21 複雜度 = 包含多層整合(x2.0 係數)
22 預估工時 = 15 × 30 分鐘 × 2.0 = 15 小時(需檢查)
23
24結論: 檔案數量和層級跨度都超標 → God Ticket(必須拆分)拆分策略執行:
1選擇策略: 按層級拆分(優先策略)
2
3拆分結果(5 個 Ticket):
4
5Ticket 1 [Layer 5]: Rating Domain 模型
6 - rating_value.dart
7 - rating.dart
8 - book.dart(新增 rating 欄位)
9
10Ticket 2 [Layer 5 + 4]: Rating Repository
11 - i_rating_repository.dart(介面)
12 - rating_repository_impl.dart(實作)
13 - rating_table.dart(資料表)
14
15Ticket 3 [Layer 3]: RateBook UseCase
16 - i_rate_book_use_case.dart(介面)
17 - rate_book_use_case.dart(實作)
18
19Ticket 4 [Layer 3]: GetBookRating UseCase
20 - i_get_book_rating_use_case.dart(介面)
21 - get_book_rating_use_case.dart(實作)
22
23Ticket 5 [Layer 2]: Rating Controller 整合
24 - book_detail_controller.dart(更新)
25 - rating_controller.dart(新建)
26
27Ticket 6 [Layer 1]: Rating UI 元件
28 - rating_widget.dart(新建)
29 - book_detail_widget.dart(更新)拆分後重新檢測:
1Ticket 1 [Layer 5]: Rating Domain 模型
2 檔案數量: 3 個(符合)
3 層級跨度: 1 層(符合)
4 預估工時: 3 小時(符合)
5 結論: 通過
6
7Ticket 2 [Layer 5 + 4]: Rating Repository
8 檔案數量: 3 個(符合)
9 層級跨度: 2 層(需檢查)(Repository 介面和實作可接受)
10 預估工時: 4 小時(符合)
11 結論: 通過
12
13Ticket 3 [Layer 3]: RateBook UseCase
14 檔案數量: 2 個(符合)
15 層級跨度: 1 層(符合)
16 預估工時: 3 小時(符合)
17 結論: 通過
18
19Ticket 4 [Layer 3]: GetBookRating UseCase
20 檔案數量: 2 個(符合)
21 層級跨度: 1 層(符合)
22 預估工時: 2.5 小時(符合)
23 結論: 通過
24
25Ticket 5 [Layer 2]: Rating Controller 整合
26 檔案數量: 2 個(符合)
27 層級跨度: 1 層(符合)
28 預估工時: 3 小時(符合)
29 結論: 通過
30
31Ticket 6 [Layer 1]: Rating UI 元件
32 檔案數量: 2 個(符合)
33 層級跨度: 1 層(符合)
34 預估工時: 4 小時(符合)
35 結論: 通過
36
37最終結論: 所有 Ticket 都通過 C1 檢測改善效果:
| 維度 | 原始 Ticket | 拆分後(6 個 Ticket) | 改善 |
|---|---|---|---|
| 檔案數量 | 14 個(超標) | 2-3 個/Ticket(合格) | 符合標準 |
| 層級跨度 | 4 層(超標) | 1-2 層/Ticket(合格) | 符合單層修改原則 |
| 預估工時 | 15 小時(需檢查) | 2.5-4 小時/Ticket(合格) | 可在半天內完成 |
| 可並行執行 | 否 | 是(Ticket 1-4 可並行)(合格) | 加速開發 |
| 風險控制 | 高風險 | 低風險(合格) | 降低失敗影響 |
2.4.3 C3. Ambiguous Responsibility 檢測
定義(引用 v0.12.G.2 第 2.3.3 節 Ambiguous Responsibility 定義):
Ambiguous Responsibility 是指 Ticket 的職責定義不明確,無法判斷屬於哪一層級,違反「層級明確原則」。
職責明確 Ticket 必要元素:
| 必要元素 | 檢查項目 | 範例 | 缺失後果 |
|---|---|---|---|
| 層級標示 | 標題包含 [Layer X] 標籤 | [Layer 2] 實作書籍詳情事件處理 | 無法判斷責任範圍 |
| 職責描述 | 目標章節明確定義單一職責 | 實作 BookDetailController 的 loadBookDetail 方法 | 職責模糊 |
| 檔案範圍 | 步驟章節明確列出檔案路徑 | 修改 lib/presentation/controllers/book_detail_controller.dart | 影響範圍不明 |
| 驗收限定 | 驗收條件限定在該層級 | BookDetailController.loadBookDetail() 正確呼叫 UseCase | 驗收標準模糊 |
檢測方法(Ticket 設計階段):
步驟 1: 檢查層級標示
1標題格式檢查:
2 合格範例:
3 - [Layer 1] 建立書籍評分 UI 元件
4 - [Layer 2] 實作書籍詳情 Controller 事件處理
5 - [Layer 3] 實作 GetBookDetail UseCase
6 - [Layer 5] 定義 Book Entity 和 Value Objects
7
8 不合格範例:
9 - 建立書籍評分功能(沒有層級標示)
10 - 實作書籍詳情(層級不明確)
11 - 整合評分功能(跨多層,職責模糊)步驟 2: 檢查職責描述
1目標章節檢查:
2 合格範例:
3 ### 目標
4 實作 BookDetailController 的 loadBookDetail 方法,
5 負責接收使用者事件並呼叫 GetBookDetailUseCase。
6
7 職責定義明確:
8 - 明確說明「做什麼」:實作 loadBookDetail 方法
9 - 明確說明「責任範圍」:接收事件 + 呼叫 UseCase
10 - 明確說明「不做什麼」:不包含業務邏輯實作
11
12 不合格範例:
13 ### 目標
14 實作書籍詳情功能
15
16 職責定義模糊:
17 - 「書籍詳情功能」範圍太廣(UI? 邏輯? 資料?)
18 - 沒有說明具體職責
19 - 沒有說明責任邊界步驟 3: 檢查檔案範圍
1步驟章節檢查:
2 合格範例:
3 ### 步驟
4 1. 修改 `lib/presentation/controllers/book_detail_controller.dart`
5 2. 新增 `loadBookDetail` 方法
6 3. 注入 `IGetBookDetailUseCase` 依賴
7 4. 實作事件處理邏輯
8
9 檔案範圍明確:
10 - 明確列出檔案路徑
11 - 避免籠統描述(如「修改相關檔案」)
12 - 檔案數量合理(1-3 個)
13
14 不合格範例:
15 ### 步驟
16 1. 修改書籍詳情相關檔案
17 2. 實作相關邏輯
18 3. 更新 UI
19
20 檔案範圍模糊:
21 - 「相關檔案」沒有具體說明是哪些檔案
22 - 「相關邏輯」沒有說明在哪裡實作
23 - 「更新 UI」沒有說明哪個 UI 檔案步驟 4: 檢查驗收限定
1驗收條件章節檢查:
2 合格範例:
3 ### 驗收條件
4 - [ ] BookDetailController.loadBookDetail() 方法建立
5 - [ ] 正確注入 IGetBookDetailUseCase 依賴
6 - [ ] loadBookDetail() 正確呼叫 UseCase.execute()
7 - [ ] 事件處理邏輯正確(不包含業務邏輯)
8 - [ ] dart analyze 0 錯誤
9
10 驗收限定在 Layer 2(Behavior):
11 - 只驗證 Controller 層的職責
12 - 不驗證 UI 呈現(Layer 1)
13 - 不驗證業務邏輯(Layer 3)
14
15 不合格範例:
16 ### 驗收條件
17 - [ ] 書籍詳情功能正常運作
18 - [ ] 使用者可以看到書籍資訊
19 - [ ] 資料正確儲存
20
21 驗收未限定在單一層級:
22 - 「功能正常運作」涵蓋所有層級
23 - 「使用者可以看到」是 UI 層(Layer 1)驗收
24 - 「資料正確儲存」是 Repository 層(Layer 5)驗收檢測失敗處理:
1C3 檢測失敗 → 執行重新定義步驟
2
3步驟 1: 明確層級定位
4 使用 v0.12.G.1 第 6.2 節檔案路徑分析法判斷層級
5 在標題加上 [Layer X] 標籤
6
7步驟 2: 重新定義職責
8 基於該層級的職責範圍重寫目標章節
9 明確說明「做什麼」「責任範圍」「不做什麼」
10
11步驟 3: 明確檔案範圍
12 列出具體的檔案路徑(避免籠統描述)
13 確保檔案都屬於同一層級
14
15步驟 4: 限定驗收條件
16 驗收條件只驗證該層級的職責
17 移除跨層級的驗收項目
18
19步驟 5: 重新檢測
20 確認所有 4 個必要元素都已補充檢測範例(完整流程):
原始 Ticket(違反 C3 標準):
1## Ticket: 實作書籍詳情功能
2
3### 背景
4根據 UC-02 需求,需要實作書籍詳情功能。
5
6### 目標
7實作書籍詳情功能,讓使用者可以查看書籍的完整資訊。
8
9### 步驟
101. 修改相關檔案
112. 實作查詢邏輯
123. 更新 UI 顯示
13
14### 驗收條件
15- [ ] 使用者可以看到書籍詳情
16- [ ] 資料正確顯示
17- [ ] 功能正常運作C3 檢測執行:
1步驟 1: 檢查層級標示
2 標題: "實作書籍詳情功能"
3 結果: 沒有 [Layer X] 標籤(不符合)
4 問題: 無法判斷屬於哪一層級
5
6步驟 2: 檢查職責描述
7 目標: "實作書籍詳情功能,讓使用者可以查看書籍的完整資訊"
8 結果: 職責定義模糊(不符合)
9 問題:
10 - "書籍詳情功能"範圍太廣(UI? 邏輯? 資料?)
11 - 沒有明確說明職責範圍
12
13步驟 3: 檢查檔案範圍
14 步驟: "修改相關檔案"
15 結果: 檔案範圍模糊(不符合)
16 問題:
17 - "相關檔案"沒有具體說明
18 - 沒有明確的檔案路徑
19
20步驟 4: 檢查驗收限定
21 驗收條件: "使用者可以看到書籍詳情"、"功能正常運作"
22 結果: 驗收未限定在單一層級(不符合)
23 問題:
24 - "使用者可以看到"是 UI 層驗收
25 - "功能正常運作"涵蓋所有層級
26
27結論: Ambiguous Responsibility(必須重新定義)重新定義執行:
1步驟 1: 明確層級定位
2 分析 Ticket 內容 → 主要涉及 Controller 事件處理
3 判斷層級 → Layer 2(Behavior)
4 更新標題 → 加上 [Layer 2] 標籤
5
6步驟 2: 重新定義職責
7 重寫目標章節:
8 - 明確說明「做什麼」
9 - 明確說明「責任範圍」
10 - 明確說明「不做什麼」
11
12步驟 3: 明確檔案範圍
13 列出具體檔案路徑
14 確認都屬於 Layer 2
15
16步驟 4: 限定驗收條件
17 只驗證 Layer 2 的職責
18 移除 UI 和業務邏輯驗收修正後 Ticket(符合 C3 標準):
1## Ticket: [Layer 2] 實作書籍詳情 Controller 事件處理
2
3### 背景
4根據 UC-02 需求,需要實作 BookDetailController 的事件處理邏輯。
5
6### 目標
7實作 BookDetailController 的 loadBookDetail 方法,
8負責接收使用者的「查看書籍詳情」事件並呼叫 GetBookDetailUseCase。
9
10職責範圍:
11
12- 接收使用者事件(如按鈕點擊)
13- 呼叫 GetBookDetailUseCase 獲取書籍資料
14- 將 UseCase 回傳的資料傳遞給 UI
15- 不包含業務邏輯實作(業務邏輯在 UseCase 層)
16
17### 步驟
181. 修改 `lib/presentation/controllers/book_detail_controller.dart`
192. 新增 `loadBookDetail(String isbn)` 方法
203. 注入 `IGetBookDetailUseCase` 依賴
214. 實作事件處理邏輯:
22 - 呼叫 `useCase.execute(isbn)`
23 - 處理回傳的 `OperationResult<Book>`
24 - 更新 Controller 狀態(loading/success/error)
255. 撰寫單元測試
26
27### 驗收條件
28- [ ] BookDetailController.loadBookDetail() 方法建立在正確位置
29- [ ] 正確注入 IGetBookDetailUseCase 依賴
30- [ ] loadBookDetail() 正確呼叫 useCase.execute()
31- [ ] 正確處理 OperationResult(success/failure)
32- [ ] 事件處理邏輯正確(不包含業務邏輯)
33- [ ] 單元測試覆蓋率 > 80%
34- [ ] dart analyze 0 錯誤
35
36### 依賴 Ticket
37- Ticket #3: 定義 IGetBookDetailUseCase 介面(必須先完成)
38
39### 參考文件
40- docs/app-requirements-spec.md #UC-02
41- docs/work-logs/v0.12.8-design-decisions.md #決策2修正後重新檢測:
1步驟 1: 檢查層級標示
2 標題: "[Layer 2] 實作書籍詳情 Controller 事件處理"
3 結果: 有 [Layer 2] 標籤(符合)
4
5步驟 2: 檢查職責描述
6 目標: 明確定義職責範圍和邊界
7 結果: 職責定義明確(符合)
8 - 明確說明「接收事件」「呼叫 UseCase」
9 - 明確說明「不包含業務邏輯」
10
11步驟 3: 檢查檔案範圍
12 步驟: 明確列出檔案路徑
13 結果: 檔案範圍明確(符合)
14 - `lib/presentation/controllers/book_detail_controller.dart`
15
16步驟 4: 檢查驗收限定
17 驗收條件: 限定在 Layer 2 職責
18 結果: 驗收限定正確(符合)
19 - 只驗證 Controller 層的職責
20 - 不包含 UI 或業務邏輯驗收
21
22結論: 通過 C3 檢測改善效果:
| 維度 | 原始 Ticket | 修正後 Ticket | 改善 |
|---|---|---|---|
| 層級標示 | 無(不合格) | [Layer 2](合格) | 明確定位 |
| 職責描述 | 模糊(不合格) | 明確定義範圍和邊界(合格) | 職責清晰 |
| 檔案範圍 | “相關檔案”(不合格) | 具體檔案路徑(合格) | 影響範圍明確 |
| 驗收限定 | 跨層級(不合格) | 限定在 Layer 2(合格) | 驗收標準清晰 |
| 可執行性 | 低(不合格) | 高(合格) | 開發者可直接執行 |
2.4.4 C2. Incomplete Ticket 檢測
定義(引用 v0.12.G.2 第 2.3.3 節 Incomplete Ticket 定義):
Incomplete Ticket 是指 Ticket 內容缺失關鍵元素,導致開發者無法明確理解需求、驗收標準或測試方法。
必要元素檢測清單:
| 元素 | 檢查內容 | 通過標準 | 重要性 |
|---|---|---|---|
| 驗收條件 | 是否有「### 驗收條件」章節 | 至少 3 個可驗證的驗收項目 | 必要 |
| 測試規劃 | 步驟中是否包含測試 | 明確列出測試檔案和測試項目 | 必要 |
| 工作日誌規劃 | 是否規劃工作日誌檔案 | 明確工作日誌檔案名稱和記錄內容 | 必要 |
| 參考文件 | 是否連結需求規格或設計文件 | 至少 1 個有效的文件連結 | 必要 |
檢測方法:
步驟 1: 檢查驗收條件完整性
1掃描 Ticket 內容
2 ↓
3檢查是否包含「### 驗收條件」章節?
4 ├─ Yes → 檢查驗收項目數量
5 │ ├─ ≥ 3 個 → 通過
6 │ └─ < 3 個 → 失敗(驗收條件不足)
7 │
8 └─ No → 失敗(缺少驗收條件章節)
9
10驗收條件品質檢查:
11 ├─ 是否可量化驗證?(避免模糊描述)
12 ├─ 是否限定在該層級?(不跨層級驗收)
13 └─ 是否涵蓋功能性、品質性、整合性?範例:
合格驗收條件:
1### 驗收條件
2- [ ] `IBookRepository` 介面檔案建立在 `lib/domains/library/repositories/`
3- [ ] `getBookByIsbn(String isbn)` 方法簽名完整且明確
4- [ ] 方法包含完整的文檔註解(參數、回傳值、異常)
5- [ ] dart analyze 0 錯誤
6- [ ] 測試覆蓋率 > 80%
7- [ ] 不破壞既有功能(回歸測試通過)不合格驗收條件:
1### 驗收條件
2- [ ] 功能可以正常運作
3- [ ] 程式碼品質良好問題:驗收條件過於模糊,無法量化驗證
步驟 2: 檢查測試規劃完整性
1掃描「步驟」章節
2 ↓
3檢查是否包含測試相關步驟?
4 ├─ Yes → 檢查測試內容
5 │ ├─ 有測試檔案路徑(符合)
6 │ ├─ 有測試項目清單(符合)
7 │ ├─ 有測試覆蓋率要求(符合)
8 │ └─ 通過
9 │
10 └─ No → 失敗(缺少測試規劃)
11
12測試規劃品質檢查:
13 ├─ 是否包含單元測試?
14 ├─ 是否包含整合測試?(如需要)
15 └─ 是否定義測試覆蓋率標準?範例:
合格測試規劃:
1### 步驟
24. 撰寫 `test/domain/repositories/book_repository_test.dart` 單元測試
3 - 測試 `getBookByIsbn` 正常流程(書籍存在)
4 - 測試書籍不存在異常處理
5 - 測試 ISBN 格式錯誤異常處理
6 - 測試網路錯誤異常處理
75. 確保測試覆蓋率 > 80%不合格測試規劃:
1### 步驟
24. 撰寫測試問題:沒有明確測試檔案路徑和測試項目
步驟 3: 檢查工作日誌規劃
1掃描 Ticket 內容
2 ↓
3檢查是否包含「### 工作日誌」章節?
4 ├─ Yes → 檢查檔案名稱
5 │ ├─ 符合命名規範(符合)
6 │ │ 格式: docs/work-logs/vX.Y.Z-feature-name.md
7 │ └─ 通過
8 │
9 └─ No → 失敗(缺少工作日誌規劃)
10
11命名規範檢查:
12 ├─ 是否包含版本號?
13 ├─ 是否描述性命名?
14 └─ 是否在 docs/work-logs/ 目錄下?範例:
合格工作日誌規劃:
1### 工作日誌
2檔案名稱: `docs/work-logs/v0.12.8-book-repository-interface.md`
3
4記錄內容:
5- Ticket 執行過程
6- 設計決策和理由
7- 遇到的問題和解決方法
8- 測試結果和覆蓋率報告不合格工作日誌規劃:
1(沒有工作日誌規劃)步驟 4: 檢查參考文件連結
1掃描 Ticket 內容
2 ↓
3檢查是否包含「### 參考文件」章節?
4 ├─ Yes → 檢查連結有效性
5 │ ├─ 至少 1 個連結(符合)
6 │ ├─ 連結格式正確(符合)
7 │ └─ 連結內容相關(符合)
8 │
9 └─ No → 失敗(缺少參考文件)
10
11連結品質檢查:
12 ├─ 是否連結需求規格?(建議)
13 ├─ 是否連結設計文件?(建議)
14 └─ 是否連結相關 Ticket?(如有依賴)範例:
合格參考文件:
1### 參考文件
2- `docs/app-requirements-spec.md` #UC-01 書籍查詢功能
3- `docs/work-logs/v0.12.7-design-decisions.md` #決策1 Repository 設計模式
4- `.claude/methodologies/layered-ticket-methodology.md` 層級隔離原則不合格參考文件:
1(沒有參考文件章節)檢測流程完整範例:
1Ticket #1: [Layer 5] 定義 IBookRepository 介面
2 ↓
3執行 C2. Incomplete Ticket 檢測
4 ↓
5【步驟 1】檢查驗收條件
6 ├─ 有「### 驗收條件」章節(符合)
7 ├─ 驗收項目數量: 6 個(符合)
8 ├─ 驗收條件可量化(符合)
9 └─ 通過
10 ↓
11【步驟 2】檢查測試規劃
12 ├─ 步驟 4 包含測試(符合)
13 ├─ 測試檔案路徑明確(符合)
14 ├─ 測試項目完整(符合)
15 └─ 通過
16 ↓
17【步驟 3】檢查工作日誌規劃
18 ├─ 有「### 工作日誌」章節(符合)
19 ├─ 檔案名稱符合規範(符合)
20 └─ 通過
21 ↓
22【步驟 4】檢查參考文件
23 ├─ 有「### 參考文件」章節(符合)
24 ├─ 連結數量: 3 個(符合)
25 ├─ 連結格式正確(符合)
26 └─ 通過
27 ↓
28C2 檢測結論: 通過修正方法:
缺失項目 1: 沒有驗收條件
修正步驟:
11. 新增「### 驗收條件」章節
22. 撰寫 3-6 個可量化驗收項目
33. 涵蓋三個維度:
4 - 功能性驗收(檔案位置、方法簽名、程式邏輯)
5 - 品質性驗收(dart analyze、測試覆蓋率、文檔)
6 - 整合性驗收(整合測試、不破壞既有功能)缺失項目 2: 沒有測試規劃
修正步驟:
11. 在「### 步驟」章節新增測試步驟
22. 明確列出測試檔案路徑
33. 列出測試項目清單(正常流程 + 異常處理)
44. 定義測試覆蓋率要求(建議 > 80%)缺失項目 3: 沒有工作日誌規劃
修正步驟:
11. 新增「### 工作日誌」章節
22. 定義工作日誌檔案名稱
3 格式: docs/work-logs/vX.Y.Z-feature-name.md
43. 說明記錄內容範圍缺失項目 4: 沒有參考文件
修正步驟:
11. 新增「### 參考文件」章節
22. 連結需求規格(必要)
33. 連結設計文件(建議)
44. 連結相關 Ticket(如有依賴)完整修正範例:
修正前(Incomplete Ticket):
1## Ticket: 定義 IBookRepository 介面
2
3### 目標
4定義書籍 Repository 的介面契約
5
6### 步驟
71. 建立介面檔案
82. 定義方法簽名
93. 撰寫文檔註解修正後(Complete Ticket):
1## Ticket: [Layer 5] 定義 IBookRepository 介面
2
3### 目標
4定義書籍 Repository 的介面契約,規範 Domain 層與 Infrastructure 層的互動方式
5
6### 步驟
71. 建立 `lib/domains/library/repositories/i_book_repository.dart`
82. 定義 `getBookByIsbn(String isbn)` 方法簽名
93. 定義 `getAllBooks()` 方法簽名
104. 撰寫完整的文檔註解(參數、回傳值、異常)
115. 撰寫 `test/domain/repositories/book_repository_test.dart` 單元測試
12 - 測試 getBookByIsbn 正常流程
13 - 測試書籍不存在異常處理
14 - 測試 ISBN 格式錯誤異常處理
156. 確保測試覆蓋率 > 80%
16
17### 驗收條件
18- [ ] `IBookRepository` 介面檔案建立在 `lib/domains/library/repositories/`
19- [ ] `getBookByIsbn(String isbn)` 方法簽名完整且明確
20- [ ] 方法包含完整的文檔註解
21- [ ] dart analyze 0 錯誤
22- [ ] 測試覆蓋率 > 80%
23- [ ] 不破壞既有功能
24
25### 工作日誌
26檔案名稱: `docs/work-logs/v0.12.8-book-repository-interface.md`
27
28### 參考文件
29- `docs/app-requirements-spec.md` #UC-01 書籍查詢功能
30- `.claude/methodologies/layered-ticket-methodology.md` 層級隔離原則2.4.5 品質閘門執行流程
完整執行流程:
1Phase 1: 功能設計(lavender-interface-designer)
2 ↓
3Ticket 清單撰寫完成
4 ↓
5┌─────────────────────────────────────┐
6│ 品質閘門檢測開始 │
7│ (lavender-interface-designer) │
8└─────────────────────────────────────┘
9 ↓
10對每個 Ticket 執行檢測(按順序)
11 ↓
12┌─────────────────────────────────────┐
13│ 【檢測 1】C1. God Ticket 檢測 │
14│ │
15│ 檢查指標: │
16│ - 檔案數量 ≤ 10? │
17│ - 層級跨度 ≤ 2? │
18│ - 預估工時 ≤ 16h? │
19│ │
20│ 組合邏輯: 任一項目超標 = God Ticket │
21└─────────────────────────────────────┘
22 ↓
23 ├─ 通過 → 繼續檢測 C3
24 └─ 失敗 → 執行拆分 → 重新檢測 C1
25 ↓
26┌─────────────────────────────────────┐
27│ 【檢測 2】C3. Ambiguous │
28│ Responsibility 檢測 │
29│ │
30│ 檢查要素: │
31│ - 有層級標示 [Layer X]? │
32│ - 職責描述明確? │
33│ - 檔案範圍明確? │
34│ - 驗收條件限定在該層? │
35└─────────────────────────────────────┘
36 ↓
37 ├─ 通過 → 繼續檢測 C2
38 └─ 失敗 → 重新定義職責 → 重新檢測 C3
39 ↓
40┌─────────────────────────────────────┐
41│ 【檢測 3】C2. Incomplete Ticket 檢測 │
42│ │
43│ 檢查要素: │
44│ - 有驗收條件章節? │
45│ - 有測試規劃? │
46│ - 有工作日誌規劃? │
47│ - 有參考文件連結? │
48└─────────────────────────────────────┘
49 ↓
50 ├─ 通過 → Ticket 通過品質閘門
51 └─ 失敗 → 補充遺漏項目 → 重新檢測 C2
52 ↓
53所有 Ticket 都通過 C1/C2/C3?
54 ↓
55 ├─ Yes → 提交品質閘門報告給 PM
56 │ ↓
57 │ PM 審查
58 │ ↓
59 │ PM 批准 → 進入 Phase 2: 測試驗證
60 │
61 └─ No → 繼續修正未通過的 Ticket檢測順序說明:
| 順序 | 檢測項目 | 檢測原因 | 失敗影響 |
|---|---|---|---|
| 1 C1 | God Ticket | 檔案數和層級是最基礎的結構問題 | 必須拆分,否則後續檢測無意義 |
| 2 C3 | Ambiguous Responsibility | 職責定義是 Ticket 品質的核心 | 必須重新定義,避免跨層級實作 |
| 3 C2 | Incomplete Ticket | 完整性是 Ticket 可執行性的保證 | 補充遺漏項目,確保開發者理解需求 |
檢測順序設計理由:
- C1 優先: 檔案數和層級問題會影響職責定義,必須先解決結構問題
- C3 次之: 職責明確後才能評估驗收條件和測試規劃是否完整
- C2 最後: 完整性檢測依賴明確的職責定義
檢測失敗處理流程:
1檢測失敗
2 ↓
3記錄失敗原因到工作日誌
4 ↓
5根據失敗類型選擇修正方法
6 ├─ C1 失敗 → 執行 Ticket 拆分
7 │ ├─ 按層級拆分(優先)
8 │ ├─ 按職責拆分(次要)
9 │ └─ 按 TDD 階段拆分(特殊)
10 │
11 ├─ C3 失敗 → 重新定義職責
12 │ ├─ 確認主要職責層級
13 │ ├─ 加入層級標示 [Layer X]
14 │ ├─ 限定職責範圍
15 │ └─ 明確列出檔案
16 │
17 └─ C2 失敗 → 補充遺漏項目
18 ├─ 補充驗收條件
19 ├─ 補充測試規劃
20 ├─ 補充工作日誌規劃
21 └─ 補充參考文件連結
22 ↓
23修正完成
24 ↓
25重新執行失敗的檢測項目
26 ↓
27 ├─ 通過 → 繼續下一個檢測
28 └─ 失敗 → 再次修正(直到通過)PM 審查標準:
審查清單:
| 審查項目 | 檢查內容 | 通過標準 |
|---|---|---|
| 品質閘門報告 | 每個 Ticket 是否都執行了 C1/C2/C3 檢測 | 所有 Ticket 都有檢測記錄(合格) |
| 檢測結果 | 所有 Ticket 是否都通過檢測 | 所有 Ticket 標記為「通過」 |
| 修正記錄 | 檢測失敗的 Ticket 是否記錄修正過程 | 修正過程完整記錄(問題 + 修正方法 + 結果) |
| Ticket 數量 | 拆分後的 Ticket 數量是否合理 | 不過度拆分(< 10 個)、不過度合併(> 1 個) |
| 依賴關係 | Ticket 間的依賴關係是否明確 | 依賴順序符合架構層級(L5→L3→L2→L1) |
PM 審查決策流程:
1PM 收到品質閘門報告
2 ↓
3【檢查 1】品質閘門報告完整性
4 ├─ 所有 Ticket 都有 C1/C2/C3 檢測記錄?
5 │ ├─ Yes → 繼續檢查 2
6 │ └─ No → 要求 lavender 補充檢測
7 ↓
8【檢查 2】檢測結果正確性
9 ├─ 所有 Ticket 都標記為「通過」?
10 │ ├─ Yes → 繼續檢查 3
11 │ └─ No → 檢查未通過原因
12 │ ├─ 未修正 → 要求 lavender 修正
13 │ └─ 修正後仍不符合 → 要求重新設計
14 ↓
15【檢查 3】修正記錄完整性
16 ├─ 檢測失敗的 Ticket 是否記錄修正過程?
17 │ ├─ Yes → 繼續檢查 4
18 │ └─ No → 要求補充修正記錄
19 ↓
20【檢查 4】Ticket 數量合理性
21 ├─ 拆分後數量是否合理(1-10 個)?
22 │ ├─ Yes → 繼續檢查 5
23 │ └─ No → 要求調整拆分策略
24 ↓
25【檢查 5】依賴關係正確性
26 ├─ Ticket 依賴順序是否符合架構層級?
27 │ ├─ Yes → PM 批准 Ticket 清單
28 │ └─ No → 要求調整依賴順序
29 ↓
30PM 批准
31 ↓
32分派給開發者執行(進入 Phase 2)工作日誌記錄範例:
1## Code Smell 品質閘門檢測
2
3### Ticket #1: [Layer 5] 定義 Book Entity
4
5#### 檢測記錄(2025-10-11)
6
7**C1. God Ticket 檢測**:
8- 檔案數量: 2 個(符合)(book.dart + isbn.dart)
9- 層級跨度: 1 層(Layer 5)(符合)
10- 預估工時: 4 小時(符合)
11- 結論: 通過
12
13**C3. Ambiguous Responsibility 檢測**:
14- 層級標示: [Layer 5](符合)
15- 職責描述: 明確(定義 Book Entity 和 ISBN Value Object)(符合)
16- 檔案範圍: 明確列出 2 個檔案路徑(符合)
17- 驗收限定: 限定在 Domain 層(符合)
18- 結論: 通過
19
20**C2. Incomplete Ticket 檢測**:
21- 驗收條件: 6 個驗收項目(符合)
22- 測試規劃: 包含測試步驟和覆蓋率要求(符合)
23- 工作日誌: 規劃檔案名稱(符合)
24- 參考文件: 連結需求規格和設計文件(符合)
25- 結論: 通過
26
27**最終結論**: Ticket #1 通過品質閘門
28
29---
30
31### Ticket #2: [Layer 3/5] 實作書籍查詢功能(原始設計)
32
33#### 檢測記錄(2025-10-11)
34
35**C1. God Ticket 檢測**:
36- 檔案數量: 15 個(不符合)(超標,標準 ≤ 10)
37- 層級跨度: 3 層(Layer 1/2/3/5)(不符合)(超標,標準 ≤ 2)
38- 預估工時: 24 小時(不符合)(超標,標準 ≤ 16h)
39- 結論: 失敗(3 個指標都超標)
40
41**修正方法**: 按層級拆分為 4 個 Ticket
42- Ticket #2a: [Layer 5] 定義 Book Entity
43- Ticket #2b: [Layer 3] 實作 GetBookUseCase
44- Ticket #2c: [Layer 2] 實作 BookController
45- Ticket #2d: [Layer 1] 實作 BookListWidget
46
47**拆分後重新檢測**:
48
49**Ticket #2a 檢測**:
50- C1: 通過(2 個檔案、1 層、4h)
51- C3: 通過(職責明確)
52- C2: 通過(4 項必要元素齊全)
53
54**Ticket #2b 檢測**:
55- C1: 通過(3 個檔案、1 層、6h)
56- C3: 通過(職責明確)
57- C2: 通過(4 項必要元素齊全)
58
59**Ticket #2c 檢測**:
60- C1: 通過(2 個檔案、1 層、4h)
61- C3: 通過(職責明確)
62- C2: 通過(4 項必要元素齊全)
63
64**Ticket #2d 檢測**:
65- C1: 通過(3 個檔案、1 層、5h)
66- C3: 通過(職責明確)
67- C2: 通過(4 項必要元素齊全)
68
69**最終結論**: 原 Ticket #2 拆分為 4 個 Ticket,全部通過品質閘門
70
71---
72
73### PM 審查報告
74
75**審查日期**: 2025-10-11
76**審查 Ticket 清單**: v0.12.8 書籍查詢功能(5 個 Ticket)
77
78**品質閘門檢測確認**:
79- Ticket #1: 通過 C1/C2/C3 檢測- Ticket #2a: 通過 C1/C2/C3 檢測(拆分後)- Ticket #2b: 通過 C1/C2/C3 檢測(拆分後)- Ticket #2c: 通過 C1/C2/C3 檢測(拆分後)- Ticket #2d: 通過 C1/C2/C3 檢測(拆分後)
80**拆分合理性**:
81- 原 Ticket 數量: 2 個(1 個正常 + 1 個 God Ticket)
82- 拆分後數量: 5 個
83- 評估: 合理(符合)
84- 理由: God Ticket 按層級拆分為 4 個,符合單層修改原則
85
86**依賴關係檢查**:
87- 依賴順序: Ticket #1 → #2a → #2b → #2c → #2d
88- 評估: 正確(符合)
89- 理由: 遵循架構層級順序(Layer 5 → Layer 3 → Layer 2 → Layer 1)
90
91**審查結論**:
92- 批准 Ticket 清單- 可分派給開發者執行(進入 Phase 2)```
93
94---
95
96#### 2.4.6 自動化檢測準備(v0.12.G.4)
97
98本節為 v0.12.G.4「代理人和 Hook 機制調整」準備自動化檢測規則設計。
99
100**自動化檢測目標**:
101
102- 減少人工檢測工作量
103- 提升檢測一致性
104- 即時反饋 Ticket 品質問題
105- 支援 lavender-interface-designer 執行檢測
106
107**可自動化項目**:
108
109**C1. God Ticket 自動化檢測(可自動化程度: 80%)**:
110
111| 檢測指標 | 自動化程度 | 自動化方法 | 需要人工判斷 |
112| ------------ | ---------- | -------------------------------------- | ---------------- |
113| **檔案數量** | 100%(合格) | 掃描步驟章節,提取檔案路徑,計算數量 | 無 |
114| **層級跨度** | 100%(合格) | 使用 v0.12.G.1 第 6.2 節決策樹判斷層級 | 無 |
115| **預估工時** | 60%(需檢查) | 根據步驟數量估算(< 10 步 = 2-4h) | 複雜度需人工確認 |
116
117**自動化規則設計**:
118
119```python
120def check_god_ticket_automated(ticket_content: str) -> dict:
121 """
122 自動化檢測 God Ticket
123
124 回傳格式:
125 {
126 "file_count": int,
127 "layer_span": int,
128 "estimated_hours": int,
129 "is_god_ticket": bool,
130 "confidence": float # 0.0-1.0
131 }
132 """
133 # 1. 提取檔案路徑
134 file_paths = extract_file_paths(ticket_content)
135 file_count = len(file_paths)
136
137 # 2. 判斷層級跨度
138 layers = [determine_layer(path) for path in file_paths]
139 layer_span = max(layers) - min(layers) + 1
140
141 # 3. 預估工時(簡化估算)
142 step_count = count_steps(ticket_content)
143 estimated_hours = estimate_hours_by_steps(step_count)
144
145 # 4. 判斷是否為 God Ticket(任一項目超標)
146 is_god_ticket = (
147 file_count > 10 or
148 layer_span > 2 or
149 estimated_hours > 16
150 )
151
152 # 5. 計算信心度
153 confidence = calculate_confidence(step_count, file_paths)
154
155 return {
156 "file_count": file_count,
157 "layer_span": layer_span,
158 "estimated_hours": estimated_hours,
159 "is_god_ticket": is_god_ticket,
160 "confidence": confidence
161 }C2. Incomplete Ticket 自動化檢測(可自動化程度: 90%):
| 檢測指標 | 自動化程度 | 自動化方法 | 需要人工判斷 |
|---|---|---|---|
| 驗收條件 | 100%(合格) | 檢查章節存在性、驗收項目數量 | 無 |
| 測試規劃 | 80%(需檢查) | 檢查測試檔案和關鍵字 | 測試完整性需人工確認 |
| 工作日誌 | 100%(合格) | 檢查章節存在性、檔案名稱格式 | 無 |
| 參考文件 | 100%(合格) | 檢查章節存在性、連結數量 | 無 |
自動化規則設計:
1def check_incomplete_ticket_automated(ticket_content: str) -> dict:
2 """
3 自動化檢測 Incomplete Ticket
4
5 回傳格式:
6 {
7 "has_acceptance_criteria": bool,
8 "acceptance_count": int,
9 "has_test_plan": bool,
10 "test_files": list,
11 "has_work_log": bool,
12 "work_log_file": str,
13 "has_references": bool,
14 "reference_count": int,
15 "is_incomplete": bool
16 }
17 """
18 # 1. 檢查驗收條件
19 has_acceptance = has_section(ticket_content, "### 驗收條件")
20 acceptance_count = count_acceptance_items(ticket_content)
21
22 # 2. 檢查測試規劃
23 has_test_plan = has_test_keywords(ticket_content)
24 test_files = extract_test_files(ticket_content)
25
26 # 3. 檢查工作日誌
27 has_work_log = has_section(ticket_content, "### 工作日誌")
28 work_log_file = extract_work_log_file(ticket_content)
29
30 # 4. 檢查參考文件
31 has_references = has_section(ticket_content, "### 參考文件")
32 reference_count = count_references(ticket_content)
33
34 # 5. 判斷是否為 Incomplete Ticket
35 is_incomplete = not (
36 has_acceptance and acceptance_count >= 3 and
37 has_test_plan and len(test_files) > 0 and
38 has_work_log and work_log_file and
39 has_references and reference_count >= 1
40 )
41
42 return {
43 "has_acceptance_criteria": has_acceptance,
44 "acceptance_count": acceptance_count,
45 "has_test_plan": has_test_plan,
46 "test_files": test_files,
47 "has_work_log": has_work_log,
48 "work_log_file": work_log_file,
49 "has_references": has_references,
50 "reference_count": reference_count,
51 "is_incomplete": is_incomplete
52 }C3. Ambiguous Responsibility 自動化檢測(可自動化程度: 70%):
| 檢測指標 | 自動化程度 | 自動化方法 | 需要人工判斷 |
|---|---|---|---|
| 層級標示 | 100%(合格) | 正則匹配 \[Layer \d+\] | 無 |
| 職責描述 | 50%(需檢查) | 檢查字數、關鍵字 | 明確性需人工確認 |
| 檔案範圍 | 100%(合格) | 檢查具體檔案路徑 | 無 |
| 驗收限定 | 70%(需檢查) | 提取驗收條件的類別名稱 | 層級一致性需人工確認 |
自動化規則設計:
1def check_ambiguous_responsibility_automated(ticket_content: str) -> dict:
2 """
3 自動化檢測 Ambiguous Responsibility
4
5 回傳格式:
6 {
7 "has_layer_tag": bool,
8 "layer_number": int,
9 "has_clear_responsibility": bool,
10 "responsibility_length": int,
11 "has_file_paths": bool,
12 "file_count": int,
13 "acceptance_limited_to_layer": bool,
14 "is_ambiguous": bool,
15 "confidence": float
16 }
17 """
18 # 1. 檢查層級標示
19 has_layer_tag, layer_number = extract_layer_tag(ticket_content)
20
21 # 2. 檢查職責描述(簡化檢查)
22 responsibility = extract_responsibility(ticket_content)
23 has_clear_responsibility = len(responsibility) > 20
24
25 # 3. 檢查檔案範圍
26 file_paths = extract_file_paths(ticket_content)
27 has_file_paths = len(file_paths) > 0
28
29 # 4. 檢查驗收限定(需要層級判斷)
30 acceptance_items = extract_acceptance_items(ticket_content)
31 acceptance_layers = [
32 determine_layer_from_acceptance(item)
33 for item in acceptance_items
34 ]
35 acceptance_limited = all(
36 layer == layer_number for layer in acceptance_layers
37 )
38
39 # 5. 判斷是否為 Ambiguous Responsibility
40 is_ambiguous = not (
41 has_layer_tag and
42 has_clear_responsibility and
43 has_file_paths and
44 acceptance_limited
45 )
46
47 # 6. 計算信心度(職責描述需人工確認)
48 confidence = 0.7 if has_clear_responsibility else 0.5
49
50 return {
51 "has_layer_tag": has_layer_tag,
52 "layer_number": layer_number,
53 "has_clear_responsibility": has_clear_responsibility,
54 "responsibility_length": len(responsibility),
55 "has_file_paths": has_file_paths,
56 "file_count": len(file_paths),
57 "acceptance_limited_to_layer": acceptance_limited,
58 "is_ambiguous": is_ambiguous,
59 "confidence": confidence
60 }需要人工判斷的項目:
| 項目 | 原因 | 人工判斷者 | 自動化支援 |
|---|---|---|---|
| Ticket 拆分合理性 | 需要業務知識和架構經驗 | PM 或架構師 | 提供拆分建議 |
| 職責定義明確性 | 需要理解業務語意 | lavender-interface-designer | 檢測關鍵字 |
| 預估工時準確性 | 需要評估任務複雜度 | PM 或開發者 | 根據步驟數量估算 |
| 依賴關係正確性 | 需要理解架構層級關係 | lavender-interface-designer | 檢查依賴順序 |
Hook 系統檢測規則(v0.12.G.4 規劃):
1# Hook 觸發時機: Ticket 檔案修改時(PostEdit Hook)
2
3def ticket_quality_gate_hook(ticket_file_path: str) -> dict:
4 """
5 Ticket 品質閘門 Hook
6
7 執行時機:
8 - Ticket 檔案儲存時
9 - lavender-interface-designer 提交工作日誌時
10
11 回傳格式:
12 {
13 "passed": bool,
14 "c1_result": dict,
15 "c2_result": dict,
16 "c3_result": dict,
17 "suggestions": list,
18 "blocking_issues": list
19 }
20 """
21 # 讀取 Ticket 內容
22 ticket_content = read_ticket_file(ticket_file_path)
23
24 # 執行自動化檢測
25 c1_result = check_god_ticket_automated(ticket_content)
26 c2_result = check_incomplete_ticket_automated(ticket_content)
27 c3_result = check_ambiguous_responsibility_automated(ticket_content)
28
29 # 判斷是否通過
30 passed = not (
31 c1_result["is_god_ticket"] or
32 c2_result["is_incomplete"] or
33 c3_result["is_ambiguous"]
34 )
35
36 # 生成建議
37 suggestions = generate_suggestions(c1_result, c2_result, c3_result)
38
39 # 生成阻斷問題(需要立即修正)
40 blocking_issues = []
41 if c1_result["is_god_ticket"]:
42 blocking_issues.append(
43 f"God Ticket 檢測失敗: "
44 f"檔案數={c1_result['file_count']}, "
45 f"層級跨度={c1_result['layer_span']}, "
46 f"工時={c1_result['estimated_hours']}h"
47 )
48 if c2_result["is_incomplete"]:
49 blocking_issues.append(
50 f"Incomplete Ticket 檢測失敗: 缺少必要元素"
51 )
52 if c3_result["is_ambiguous"]:
53 blocking_issues.append(
54 f"Ambiguous Responsibility 檢測失敗: 職責不明確"
55 )
56
57 return {
58 "passed": passed,
59 "c1_result": c1_result,
60 "c2_result": c2_result,
61 "c3_result": c3_result,
62 "suggestions": suggestions,
63 "blocking_issues": blocking_issues
64 }
65
66# Hook 輸出範例:
67# - 品質閘門通過 → 記錄日誌,允許繼續
68# - 品質閘門失敗 → 阻止提交,提供修正建議v0.12.G.4 實作準備清單:
- 實作檔案路徑提取函式
- 實作層級判斷函式(基於 v0.12.G.1 第 6.2 節)
- 實作步驟數量計算和工時估算函式
- 實作章節檢測函式
- 實作驗收條件提取和驗證函式
- 實作測試檔案檢測函式
- 實作 Hook 整合(PostEdit Hook)
- 撰寫 Hook 測試(模擬 Ticket 檔案)
- 建立檢測結果日誌機制
- 提供修正建議生成器
2.5 Ticket 大小標準和範例
Ticket 大小標準總結:
| 類型 | 職責 | 檔案 | 測試 | 行數 | 適用場景 |
|---|---|---|---|---|---|
| Interface 定義 | 1 個 | 1 個 | 0 個 | < 30 行 | 定義契約 |
| Value Object 實作 | 1 個 | 1 個 | 2-3 個 | 30-40 行 | 簡單邏輯 |
| Repository 實作 | 2-3 個 | 1 個 | 4-6 個 | 50-80 行 | CRUD 操作 |
| Use Case 實作 | 2-3 個 | 2-3 個 | 5-8 個 | 40-70 行 | 業務邏輯 |
| 整合驗證 | 2-3 個 | 2-3 個 | 3-5 個 | 30-50 行 | 端到端測試 |
2.6 拆分決策樹
當面對一個大任務時,使用以下決策樹判斷如何拆分:
1任務評估
2│
3├─ 是否為單一職責且檔案數 ≤ 1?
4│ └─ Yes → 建立單一 Ticket(簡單)
5│ └─ No → 繼續評估
6│
7├─ 可按 Clean Architecture 分層拆分?
8│ └─ Yes → 拆分為 4 種 Ticket
9│ │ 1. Interface 定義 Ticket
10│ │ 2. 測試驗證 Ticket
11│ │ 3. 具體實作 Ticket
12│ │ 4. 整合連接 Ticket
13│ └─ No → 繼續評估
14│
15├─ 可按功能模組拆分?
16│ └─ Yes → 拆分為多個功能 Ticket
17│ │ 範例:User 模組、Book 模組、Order 模組
18│ └─ No → 繼續評估
19│
20├─ 可按步驟順序拆分?
21│ └─ Yes → 拆分為多個步驟 Ticket
22│ │ 範例:步驟1 資料準備、步驟2 邏輯處理、步驟3 結果輸出
23│ └─ No → 繼續評估
24│
25└─ 可按 CRUD 操作拆分?
26 └─ Yes → 拆分為 Create、Read、Update、Delete Ticket
27 └─ No → 重新分析任務結構或尋求 PM 協助2.7 Ticket 拆分檢查清單
拆分前檢查(5 項):
- 任務描述是否清晰明確?
- 是否有明確的需求來源?
- 是否理解任務的技術實作方式?
- 是否識別所有依賴關係?
- 是否評估職責數量、檔案數、測試數、程式碼行數?
拆分策略檢查(5 項):
- 是否嘗試按 Clean Architecture 分層拆分?
- 是否嘗試按功能模組拆分?
- 是否嘗試按步驟順序拆分?
- 拆分後的 Ticket 是否都可獨立驗收?
- 拆分後的 Ticket 是否符合複雜度標準(職責、檔案、測試、行數)?
拆分後檢查(4 項):
- 每個 Ticket 是否都有明確的驗收條件?
- Ticket 間的依賴關係是否明確標註?
- 是否有並行執行的機會?
- 所有 Ticket 加總是否完整覆蓋原任務?
第三章:Ticket 生命週期管理
3.1 Ticket 狀態定義
Ticket 從建立到關閉經歷 4 個狀態:
狀態 1:待執行(Pending)
定義:Ticket 已建立並通過準備度檢查,等待開發者執行。
進入條件:
- Ticket 建立完成
- 驗收條件明確
- 依賴 Ticket 已完成(如適用)
可執行動作:
- 指派開發者
- 調整優先級
- 開始執行(轉為「進行中」)
流程特性:快速流轉至 In Progress
狀態 2:進行中(In Progress)
定義:開發者正在執行 Ticket。
進入條件:
- 開發者開始執行
- 標記 Ticket 為「進行中」
可執行動作:
- 持續更新進度
- 遇到問題記錄到 Ticket 日誌
- 完成後提交 review(轉為「Review 中」)
- 發現問題暫停(轉回「待執行」)
流程特性:快速完成並進入 Review
狀態 3:Review 中(In Review)
定義:Ticket 已完成執行,等待 review 驗收。
進入條件:
- 開發者認為已完成
- 提交 review 請求
可執行動作:
- Review 檢查驗收條件
- 通過驗收(轉為「已完成」)
- 發現問題(轉回「進行中」,建立修正 Ticket)
流程特性:快速 Review 並決定結果
狀態 4:已完成(Completed)
定義:Ticket 通過 review 驗收,已關閉。
進入條件:
- 所有驗收條件滿足
- Review 通過
- 相關測試 100% 通過
可執行動作:
- 更新主版本日誌 Ticket 索引
- 更新 todolist 任務狀態
- 記錄完成時間和實際工時
停留時間:永久(已歸檔)
生命週期流程圖:
1建立 Ticket
2 ↓
3待執行(Pending)
4 ↓
5進行中(In Progress) ←─┐
6 ↓ │
7Review 中(In Review) │
8 ↓ │
9 通過? │
10 ├─ Yes → 已完成(Completed)
11 └─ No ──────────────┘
12 (建立修正 Ticket,重新執行)3.2 Ticket 建立標準
Ticket 標題格式
格式:Ticket #N: [動詞] [目標]
動詞選擇:
- 定義:定義 Interface、定義 Entity
- 撰寫:撰寫測試、撰寫文檔
- 實作:實作 Repository、實作 Use Case
- 整合:整合 Service、整合 Module
- 修復:修復 Bug、修復測試
- 重構:重構邏輯、重構架構
範例:
Ticket #1: 定義 IBookRepository 介面-Ticket #2: 撰寫 BookRepository 測試-Ticket #3: 實作 SQLiteBookRepository-Ticket #1: BookRepository(缺少動詞)- 反例:做一下 Repository(不明確)
Ticket 描述內容
完整的 Ticket 必須包含以下 5 個核心欄位:
Ticket 建立模板:
1## Ticket #N: [動詞] [目標]
2
3### 背景
4[為什麼需要這個 Ticket?來自哪個需求或問題?]
5
6### 目標
7[這個 Ticket 要達成什麼?明確且可驗證]
8
9### 步驟
101. [具體步驟 1]
112. [具體步驟 2]
123. [具體步驟 3]
13
14### 驗收條件
15- [ ] [可驗證的條件 1]
16- [ ] [可驗證的條件 2]
17- [ ] [可驗證的條件 3]
18
19### 參考文件
20- [設計文件連結]
21- [需求文件連結]
22
23### 依賴 Ticket
24- Ticket #X (必須先完成)
25- Ticket #Y (可並行)欄位說明:
1. 背景:
- 說明為什麼需要這個 Ticket
- 連結到需求或設計決策
- 提供上下文資訊
2. 目標:
- 一句話說明要達成什麼
- 必須明確且可驗證
- 避免模糊用語
3. 步驟:
- 列出具體執行步驟(3-5 步)
- 步驟必須可操作
- 幫助開發者快速理解如何執行
4. 驗收條件:
- 列出所有可驗證的條件(3-5 項)
- 條件必須客觀可檢查
- 使用 checkbox 格式
5. 參考文件:
- 連結到設計文件
- 連結到需求規格
- 連結到相關 Ticket
6. 依賴 Ticket:
- 列出必須先完成的 Ticket
- 列出可並行的 Ticket
- 明確依賴關係
3.3 Ticket 執行流程
步驟 1:領取 Ticket
- 開發者從「待執行」清單選擇 Ticket
- 確認依賴 Ticket 已完成
- 標記 Ticket 為「進行中」
步驟 2:閱讀 Ticket
- 閱讀背景和目標
- 檢查參考文件
- 理解驗收條件
步驟 3:執行步驟
- 按照步驟執行
- 遇到問題記錄到 Ticket 日誌
- 持續更新進度
步驟 4:自我檢查
- 逐項檢查驗收條件
- 確保所有條件滿足
- 執行相關測試
步驟 5:提交 Review
- 標記所有驗收條件為完成
- 標記 Ticket 為「Review 中」
- 通知 Reviewer
步驟 6:處理 Review 結果
- 如果通過:Ticket 標記為「已完成」
- 如果未通過:根據 Review 意見修正,重新執行
3.4 Ticket 驗收標準
驗收條件必須符合 SMART 原則:
S - Specific(具體):
- 反例:「功能運作正常」(太模糊)- 正例:「呼叫 getBookByIsbn(‘123’) 回傳正確的 Book 物件」
M - Measurable(可測量):
- 反例:「程式碼品質良好」(無法測量)- 正例:「dart analyze 0 錯誤,測試覆蓋率 > 80%」
A - Achievable(可達成):
- 反例:「整合所有第三方 API」(範圍太大)- 正例:「整合 Google Books API 的書籍搜尋功能」
R - Relevant(相關):
- 反例:「優化 UI 顏色」(與 Repository Ticket 無關)- 正例:「Repository 實作完成,測試通過」
T - Time-bound(有明確完成標準):
- 反例:「未來會完成」(無明確標準)- 正例:「符合所有驗收條件即完成」
3.5 Ticket 關閉條件
Ticket 必須滿足以下所有條件才能關閉:
強制條件(5 項):
- 所有驗收條件打勾完成
- Review 通過
- 相關測試 100% 通過
- dart analyze 0 錯誤
- 工作日誌已更新
建議條件(3 項):
- 程式碼符合專案規範
- 無技術債務產生
- 文檔同步更新
3.6 生命週期管理檢查清單
Ticket 建立檢查(3 項):
- 標題格式正確(動詞 + 目標)
- 5 個核心欄位完整
- 驗收條件符合 SMART 原則
Ticket 執行檢查(4 項):
- 依賴 Ticket 已完成
- 開發者理解目標和步驟
- 進度持續更新
- 遇到問題即時記錄
Ticket Review 檢查(4 項):
- 所有驗收條件滿足
- 測試 100% 通過
- 程式碼品質符合標準
- 文檔同步更新
Ticket 關閉檢查(3 項):
- Review 通過
- 工作日誌已更新
- 主版本日誌索引已更新
第四章:即時 Review 機制
4.1 一邊實作一邊 review 的原則
傳統 Review 問題:
傳統的「實作完成後才 review」存在以下問題:
- 發現問題太晚:實作偏差已形成,修正成本高
- 返工時間長:需要大幅修改已完成的程式碼
- 士氣影響大:開發者認為「白做了」,影響積極性
- 無法並行:必須等所有任務完成才能 review
即時 Review 原則:
「一邊實作一邊 review」的核心原則:
- 每完成一個 Ticket 觸發 review
- review 快速完成,聚焦核心問題
- 只 review 當前 Ticket,不累積
- 發現問題立即建立修正 Ticket
效益:
| 維度 | 傳統 Review | 即時 Review |
|---|---|---|
| 問題發現時機 | 實作完成後(數天後) | 每個 Ticket 完成後(即時) |
| 修正成本 | 高(需大幅修改) | 低(只需修正單一 Ticket) |
| 開發者體驗 | 挫折感(白做了) | 即時回饋(快速修正) |
| 可並行性 | 低(必須等全部完成) | 高(可持續並行開發) |
4.2 Review 觸發時機
觸發條件:
Review 在以下時機觸發:
- 每完成一個 Ticket:開發者標記 Ticket 為「Review 中」
- 每完成 3-5 個 Ticket:觸發階段性 review(可選)
- 每完成一個模組:觸發模組整合 review(可選)
主要觸發機制:
每完成一個 Ticket 觸發:
- 開發者完成 Ticket,自我檢查驗收條件
- 標記 Ticket 為「Review 中」
- Reviewer 收到通知,開始 review
- Review 快速完成,聚焦核心問題
不等待:
- 不等待整個任務完成才 review
- 不累積多個 Ticket 一起 review
- 不延後 review 時機
4.3 Review 檢查項目
Review 分為 4 大類,共 16 項檢查項:
類別 1:功能正確性檢查(4 項)
檢查項 1:Ticket 描述的功能是否實現?
- 檢查方法:對照 Ticket 目標和實際程式碼
- 通過標準:功能完全符合 Ticket 描述
檢查項 2:驗收條件是否全部滿足?
- 檢查方法:逐項檢查驗收條件 checkbox
- 通過標準:所有條件都打勾且確實滿足
檢查項 3:是否有未處理的邊界情況?
- 檢查方法:檢查 null、empty、異常輸入處理
- 通過標準:所有邊界情況都有處理
檢查項 4:錯誤處理是否完整?
- 檢查方法:檢查 try-catch、異常拋出
- 通過標準:所有異常都有妥善處理
類別 2:架構合規性檢查(4 項)
檢查項 5:是否符合 Clean Architecture 分層原則?
- 檢查方法:檢查檔案位置、模組分層
- 通過標準:符合 Domain/Application/Infrastructure/Presentation 分層
檢查項 6:依賴方向是否正確(內層不依賴外層)?
- 檢查方法:檢查 import 語句
- 通過標準:所有依賴都指向內層或 Interface
檢查項 7:是否使用 Interface-Driven 開發?
- 檢查方法:檢查是否依賴 Interface 而非具體實作
- 通過標準:外層依賴 Interface,不直接依賴實作類別
檢查項 8:是否有架構債務產生?
- 檢查方法:檢查是否有違反 SOLID 原則的程式碼
- 通過標準:無明顯架構債務
類別 3:測試通過率檢查(4 項)
檢查項 9:相關單元測試是否 100% 通過?
- 檢查方法:執行
dart test或flutter test - 通過標準:所有測試通過,0 失敗
檢查項 10:相關整合測試是否 100% 通過?
- 檢查方法:執行整合測試
- 通過標準:所有整合測試通過
檢查項 11:測試覆蓋率是否達標?
- 檢查方法:檢查測試覆蓋率報告
- 通過標準:覆蓋率 > 80%(建議)
檢查項 12:是否有測試被 skip?
- 檢查方法:搜尋
skip:或.skip - 通過標準:無 skip 的測試
類別 4:文檔同步性檢查(4 項)
檢查項 13:Ticket 工作日誌是否更新?
- 檢查方法:檢查對應的 Ticket 日誌檔案
- 通過標準:記錄執行過程和決策
檢查項 14:設計決策是否記錄?
- 檢查方法:檢查設計決策日誌
- 通過標準:重要決策都有記錄
檢查項 15:API 文檔是否同步?
- 檢查方法:檢查程式碼註解和 dartdoc
- 通過標準:公開 API 都有完整文檔註解
檢查項 16:README 是否需要更新?
- 檢查方法:檢查是否有新增功能或變更使用方式
- 通過標準:如需更新則已更新
4.4 偏差糾正流程
當 Review 發現問題時,執行以下偏差糾正流程:
1Review 發現偏差
2 ↓
3暫停當前 Ticket
4 ↓
5記錄偏差問題(描述、影響、根因)
6 ↓
7分析根因
8 ├─ 理解錯誤? → 釐清需求,重新執行
9 ├─ 技術問題? → 尋求技術支援
10 └─ 架構問題? → 修正架構設計
11 ↓
12建立修正 Ticket
13 ↓
14修正 Ticket 執行
15 ↓
16再次 Review
17 ├─ 通過 → 標記原 Ticket 為「已完成」
18 └─ 未通過 → 重複偏差糾正流程
19 ↓
20總結經驗教訓(更新檢查清單)偏差記錄格式:
1### Review 偏差記錄 #N
2
3**發現時間**:2025-10-10 14:30
4
5**偏差描述**:
6實作的 Repository 方法簽名與 Interface 不一致
7
8**影響範圍**:
9
10- SQLiteBookRepository.getBookByIsbn 方法
11- 相關測試需要調整
12
13**根因分析**:
14開發者未參考最新的 Interface 定義
15
16**糾正措施**:
17
18- 建立修正 Ticket:修正 Repository 方法簽名
19- 更新相關測試
20- 加入檢查清單:實作前必須確認 Interface 最新版本
21
22**責任歸屬**:
23開發者(未確認 Interface)+ Reviewer(未及時發現)
24
25**經驗教訓**:
26實作前必須先閱讀最新的 Interface 定義4.5 Review 記錄格式
每次 Review 都必須記錄,格式如下:
1### Review 記錄 - Ticket #N
2
3**Review 時間**:2025-10-10 15:00
4
5**Reviewer**:張三
6
7**Ticket 標題**:實作 SQLiteBookRepository
8
9**Review 結果**:通過 / 未通過
10
11**檢查項目**:
12
13- [x] 功能正確性(4/4 通過)
14- [x] 架構合規性(4/4 通過)
15- [x] 測試通過率(4/4 通過)
16- [x] 文檔同步性(4/4 通過)
17
18**發現問題**:
19
20- 無(如果有,列出問題清單)
21
22**建議改善**:
23
24- 建議補充更多邊界情況測試(可選)
25
26**Review 時間**:8 分鐘
27
28**下一步行動**:
29
30- 標記 Ticket 為「已完成」
31- 更新主版本日誌索引4.6 即時 Review 檢查清單
Review 前準備(3 項):
- Reviewer 收到 review 通知
- Ticket 標記為「Review 中」
- 所有驗收條件已打勾
Review 執行(4 項):
- 逐項檢查 16 個檢查項目
- 記錄 Review 結果
- 發現問題建立偏差記錄
- Review 快速完成,聚焦核心問題
Review 後處理(2 項):
- 通過:標記 Ticket 為「已完成」
- 未通過:建立修正 Ticket
持續改善(5 項):
- 總結經驗教訓
- 更新檢查清單(如需要)
- 優化 Review 流程
- 提升 Review 效率
- 降低偏差發生率
第五章:文件管理策略
5.1 避免工作日誌臃腫的三層文件結構
問題分析:v0.12.7 工作日誌臃腫案例
v0.12.7 工作日誌問題:
- 檔案大小:6000 行
- 問題根因:
- 所有 Ticket 日誌都寫在主版本日誌
- 設計迭代過程全部記錄在同一檔案
- 缺乏分層管理機制
影響:
- 開發者難以快速找到關鍵資訊
- 檔案過大導致編輯器效能下降
- 歷史記錄難以追溯
三層文件結構設計
為了解決工作日誌臃腫問題,採用三層文件結構:
第 1 層:主版本日誌(Main Version Log)
檔案命名:vX.Y.Z-main.md
目標大小:500-800 行
內容範圍:
- 版本目標和規劃
- Ticket 索引(只記錄 Ticket 編號和標題)
- 設計決策索引(連結到決策日誌)
- 版本總結
範例:
1# v0.12.7 主版本日誌
2
3## 版本目標
4實現書籍資訊豐富化功能
5
6## Ticket 索引
7- Ticket #1: 定義 IBookInfoEnrichmentService 介面 → [詳細日誌](/record/ticket_v2/v0.12.7-ticket-001.md)
8- Ticket #2: 撰寫 BookInfoEnrichmentService 測試 → [詳細日誌](/record/ticket_v2/v0.12.7-ticket-002.md)
9- Ticket #3: 實作 GoogleBooksEnrichmentService → [詳細日誌](/record/ticket_v2/v0.12.7-ticket-003.md)
10
11## 設計決策索引
12- 決策 #1: 選擇 Strategy Pattern 處理多資料源 → [詳細日誌](/record/ticket_v2/v0.12.7-design-decisions.md#決策1)
13- 決策 #2: 使用 Riverpod 管理服務註冊 → [詳細日誌](/record/ticket_v2/v0.12.7-design-decisions.md#決策2)
14
15## 版本總結
16- 完成 12 個 Ticket
17- 總開發時間:4.5 小時
18- 測試覆蓋率:92%第 2 層:Ticket 工作日誌(Ticket Work Log)
檔案命名:vX.Y.Z-ticket-NNN.md
目標大小:100-200 行
內容範圍:
- Ticket 描述(背景、目標、步驟、驗收條件)
- 執行過程記錄
- 遇到的問題和解決方案
- Review 結果
範例:
1# Ticket #1 工作日誌
2
3## Ticket 描述
4定義 IBookInfoEnrichmentService 介面
5
6### 背景
7根據 UC-05 需求,需要建立書籍資訊豐富化服務的介面契約
8
9### 目標
10建立 `IBookInfoEnrichmentService` 介面,定義書籍資訊豐富化的契約
11
12### 步驟
131. 建立介面檔案
142. 定義 `enrichBook` 方法
153. 定義 `enrichProgress` 方法
164. 撰寫文檔註解
17
18### 驗收條件
19- [x] 介面檔案建立在正確位置
20- [x] 方法簽名完整且明確
21- [x] 包含完整的文檔註解
22- [x] dart analyze 0 錯誤
23
24## 執行過程
251. 建立 `lib/domains/import/services/i_book_info_enrichment_service.dart`
262. 定義 `enrichBook` 方法:接收 ISBN,回傳豐富化後的 Book
273. 定義 `enrichProgress` 方法:回傳豐富化進度 Stream
284. 補充文檔註解說明每個方法的用途
29
30## Review 結果
31通過(8 分鐘)
32- 功能正確性:4/4 通過
33- 架構合規性:4/4 通過第 3 層:設計決策日誌(Design Decision Log)
檔案命名:vX.Y.Z-design-decisions.md
目標大小:300-500 行
內容範圍:
- 重要設計決策記錄
- 技術選型理由
- 架構調整說明
- 決策的影響分析
範例:
1# v0.12.7 設計決策日誌
2
3## 決策 #1: 選擇 Strategy Pattern 處理多資料源
4
5### 決策時間
62025-10-09 14:30
7
8### 決策背景
9書籍資訊豐富化需要支援多個資料來源(Google Books、Open Library、豆瓣讀書)
10
11### 可選方案
121. **方案 A**:使用 if-else 判斷資料來源
132. **方案 B**:使用 Strategy Pattern 封裝每個資料來源
143. **方案 C**:使用 Chain of Responsibility Pattern
15
16### 選擇理由
17選擇方案 B(Strategy Pattern):
18
19- 每個資料來源獨立封裝,符合 Open-Closed Principle
20- 新增資料來源只需新增 Strategy,不修改現有程式碼
21- 可以動態切換資料來源策略
22
23### 影響範圍
24- 建立 `IEnrichmentStrategy` 介面
25- 實作 `GoogleBooksStrategy`、`OpenLibraryStrategy`
26- `BookInfoEnrichmentService` 依賴 `IEnrichmentStrategy`
27
28### 實作 Ticket
29- Ticket #4: 定義 IEnrichmentStrategy 介面
30- Ticket #5: 實作 GoogleBooksStrategy
31- Ticket #6: 實作 OpenLibraryStrategy三層結構效益
效益總結:
| 維度 | v0.12.7 單一檔案(6000 行) | 三層結構(800+200*N+400 行) |
|---|---|---|
| 可讀性 | 低(難以快速找到資訊) | 高(分層清晰) |
| 維護性 | 低(修改影響範圍大) | 高(獨立修改) |
| 查找效率 | 低(需搜尋整個檔案) | 高(索引快速定位) |
| 協作友善 | 低(衝突機率高) | 高(不同檔案並行編輯) |
改善數據:
- 主版本日誌:6000 行 → 800 行(減少 87%)
- Ticket 日誌:分散到 12 個檔案,每個 150 行
- 設計決策日誌:獨立 400 行
5.2 設計迭代文件管理
設計迭代的挑戰
問題: 設計過程中會產生多個版本的設計文件:
- 初版設計(可能有缺陷)
- 修正版設計(發現問題後調整)
- 最終設計(經過 review 確認)
如果不管理:
- 開發者不知道哪個是最終版本
- 過時的設計誤導後續開發
- 設計演進過程難以追溯
版本管理策略
策略 1:設計檔案版本標記
在設計決策日誌中明確標記版本狀態:
1## 決策 #1: 選擇 Strategy Pattern 處理多資料來源
2
3**決策狀態**:最終決策(已實作)
4
5**版本歷史**:
6
7- v1 (2025-10-09 14:30): 初版設計 - 使用 if-else 判斷(已廢棄)
8- v2 (2025-10-09 15:00): 修正版 - 改用 Strategy Pattern(最終版本)
9
10**當前版本**: v2策略 2:最終設計明確標記
在主版本日誌中明確標記最終設計:
1## 設計決策索引
2- 決策 #1: 選擇 Strategy Pattern(最終決策)→ [詳細日誌](/record/ticket_v2/v0.12.7-design-decisions.md#決策1)
3- 決策 #2: 使用 Riverpod 管理服務(最終決策)→ [詳細日誌](/record/ticket_v2/v0.12.7-design-decisions.md#決策2)
4- ~~決策 #3: 使用 GetIt 管理服務~~(已廢棄,改用決策 #2)策略 3:廢棄設計保留但標記
不刪除過時設計,而是標記為廢棄並說明原因:
1## ~~決策 #3: 使用 GetIt 管理服務~~(已廢棄)
2
3**廢棄原因**:
4發現 Riverpod 更適合 Flutter 3.x,提供更好的型別安全
5
6**廢棄時間**:2025-10-09 16:00
7
8**替代決策**:決策 #2(使用 Riverpod)
9
10**保留原因**:
11記錄設計演進過程,避免重複評估相同方案5.3 開發者查找設計的指引
設計查找流程
步驟 1:從主版本日誌開始
開發者接到任務時,先查看主版本日誌:
1# v0.12.7 主版本日誌
2
3## 快速導航
4- [版本目標](#版本目標)
5- [Ticket 索引](#Ticket索引)
6- [設計決策索引](#設計決策索引)(開發者從這裡開始)步驟 2:查看設計決策索引
根據任務相關的領域,找到對應的設計決策:
1## 設計決策索引
2
3### 服務層設計
4- 決策 #1: 選擇 Strategy Pattern(最終決策)→ [詳細](/record/ticket_v2/v0.12.7-design-decisions.md#決策1)
5- 決策 #2: 使用 Riverpod 管理服務(最終決策)→ [詳細](/record/ticket_v2/v0.12.7-design-decisions.md#決策2)
6
7### 資料層設計
8- 決策 #4: 選擇 SQLite 儲存(最終決策)→ [詳細](/record/ticket_v2/v0.12.7-design-decisions.md#決策4)步驟 3:閱讀設計決策詳細內容
點擊連結進入設計決策日誌,閱讀詳細內容:
1## 決策 #1: 選擇 Strategy Pattern 處理多資料來源
2
3**決策狀態**:最終決策(已實作)
4
5### 決策背景
6...
7
8### 選擇理由
9...
10
11### 影響範圍
12...
13
14### 實作 Ticket
15- Ticket #4: 定義 IEnrichmentStrategy 介面
16- Ticket #5: 實作 GoogleBooksStrategy步驟 4:查看相關 Ticket
根據設計決策中的「實作 Ticket」,查看具體實作細節:
1# Ticket #4 工作日誌
2
3## Ticket 描述
4定義 IEnrichmentStrategy 介面
5...設計文件索引規範
主版本日誌索引格式:
1## 設計決策索引
2
3### [領域名稱]
4- 決策 #N: [決策摘要](最終決策 / 已廢棄)→ [詳細日誌連結]
5
6**索引規則**:
7
81. 按領域分組(服務層、資料層、UI 層)
92. 標記決策狀態(最終決策、已廢棄)
103. 提供直接連結到詳細日誌設計決策日誌格式:
1## 決策 #N: [決策標題]
2
3**決策狀態**:最終決策 / 已廢棄
4
5**相關 Ticket**:
6
7- Ticket #X: [Ticket 標題]
8- Ticket #Y: [Ticket 標題]
9
10**決策背景**:...
11**選擇理由**:...
12**影響範圍**:...5.4 文件管理檢查清單
主版本日誌檢查(4 項):
- 版本目標明確且可驗證
- Ticket 索引完整(所有 Ticket 都有連結)
- 設計決策索引清晰(按領域分組)
- 檔案大小控制在 500-800 行
Ticket 工作日誌檢查(4 項):
- 檔案命名符合規範(vX.Y.Z-ticket-NNN.md)
- Ticket 描述完整(6 個核心欄位)
- 執行過程記錄清楚
- 檔案大小控制在 100-200 行
設計決策日誌檢查(4 項):
- 每個決策都有明確的狀態標記
- 廢棄決策保留但標記廢棄原因
- 版本歷史記錄完整
- 檔案大小控制在 300-500 行
設計文件索引檢查(4 項):
- 主版本日誌有「快速導航」區塊
- 設計決策索引按領域分組
- 所有連結都正確指向目標
- 最終決策明確標記
第六章:與敏捷重構和 TDD 的整合
6.1 Ticket 機制與三重文件原則的關係
三重文件原則回顧
本專案採用三重文件原則(CHANGELOG + todolist + work-log)進行全方位進度管理:
1. CHANGELOG.md:
- 面向用戶的版本功能描述
- 只記錄「做了什麼」,不記錄「怎麼做」
2. todolist.md:
- 記錄整個開發過程所有待處理任務
- 任務狀態追蹤(待執行/進行中/已完成)
3. work-log/:
- 完整的技術實作細節和決策過程
- TDD 四階段進度追蹤
Ticket 機制如何融入三重文件
Ticket 機制定位:
Ticket 機制是「work-log 層」的細化管理工具:
- work-log 主版本日誌 = Ticket 索引 + 版本總覽
- work-log Ticket 日誌 = 單一 Ticket 的執行記錄
- work-log 設計決策日誌 = 設計迭代過程記錄
整合關係:
1CHANGELOG.md(版本功能描述)
2 ↑ 提取功能變動
3work-log/vX.Y.Z-main.md(主版本日誌)
4 ↓ Ticket 索引
5work-log/vX.Y.Z-ticket-NNN.md(Ticket 日誌)
6 ↑ 完成狀態
7todolist.md(任務狀態追蹤)協作流程:
PM 規劃階段:
- 在
todolist.md建立任務項目 - 在
vX.Y.Z-main.md規劃 Ticket 索引
- 在
開發執行階段:
- 建立
vX.Y.Z-ticket-NNN.mdTicket 日誌 - 執行 Ticket,記錄過程
- 完成後更新
todolist.md狀態
- 建立
版本發布階段:
- 從
vX.Y.Z-main.md提取功能變動 - 更新
CHANGELOG.md版本說明
- 從
6.2 Ticket 與 TDD 階段的對應關係
TDD 階段與 Ticket 類型對應
Phase 1(功能設計)→ Interface 定義 Ticket:
Phase 1 產出的設計決策 → 轉化為 Interface 定義 Ticket:
1Phase 1 產出:
2
3- IBookRepository 介面設計
4- IBookInfoEnrichmentService 介面設計
5
6↓ 轉化為 Ticket
7
8Ticket #1: 定義 IBookRepository 介面
9Ticket #2: 定義 IBookInfoEnrichmentService 介面Phase 2(測試設計)→ 測試撰寫 Ticket:
Phase 2 產出的測試設計 → 轉化為測試撰寫 Ticket:
1Phase 2 產出:
2
3- BookRepository 測試用例設計
4- BookInfoEnrichmentService 測試用例設計
5
6↓ 轉化為 Ticket
7
8Ticket #3: 撰寫 BookRepository 測試
9Ticket #4: 撰寫 BookInfoEnrichmentService 測試Phase 3(實作執行)→ 具體實作 Ticket + 整合 Ticket:
Phase 3 產出的實作 → 拆分為具體實作和整合 Ticket:
1Phase 3 產出:
2
3- SQLiteBookRepository 實作
4- GoogleBooksEnrichmentService 實作
5- 整合到 Use Case
6
7↓ 轉化為 Ticket
8
9Ticket #5: 實作 SQLiteBookRepository
10Ticket #6: 實作 GoogleBooksEnrichmentService
11Ticket #7: 整合到 GetBookUseCasePhase 4(重構優化)→ 重構 Ticket:
Phase 4 發現的重構需求 → 建立重構 Ticket:
1Phase 4 發現:
2
3- BookRepository 邏輯複雜,需要拆分
4- EnrichmentService 錯誤處理不完整
5
6↓ 轉化為 Ticket
7
8Ticket #8: 重構 BookRepository,拆分 CRUD 邏輯
9Ticket #9: 補充 EnrichmentService 錯誤處理TDD 階段完成標準與 Ticket 關係
Phase 1 完成標準:
- 所有 Interface 定義 Ticket 建立並標記為「待執行」
- 設計決策日誌記錄完整
Phase 2 完成標準:
- 所有測試撰寫 Ticket 建立並標記為「待執行」
- 測試覆蓋所有 Interface 方法
Phase 3 完成標準:
- 所有具體實作 Ticket 完成並通過 review
- 所有整合 Ticket 完成並通過測試
- 測試 100% 通過
Phase 4 完成標準:
- 所有重構 Ticket 完成並通過 review
- 程式碼品質達標,無技術債務
6.3 Ticket 派工前的準備度檢查
準備度檢查清單
在建立和派工 Ticket 前,必須檢查以下準備度:
設計準備度(4 項):
- 相關設計決策已完成且標記為「最終決策」
- Interface 定義已完成(如適用)
- 設計決策日誌已更新
- 沒有未解決的設計問題
依賴準備度(3 項):
- 依賴的 Ticket 已完成
- 依賴的 Interface 已定義
- 依賴的測試已撰寫(如適用)
資源準備度(3 項):
- 開發者已理解 Ticket 目標
- 開發環境已準備就緒
- 相關文檔已閱讀
品質準備度(2 項):
- 驗收條件明確且可驗證
- Review 機制已建立
準備度不足的處理
發現準備度不足時:
1Ticket 派工前檢查
2 ↓
3準備度檢查
4 ├─ 通過 → 派工執行
5 └─ 不通過 → 暫停派工
6 ↓
7 分析缺失項目
8 ├─ 設計不完整 → 補充設計決策
9 ├─ 依賴未完成 → 等待依賴 Ticket
10 └─ 資源不足 → 準備環境和文檔
11 ↓
12 重新檢查準備度6.4 Ticket 完成後的文件更新
更新流程
每完成一個 Ticket,必須更新以下文件:
步驟 1:更新 Ticket 工作日誌
在 vX.Y.Z-ticket-NNN.md 記錄:
- 執行過程
- Review 結果
- 遇到的問題和解決方案
步驟 2:更新主版本日誌
在 vX.Y.Z-main.md 更新:
- Ticket 索引(標記為已完成)
- 如有新的設計決策,更新設計決策索引
步驟 3:更新 todolist
在 todolist.md 更新:
- 標記對應任務為「已完成」
- 如發現新任務,新增到待辦清單
步驟 4:更新設計決策日誌(如適用)
在 vX.Y.Z-design-decisions.md 更新:
- 如有設計調整,記錄新的決策版本
- 如廢棄舊決策,標記廢棄原因
6.5 整合檢查清單
Ticket 建立檢查(4 項):
- Ticket 來自 TDD Phase 1-4 的產出
- Ticket 類型符合 Clean Architecture 分層
- Ticket 已連結到設計決策日誌
- Ticket 準備度檢查通過
Ticket 執行檢查(4 項):
- 執行過程記錄到 Ticket 日誌
- 完成後更新主版本日誌索引
- 完成後更新 todolist 狀態
- 如有設計調整,更新設計決策日誌
文件同步檢查(4 項):
- Ticket 日誌大小控制在 100-200 行
- 主版本日誌索引保持最新
- 設計決策狀態正確標記
- todolist 任務狀態與實際一致
第七章:實務案例和模板
7.1 v0.12.7 工作日誌臃腫問題分析
原始問題描述
v0.12.7 版本資訊:
- 功能範圍:書籍資訊豐富化功能
- 工作日誌大小:6000 行
- 開發時間:5 天
- Ticket 數量:未明確拆分
臃腫問題根因:
根因 1:缺乏 Ticket 拆分機制
- 所有實作細節都寫在主版本日誌
- 沒有建立獨立的 Ticket 日誌
- 設計迭代過程全部記錄在同一檔案
根因 2:設計迭代未分層管理
- 初版設計、修正版設計、最終設計混在一起
- 廢棄的設計沒有明確標記
- 開發者難以找到最終設計
根因 3:缺乏文件索引機制
- 沒有 Ticket 索引
- 沒有設計決策索引
- 開發者需搜尋整個檔案才能找到資訊
問題影響分析
影響 1:開發效率降低
- 開發者花費 30% 時間搜尋設計資訊
- 編輯器效能下降(檔案過大)
- 協作衝突頻繁(多人編輯同一檔案)
影響 2:品質風險增加
- 使用過時的設計實作(找錯版本)
- Review 困難(難以理解上下文)
- 技術債務累積(沒時間重構)
影響 3:知識傳承困難
- 新成員難以快速理解設計演進
- 歷史決策難以追溯
- 重複犯錯(不知道為什麼廢棄某設計)
7.2 基於 Ticket 機制的改善方案
改善方案設計
方案目標: 將 6000 行主版本日誌改善為三層文件結構,控制在約 2000 行總量(800+200*6+400)。
改善步驟:
步驟 1:Ticket 拆分(回溯分析)
分析 v0.12.7 的開發過程,回溯拆分為 12 個 Ticket:
Domain 層 Ticket(3 個):
- Ticket #1: 定義 IBookInfoEnrichmentService 介面
- Ticket #2: 定義 IEnrichmentStrategy 介面
- Ticket #3: 定義 EnrichmentProgress Value Object
Application 層 Ticket(2 個):
- Ticket #4: 定義 EnrichBookUseCase 介面
- Ticket #5: 實作 EnrichBookInteractor
Infrastructure 層 Ticket(4 個):
- Ticket #6: 實作 GoogleBooksStrategy
- Ticket #7: 實作 OpenLibraryStrategy
- Ticket #8: 實作 BookInfoEnrichmentService
- Ticket #9: 實作 Riverpod Provider 註冊
測試 Ticket(3 個):
- Ticket #10: 撰寫 BookInfoEnrichmentService 測試
- Ticket #11: 撰寫 EnrichBookInteractor 測試
- Ticket #12: 撰寫整合測試
步驟 2:建立三層文件結構
主版本日誌(800 行):
1# v0.12.7 主版本日誌
2
3## 快速導航
4- [版本目標](#版本目標)
5- [Ticket 索引](#Ticket索引)(12 個 Ticket)
6- [設計決策索引](#設計決策索引)(5 個決策)
7- [版本總結](#版本總結)
8
9## Ticket 索引
10
11### Domain 層
12- Ticket #1: 定義 IBookInfoEnrichmentService 介面 → [詳細](/record/ticket_v2/v0.12.7-ticket-001.md)
13- Ticket #2: 定義 IEnrichmentStrategy 介面 → [詳細](/record/ticket_v2/v0.12.7-ticket-002.md)
14- Ticket #3: 定義 EnrichmentProgress Value Object → [詳細](/record/ticket_v2/v0.12.7-ticket-003.md)
15
16### Application 層
17- Ticket #4: 定義 EnrichBookUseCase 介面 → [詳細](/record/ticket_v2/v0.12.7-ticket-004.md)
18- Ticket #5: 實作 EnrichBookInteractor → [詳細](/record/ticket_v2/v0.12.7-ticket-005.md)
19...Ticket 工作日誌(200 行 × 12 = 2400 行,分散到 12 個檔案):
1# Ticket #1 工作日誌
2
3## Ticket 描述
4定義 IBookInfoEnrichmentService 介面
5
6### 背景
7根據 UC-05 需求,需要建立書籍資訊豐富化服務的介面契約
8...
9
10## 執行過程
111. 建立介面檔案
122. 定義方法簽名
13...
14
15## Review 結果
16通過(8 分鐘)設計決策日誌(400 行):
1# v0.12.7 設計決策日誌
2
3## 決策 #1: 選擇 Strategy Pattern 處理多資料源
4
5**決策狀態**:最終決策(已實作)
6
7**版本歷史**:
8
9- v1 (2025-10-09 14:30): 初版設計 - 使用 if-else 判斷(已廢棄)
10- v2 (2025-10-09 15:00): 修正版 - 改用 Strategy Pattern(最終版本)
11...步驟 3:建立設計文件索引
在主版本日誌建立清晰的索引:
1## 設計決策索引
2
3### 服務層設計
4- 決策 #1: 選擇 Strategy Pattern(最終決策)→ [詳細](/record/ticket_v2/v0.12.7-design-decisions.md#決策1)
5- 決策 #2: 使用 Riverpod 管理服務(最終決策)→ [詳細](/record/ticket_v2/v0.12.7-design-decisions.md#決策2)
6
7### 資料來源設計
8- 決策 #3: Google Books 為主要資料源(最終決策)→ [詳細](/record/ticket_v2/v0.12.7-design-decisions.md#決策3)
9- ~~決策 #4: 豆瓣讀書為備用資料源~~(已廢棄,API 限制)改善效果評估
檔案大小改善:
| 維度 | 改善前 | 改善後 | 改善幅度 |
|---|---|---|---|
| 主版本日誌 | 6000 行 | 800 行 | -87% |
| Ticket 日誌 | 0(混在主日誌) | 200 行 × 12 = 2400 行 | 分散管理 |
| 設計決策日誌 | 0(混在主日誌) | 400 行 | 獨立管理 |
| 總計 | 6000 行(單一檔案) | 3600 行(14 個檔案) | -40% 且分散 |
查找效率改善:
| 任務 | 改善前 | 改善後 | 效率提升 |
|---|---|---|---|
| 找到特定 Ticket | 搜尋 6000 行 | 查索引 → 直接開啟 | 90% ↑ |
| 找到最終設計 | 搜尋全文 | 查設計決策索引 | 85% ↑ |
| 理解設計演進 | 難以追溯 | 查版本歷史 | 80% ↑ |
7.3 Ticket 模板集合
模板 1:Interface 定義 Ticket
1## Ticket #N: 定義 [Interface 名稱] 介面
2
3### 背景
4根據 [需求編號] 需求,需要建立 [功能描述] 的介面契約
5
6### 目標
7建立 `[Interface 名稱]` 介面,定義 [功能描述] 的契約
8
9### 步驟
101. 在 `lib/domains/[domain]/[layer]/` 建立 `[interface_file].dart`
112. 定義 `[method1]` 方法簽名
123. 定義 `[method2]` 方法簽名
134. 撰寫文檔註解
14
15### 驗收條件
16- [ ] Interface 檔案建立在正確位置
17- [ ] 所有方法簽名完整且明確
18- [ ] 輸入輸出類型定義清楚
19- [ ] 包含完整的文檔註解
20- [ ] dart analyze 0 錯誤
21
22### 參考文件
23- [設計文件連結]
24- [需求文件連結]
25
26### 依賴 Ticket
27- 無(Interface 定義通常是第一個 Ticket)模板 2:具體實作 Ticket
1## Ticket #N: 實作 [類別名稱]
2
3### 背景
4根據 [Interface 名稱] 介面契約,實作 [功能描述]
5
6### 目標
7實作 `[類別名稱]`,提供 [功能描述]
8
9### 步驟
101. 建立 `[類別名稱]` 類別
112. 實作 `[method1]` 方法
123. 實作 `[method2]` 方法
134. 處理異常情況
145. 確保所有測試通過
15
16### 驗收條件
17- [ ] 實作所有 [Interface 名稱] 方法
18- [ ] 異常處理完整(列出可能的異常)
19- [ ] 單元測試 100% 通過
20- [ ] dart analyze 0 錯誤
21
22### 參考文件
23- [Interface 定義 Ticket]
24- [設計決策日誌]
25
26### 依賴 Ticket
27- Ticket #X: 定義 [Interface 名稱] 介面(必須先完成)模板 3:測試撰寫 Ticket
1## Ticket #N: 撰寫 [類別名稱] 測試
2
3### 背景
4為 `[類別名稱]` 撰寫完整的測試用例,確保功能正確性
5
6### 目標
7撰寫 `[類別名稱]` 的完整測試用例
8
9### 步驟
101. 建立測試檔案 `[test_file]_test.dart`
112. 撰寫 `[method1]` 測試(正常流程 + 異常處理)
123. 撰寫 `[method2]` 測試(正常流程 + 異常處理)
134. 確保所有測試通過
14
15### 驗收條件
16- [ ] 測試檔案建立在 `test/unit/[path]/`
17- [ ] 至少 [N] 個測試用例
18- [ ] 覆蓋所有方法的正常流程
19- [ ] 覆蓋所有方法的異常處理
20- [ ] 所有測試 100% 通過
21
22### 參考文件
23- [Interface 定義 Ticket]
24- [測試設計文件]
25
26### 依賴 Ticket
27- Ticket #X: 定義 [Interface 名稱] 介面(必須先完成)模板 4:整合連接 Ticket
1## Ticket #N: 整合 [Module A] 到 [Module B]
2
3### 背景
4將 `[Module A]` 整合到 `[Module B]`,實現完整流程
5
6### 目標
7連接 [Module A] 和 [Module B],實現端到端功能
8
9### 步驟
101. 修改 `[Module B]` 注入 `[Module A Interface]`
112. 在 `[method]` 方法中呼叫 `[Module A].[method]`
123. 處理 [Module A] 的異常
134. 撰寫整合測試驗證端到端流程
145. 確保所有測試通過
15
16### 驗收條件
17- [ ] `[Module B]` 正確注入 `[Module A Interface]`
18- [ ] 端到端流程正常運作
19- [ ] 整合測試 100% 通過
20- [ ] 異常處理完整
21
22### 參考文件
23- [Module A 實作 Ticket]
24- [Module B 實作 Ticket]
25- [整合設計文件]
26
27### 依賴 Ticket
28- Ticket #X: 實作 [Module A](必須先完成)
29- Ticket #Y: 實作 [Module B](必須先完成)模板 5:重構 Ticket
1## Ticket #N: 重構 [功能描述]
2
3### 背景
4Phase 4 發現 [問題描述],需要重構改善
5
6### 目標
7重構 `[類別名稱]`,[改善目標]
8
9### 步驟
101. 分析當前程式碼問題
112. 設計重構方案
123. 執行重構(保持測試通過)
134. 驗證功能未受影響
145. 確保所有測試通過
15
16### 驗收條件
17- [ ] 重構完成,程式碼品質改善
18- [ ] 所有測試 100% 通過(功能未受影響)
19- [ ] dart analyze 0 錯誤
20- [ ] 無新的技術債務產生
21
22### 參考文件
23- [Phase 4 重構報告]
24- [程式碼品質標準]
25
26### 依賴 Ticket
27- 無(重構可獨立進行)7.4 常見錯誤和解決方案
錯誤 1:Ticket 拆分過細或過粗
問題描述:
- 過細:Ticket 的職責過於單一,失去獨立交付價值
- 過粗:Ticket 包含過多職責(>5 個)或檔案(>5 個),失去即時 review 的效益
解決方案:
- 標準複雜度:控制在單一職責或少數相關職責
- 過細時:合併相關的小 Ticket 形成完整職責
- 過粗時:按 Clean Architecture 分層或步驟拆分
範例:
1反例 - 過細拆分:
2
3- Ticket #1: 建立檔案(職責不完整)
4- Ticket #2: 定義 class(職責不完整)
5- Ticket #3: 撰寫註解(職責不完整)
6
7正例 - 合理拆分:
8
9- Ticket #1: 定義 Interface(包含建立檔案、定義 class、撰寫註解 - 完整職責)錯誤 2:驗收條件模糊
問題描述: 驗收條件使用主觀描述,無法客觀驗證。
錯誤範例:
1反例 - 模糊的驗收條件:
2
3- [ ] 功能運作正常
4- [ ] 程式碼品質良好
5- [ ] 效能可接受正確範例:
1正例 - 明確的驗收條件:
2
3- [ ] 呼叫 getBookByIsbn('123') 回傳正確的 Book 物件
4- [ ] dart analyze 0 錯誤,測試覆蓋率 > 80%
5- [ ] API 回應時間 < 500ms(在 100 筆資料下)解決方案: 使用 SMART 原則撰寫驗收條件(Specific, Measurable, Achievable, Relevant, Time-bound)。
錯誤 3:忽略 Ticket 依賴關係
問題描述: 沒有明確標註 Ticket 間的依賴關係,導致執行順序錯誤。
錯誤範例:
1反例 - 缺少依賴標註:
2
3- Ticket #1: 實作 Repository
4- Ticket #2: 定義 Repository Interface正確範例:
1正例 - 明確依賴關係:
2
3- Ticket #1: 定義 IBookRepository 介面
4- Ticket #2: 實作 SQLiteBookRepository
5 依賴:Ticket #1(必須先完成)解決方案:
- Interface 定義 Ticket 優先於實作 Ticket
- 測試撰寫 Ticket 可與實作 Ticket 並行
- 整合 Ticket 必須等待所有依賴 Ticket 完成
錯誤 4:Review 累積延後
問題描述: 等待多個 Ticket 完成後才一起 review,失去即時 review 的效益。
錯誤做法:
1完成 Ticket #1 → 繼續 Ticket #2 → 繼續 Ticket #3 → 一起 Review
2(問題:Ticket #1 的錯誤到 Review 時才發現,已完成 #2、#3,需大量返工)正確做法:
1完成 Ticket #1 → Review #1 → 完成 Ticket #2 → Review #2 → 完成 Ticket #3 → Review #3
2(好處:每個 Ticket 完成後立即發現問題,修正成本低)解決方案:
- 每完成一個 Ticket 立即觸發 review
- Review 快速完成,聚焦核心問題
- 發現問題立即建立修正 Ticket
錯誤 5:工作日誌未同步更新
問題描述: Ticket 完成後未更新工作日誌,導致文件與實際進度不一致。
解決方案: 每完成一個 Ticket 必須執行以下更新:
- 更新 Ticket 工作日誌(記錄執行過程和 Review 結果)
- 更新主版本日誌 Ticket 索引(標記為已完成)
- 更新 todolist 任務狀態
- 如有設計調整,更新設計決策日誌
7.5 完整 Ticket 設計檢查清單
Ticket 建立階段檢查清單(10 項)
基本資訊(3 項):
- Ticket 標題格式正確(動詞 + 目標)
- Ticket 編號唯一且連續
- Ticket 分類明確(Interface/實作/測試/整合/重構)
內容完整性(6 項):
- 背景欄位說明來源(需求或設計決策)
- 目標欄位明確且可驗證
- 步驟欄位具體且可操作(3-5 步)
- 驗收條件符合 SMART 原則(3-5 項)
- 參考文件連結正確
- 依賴 Ticket 明確標註
Ticket 執行階段檢查清單(8 項)
執行前檢查(3 項):
- 依賴 Ticket 已完成
- 相關設計決策已確認為「最終決策」
- 開發者已理解目標和步驟
執行中檢查(3 項):
- Ticket 標記為「進行中」
- 執行過程記錄到 Ticket 日誌
- 遇到問題即時記錄
執行後檢查(2 項):
- 所有驗收條件已滿足
- Ticket 標記為「Review 中」
Ticket Review 階段檢查清單(16 項)
功能正確性(4 項):
- Ticket 描述的功能是否實現?
- 驗收條件是否全部滿足?
- 是否有未處理的邊界情況?
- 錯誤處理是否完整?
架構合規性(4 項):
- 是否符合 Clean Architecture 分層原則?
- 依賴方向是否正確(內層不依賴外層)?
- 是否使用 Interface-Driven 開發?
- 是否有架構債務產生?
測試通過率(4 項):
- 相關單元測試是否 100% 通過?
- 相關整合測試是否 100% 通過?
- 測試覆蓋率是否達標(> 80%)?
- 是否有測試被 skip?
文檔同步性(4 項):
- Ticket 工作日誌是否更新?
- 設計決策是否記錄?
- API 文檔是否同步?
- README 是否需要更新?
Ticket 關閉階段檢查清單(8 項)
強制條件(5 項):
- 所有驗收條件打勾完成
- Review 通過
- 相關測試 100% 通過
- dart analyze 0 錯誤
- 工作日誌已更新
建議條件(3 項):
- 程式碼符合專案規範
- 無技術債務產生
- 文檔同步更新
文件版本: v1.0.0(完整版) 最後更新: 2025-10-10