單一版本的工作日誌膨脹到六千行時,它同時在做兩件事:記錄決策脈絡、追蹤任務狀態。這兩件事的讀取方式不同——決策脈絡是事後回查、任務狀態是執行中反覆更新——擠在同一份文件裡,兩邊都變難用。

拆法是把執行層與記錄層分開:Ticket 承載執行,三層日誌承載記錄。

Ticket 是執行層、工作日誌是記錄層

工作日誌是記錄層,寫給之後回來查的人,記錄決策脈絡與其中被放棄的選項。Ticket 是執行層,寫給正在做事的人,代表一個可以獨立完成、驗收、追蹤的最小任務單位。

一張 Ticket 的核心特徵有四個:獨立性(可以獨立執行和驗收)、原子性(不可再分割)、可驗證性(有明確的完成標準)、單一職責(一個動詞加一個目標)。

單一職責是拆分的唯一標準

用量化指標判斷是否需要拆分(職責數量、檔案數量、測試案例數、行數)直觀,而它量的不是職責:一張改動 100 行的 Ticket 可能職責清楚、完全不需要拆;一張只改 30 行的若混了兩個不相關的目標,就該拆。

四個語義檢查取代數字:

語義檢查:能用「動詞加單一目標」描述嗎。描述時出現「並且」或「以及」,通常要拆。

修改原因檢查:只有一個原因會觸發修改嗎。兩個不同的業務規則各自可能觸發修改,就是兩張 Ticket。

驗收一致性:所有驗收條件都指向同一個目標嗎。

依賴獨立性:拆分後不會產生循環依賴嗎。

驗收條件的標準同樣要寫到可檢查:「功能正常」不夠,「所有單元測試通過且 dart analyze 輸出 0 個問題」才算。

Ticket 與 Clean Architecture 的對應

Interface 定義優先於具體實作:每個功能模組先建 Interface 定義的 Ticket,再建具體實作的 Ticket。外層因此可以依賴 Interface 先行開發,不被內層實作進度卡住。

分層拆分讓每張 Ticket 待在自己的架構層。Domain、Application、Infrastructure、Presentation 層的 Ticket 不互相混合,並行執行時的衝突面也跟著縮小。

即時 Review

Review 在整個版本完成後才做時,範圍是整個版本,而問題可能已經影響許多後續實作。

改為每張 Ticket 完成時立即觸發之後,Review 的範圍只有單一 Ticket 的相關程式碼——執行 review 的一方不需要載入整個版本的脈絡,反饋在數小時內完成。

Review 涵蓋四個面向共 16 項:功能正確性(功能實現、驗收條件、邊界情況、錯誤處理)、架構合規性(Clean Architecture、依賴方向、Interface-Driven、架構債務)、測試通過率(單元測試、整合測試、覆蓋率、跳過測試)、文件同步性(Ticket 日誌、設計決策、API 文件、README)。

三層文件結構

記錄層拆成三種文件,各自有自己的行數區間與讀取時機:

  • 主版本日誌(500 到 1000 行):說明版本目標,提供所有 Ticket 的索引
  • Ticket 工作日誌(每張一份,100 到 200 行):記錄執行過程、Review 結果與完成標記
  • 設計決策日誌(300 到 500 行):記錄設計決策的演進,包含被放棄的決策與放棄的原因

六千行的單一文件拆成一份主日誌加十幾份 Ticket 日誌加一份設計決策日誌之後,每次查找要讀的範圍從整份文件縮到其中一份。

積極派發:發現問題就建 Ticket

執行一張 Ticket 時經常會發現超出原本範圍的情況。處理方式若是「繼續在這張 Ticket 裡處理」,Ticket 失去單一職責;若是「先記著等有空再說」,問題離開了追蹤系統。

積極派發的做法是:發現超出範圍的新情況就立刻評估性質,建立對應的新 Ticket。阻塞當前 Ticket 的建子 Ticket 標記依賴;獨立於當前 Ticket 的建新 Ticket 讓兩者並行;屬於未來改進的建技術債務 Ticket 記錄。

換到的是每個決策都有獨立記錄、任務粒度可估、學習點不被大 Ticket 淹沒。

要避開的反模式是「為派發而派發」。判斷標準始終是單一職責:這個情況是否真的超出原 Ticket 的範圍。

四大檢查在 TDD 流程的哪個階段執行,走 Ticket 設計決策集中在 Phase 3a;Review 的觸發時機與 16 項清單,走 即時 Review 機制