Skip to content

撰寫優質規格

你很少會從空白頁面開始撰寫規格。你以淺白的語言描述變更,/opsx:propose 會起草需求與場景,之後你再將它們優化。本頁聚焦於最後這個環節——什麼是「優質」的規格,以及如何引導 AI 產出符合標準的內容。

它是審閱變更的配套文件:審閱是找出草稿中的薄弱之處,撰寫則是明確優質規格的構成要素。

規格描述行為,而非程式碼

規格說明你的系統做什麼,以任何都能驗證的方式表述,而非說明系統是如何建置的。規格由需求(行為描述)與場景(證明需求成立的具體範例)構成。

markdown
### Requirement: Session Timeout
The system SHALL expire a session after 30 minutes of inactivity.

#### Scenario: Idle timeout
- GIVEN an authenticated session
- WHEN 30 minutes pass with no activity
- THEN the session is invalidated and the user must re-authenticate

實作細節(例如佇列、函式庫、資料表結構)請放在 design.md 或程式碼中。當行為與實作細節被混入同一條需求時,這條需求將無法被測試,且只要程式碼一變更,需求就會立刻過時。

優質需求的構成要素

優質的需求是單一行為的描述,表述得足够淺白,你可以直接交給其他人進行測試。

  • 單一語句、單個 SHALL/MUST。如果一條需求包含三個「同時也要」的條款,實際上它已經是三條需求,請將其拆分。

  • 可觀察。不熟悉程式碼的人也應該能判斷這條需求是否成立。「系統 SHALL 在上傳大小超過 10 MB 時顯示錯誤橫幅」是可觀察的;「系統 SHALL 優雅處理大型上傳」則不是。

  • 適當的強制程度。OpenSpec 使用 RFC 2119 的關鍵字,它們的含義各不相同:

    關鍵字含義
    MUST / SHALL強制要求,毫無協商空間。
    SHOULD強烈建議,但允許有正當理由的例外。
    MAY純屬可選。

    預設情況下優先使用 MUST/SHALL,只有當你確實想表達「除非有正當理由否則必須這麼做」時,才使用 SHOULD

驗證需求的標準是:從未看過程式碼的測試人員,能否判斷這條需求是否通過? 如果答案是否定的,這條需求就需要進一步明確。

優質場景的構成要素

場景是需求價值的體現。每個場景都是一個具體的 GIVEN / WHEN / THEN 結構,可以直接轉換為自動化測試。

  • 能驗證對應的需求。如果一個場景只是用不同措辭重述需求,那麼它什麼都測試不了。請讓場景成為帶有具體結果的特定情境。
  • 涵蓋重要的情境,而不只是順利流程。有效的登入很簡單,但空輸入、過期權杖、重複點擊、出錯的情況——這些才是 bug 藏身之處,也是場景價值最高的地方。
  • 在標題中明確說明情境。「場景:拒絕過期權杖」能讓審閱者一眼就知道涵蓋了什麼內容;而「場景:測試 2」則做不到。

一個實用的習慣:在批准之前,先問自己「如果哪個情境出問題我會最不開心?」——並確保有一個場景涵蓋了這個情境。

選擇正確的差異類型

變更透過三種區塊類型描述對規格的修改。使用正確的類型能確保歸檔的規格保持準確:

  • ## ADDED Requirements(已新增需求)——從未存在過的全新行為。
  • ## MODIFIED Requirements(已修改需求)——已存在但正在變更的行為。請包含完整的新版本;附上一句簡短說明變更內容,能幫助審閱者理解。
  • ## REMOVED Requirements(已移除需求)——即將廢棄的行為,並說明移除原因。

歸檔時,ADDED 的內容會附加到主規格中,MODIFIED 會取代舊版本,REMOVED 則會被刪除。如果把真正的變更標記為 ADDED,最終會出現兩條互相衝突的需求;如果把新行為描述為 MODIFIED,則沒有可取代的舊內容。如果不確定,請打開當前規格,確認該需求是否已經存在。

控制變更的規模

撰寫規格時最常見的錯誤,不是需求表述不佳,而是一個變更試圖包含三個變更的內容。

優質的變更只有一個意圖,可以用一句話說明。 例如:「新增深色模式切換開關」「為登入端點設定速率限制」「將會話從 Cookie 遷移出去」。如果描述變更時需要大量使用「同時也要」,這就是需要拆分的信號。

變更過大的跡象:

  • 提案的範圍看起來像是一系列無關的功能列表。
  • 審閱它需要整整一個下午,因此沒人會願意審閱。
  • 兩個人無法同時對它進行工作而不會產生衝突。
  • 一半的任務可以單獨上線。

較小的變更更容易審閱、更容易在一個專注的開發時段內完成,且六個月後當只剩下歸檔內容時,也更容易理解。你隨時可以並行執行多個變更——詳見編輯與迭代工作流程

相反的情況也會出現:修復一行拼寫錯誤不需要三條需求和一份設計文件。流程的複雜程度應與變更的影響程度相匹配。

如何引導 AI 產出優質草稿

由於 /opsx:propose 負責起草初稿,你得到的產出品質,取決於你輸入的內容品質。你不需要手動撰寫所有需求,只需要準確引導 AI 即可:

  • 說明意圖與邊界。 「新增深色模式切換開關,首次載入時跟隨作業系統設定——不要修改現有的主題 API。」 範圍外的說明與範圍內的說明同等重要。
  • 列出你關注的情境。 「確保有一個場景涵蓋手動選擇過主題的用戶。」 AI 只會覆蓋你指出的內容。
  • 接著編輯。 內容是純 Markdown 格式。你可以明確模糊的 SHALL 表述、刪除無意義的場景、新增它遺漏的情境——也可以直接要求 AI 這麼做:「逾時需求的表述太模糊,請將其明確為 30 分鐘。」

起草、優化、重複。經過幾輪這樣的循環,就能產出你信賴的規格,這就是整個流程的目的。

快速檢查清單

  • [ ] 每條需求都是單一可觀察的行為,且包含 SHALL/MUST 關鍵字。
  • [ ] 需求中沒有嵌入任何實作細節。
  • [ ] 每條需求至少有一個能實際驗證它的場景。
  • [ ] 重要的邊界與錯誤情境都有對應的場景,而不只是順利流程。
  • [ ] 差異區塊正確使用 ADDED / MODIFIED / REMOVED 對應當前規格的修改。
  • [ ] 整個變更只有一個意圖,可以用一句話說明。

延伸閱讀

  • 審閱變更 —— 兩分鐘快速檢查,找出遺漏的問題。
  • 概念 —— 規格、變更與差異背後的更深層模型。
  • 範例與實踐 —— 從頭到尾的真實變更案例。