Theme / v1.2.3

Matt Pocock's Engineering Skills

可組合的 AI 工程工作流技能庫

實戰範例

實戰範例 008:用 /domain-modeling 解開「訂閱」與「會員」的詞彙衝突

團隊把同一個詞用在不同概念上,用邊界情境壓力測試並寫進 CONTEXT.md 與 ADR。

情境背景

產品經理說「我們要加訂閱功能」,工程師聽成「定期扣款的方案」,行銷聽成「電子報訂閱」。三個人會議中點頭,會後各自做不同的事。這是典型 ubiquitous language(共享語言)破洞,不處理的話需求、程式碼、文件會互相矛盾。

/domain-modeling 用來主動建立並磨利專案的領域模型。它不是把對話詞彙倒進詞彙表就了事,而是會挑戰術語、用邊界情境壓力測試、即時更新 CONTEXT.md 與 ADR。


第 1 步:讀取現有模型

目標:先看 repo 目前記錄了什麼

/domain-modeling 第一個動作是讀取既有的 CONTEXT.md(或多情境的 CONTEXT-MAP.md)與 docs/adr/。如果 repo 是空的,這也是預期狀態,不是問題。這些檔案是延遲建立的,只在 term 或決策真的被解決時才寫。

AI 對話

  • You:

    /domain-modeling
    我們要加訂閱功能,使用者可以訂閱方案。
  • AI:

    我讀過你的 CONTEXT.mddocs/adr/。目前詞彙表有「會員」「方案」,沒有「訂閱」。

    「訂閱」這個詞還沒定義。我先挑戰它:

    • 「訂閱」是指一次性購買方案,還是定期續約?
    • 如果定期續約,與現有「會員」差在哪?會員也是定期的。
    • 一個使用者可以同時有多個訂閱嗎?

第 2 步:挑戰 term

目標:讓模糊詞被檢驗

/domain-modeling 對每個新出現的 term 都會對照詞彙表檢驗。它要回答三個問題:這個 term 清晰嗎?它與既有 term 矛盾嗎?它還沒被命名嗎?

AI 對話

  • You:

    會員是免費的、訂閱是付費的。

  • AI:

    這是個關鍵區分。我壓力測試一下:如果某個方案首月免費、之後付費,它在首月算會員還是訂閱?

    還有,行銷說的「電子報訂閱」也是「訂閱」嗎?如果是,那「訂閱」這個詞同時指付費方案關係與電子報收信,這是兩個不同的概念擠在同一個名字下。

  • You:

    你說得對。電子報那個應該叫「關注」或「訂閱電子報」,不是「訂閱」。


第 3 步:用邊界情境壓力測試

目標:確認定義站得住

寫進 CONTEXT.md 之前,term 要先通過邊界情境考驗。/domain-modeling 會主動設計邊界,例如:

  • 首月免費的方案,在首月算會員還是訂閱?
  • 使用者取消付費訂閱後,會員關係還在嗎?
  • 付費訂閱退款後,已存取的內容要不要回收?

這些情境不是 nitpick。它們是定義能不能用的考驗。

AI 對話

  • AI:

    建議的定義:

    • 會員:免費、定期續約的關係。
    • 訂閱:付費、定期續約的方案關係。
    • 電子報訂閱:免費、可隨時取消的收信同意,與訂閱不同概念。
    • 邊界按是否付費畫分。

    同意嗎?同意我就寫進 CONTEXT.md

  • You:

    同意。首月免費的方案在首月算會員、之後轉訂閱。


第 4 步:resolve 並寫入檔案

目標:把共識固化成可追溯的檔案

/domain-modeling 會在 term 真的被解決時才寫入。一個空白 repo 保持空白是預期狀態,不是 bug。

AI 對話

  • AI:

    已寫入 CONTEXT.md

    ## 會員(Member)
    免費、定期續約的使用者關係。每個使用者最多一個會員關係。
    
    ## 訂閱(Subscription)
    付費、定期續約的方案關係。一個使用者同時最多一個有效訂閱。
    
    ## 電子報訂閱(Newsletter Opt-in)
    免費的收信同意,與訂閱不同概念。可獨立存在。

    同時建議寫 ADR-0007 記錄「會員與訂閱邊界以是否付費畫分」這個決策。要我寫嗎?

  • You:

    寫。

  • AI:

    已建立 docs/adr/0007-member-vs-subscription.md,記錄決策、理由、與首月免費方案的邊界處理。


第 5 步:偵測 ADR 衝突

目標:理解為什麼要回頭讀 ADR

/domain-modeling 在寫新 ADR 前會掃既有 ADR。如果發現衝突會明確標出,例如:

等等,docs/adr/0003-order-storage.md 記錄了你們用 PostgreSQL 存訂單的決策。你現在要把訂單事件流存到 MongoDB,這是 ADR 衝突。兩個選項:推翻舊 ADR 寫 ADR-0004 supersede 它;或這是個新 term「訂單事件流」與「訂單」本體不同,需要分開定義。是哪一個?

這個步驟的存在理由是避免 ADR 之間或 term 之間互相打架。


第 6 步:作為其他 skill 的子步驟

目標:知道 /domain-modeling 不只獨立使用

/grill-with-docs/improve-codebase-architecture 內部會呼叫 /domain-modeling。意思是你在做共享語言訪談或架構深化時,term 挑戰與邊界測試會自動跑,不必你記得。

它與 /codebase-design 互補:前者管領域詞彙,後者管模組介面設計。


何時不應該用 /domain-modeling

還沒有任何對話或 context

這是延遲建立的,先有東西討論才建模。空詞彙表是預期狀態,不是問題。

純技術決策、與領域無關

直接寫 ADR,不必建模 term。例如「要不要用 Redis 做快取」是技術選型,不是領域詞彙。

對方還沒準備好定義

逼問會變成 /grilling,先讓討論發酵。/domain-modeling 是共識驅動,不是逼問工具。


工具使用摘要

Skill 用途 在本例的作用
domain-modeling 詞彙挑戰與壓力測試 解開訂閱、會員、電子報訂閱的衝突
grill-with-docs 共享語言訪談 內部會呼叫 domain-modeling
improve-codebase-architecture 架構深化 內部會呼叫 domain-modeling
codebase-design 模組介面設計 與 domain-modeling 互補

結果

  • CONTEXT.md 寫下 3 個不衝突的 term 定義,每個都通過邊界情境考驗
  • 寫 ADR-0007 記錄「會員與訂閱以是否付費畫分」這個不可逆決策
  • 之後對話、程式碼、文件都用同一份詞彙,省下每次會議重新解釋的成本

關鍵學習點

  • /domain-modeling 會挑戰 term 並用邊界情境壓力測試,不是把對話詞彙倒進詞彙表就了事。
  • CONTEXT.md 與 ADR 是延遲建立的,只在 term 或決策真的被解決時才寫。空白 repo 是預期狀態。
  • 寫新 ADR 前會掃既有 ADR 偵測衝突,避免決策之間互相打架。
  • /codebase-design 互補:domain-modeling 管領域詞彙,codebase-design 管模組介面。