🎯 什麼情境該想到我

當某塊功能「核心運作少不了它,但它本身不是你的競爭賣點」——例如報表、後台設定——你在猶豫該投多少資源、要不要外包時。

⚙️ 怎麼用(步驟 / 公式)

意圖:辨識出「支援核心但不構成差異化」的部分,給它剛好夠用的投入。

  1. 找出那些「核心需要、但市面上沒有現成方案能直接套」、又不是你獨門價值的子領域。
  2. 給它足夠但不過度的投入:能可靠支撐核心即可,不必追求最精緻的建模。
  3. 適合交給次要團隊、外包或用較低成本方式實作。
  4. 把省下的頂尖資源集中回核心子領域。

★★ 它是三種子領域裡最容易被做錯的一個(兩個方向都錯)

★★ 錯誤一:把它當核心做
  ★ 「訂單履約雖然不是我們的差異化,但也很重要,所以要好好設計」
  → ★ 引入聚合、值物件、資料對應器、事件溯源…
  → ★★ 結果:★ 一個沒有人真正在意的模組,複雜度和核心一樣高
     而核心那邊因為人力被吃掉而沒有深入

★★ 錯誤二:把它當通用做(去買)
  ★ 「這不是我們的優勢,用現成的 SaaS 吧」
  → ★★ 但它牽涉你的獨特業務規則 ⇒ ★ 現成的做不到,於是大量客製
  → ★★ 結果:付了訂閱費、還要維護一堆客製整合,比自己寫更貴

★★ 判準:它有沒有「你獨特的業務規則」?
有(但不是差異化)→ 支撐,自己做,但用最簡單的方式。
沒有(大家都一樣)→ 通用,去買(見 通用子領域)。

★★ 「用最簡單的方式做」具體是什麼

// ★ 支撐子領域的正確樣貌:交易指令稿 + sqlc,一個函式從頭讀到尾
package fulfilment
 
func (s *Service) Dispatch(ctx context.Context, cmd DispatchCommand) error {
    tx, err := s.db.BeginTx(ctx, nil)
    if err != nil { return fmt.Errorf("begin: %w", err) }
    defer tx.Rollback()
 
    o, err := s.q.WithTx(tx).GetOrderForUpdate(ctx, cmd.OrderID)   // ★ 直接用 row struct
    if err != nil { return err }
    if o.Status != "paid" { return ErrNotPayable }                   // ★ 規則直接寫在這裡
    …
    return tx.Commit()
}

★★ 刻意不做的事:

★ ❌ 不建聚合與聚合根           ❌ 不做資料對應器與 reconstitute
★ ❌ 不做儲存庫介面             ❌ 不引入領域事件(除非真的要通知別人)
★ ✅ 有測試(★ 關鍵路徑)       ✅ 有清楚的錯誤訊息
★ ✅ 有監控                      ✅ ★★ 有「之後可以升級」的空間

★ 最後一項是關鍵:★★ 支撐子領域可能變成核心(見 核心子領域),
所以不要寫成無法重構的樣子——★ 規則抽成純函式、交易邊界明確,就夠了。

★★ 它的技術債容忍度:高,但不是無限

★ 可以接受的:
  ★ 交易指令稿而非領域模型        ★ 覆蓋率 50% 而非 90%
  ★ 沒有完整的通用語言            ★ 直接用 row struct 而非領域型別
  ★ 某些邊界情況沒處理(★ 但要記在 ticket 裡)

★★ 不可以接受的(★ 這些和核心一樣嚴格):
  ★★ 資料正確性 —— ★ 支撐子領域算錯庫存,客戶一樣會生氣
  ★★ 安全 —— ★ 「這只是支撐」不是 SQL injection 的理由
  ★★ 可觀測性 —— ★ 出事時你要查得到
  ★★ 交易邊界與冪等 —— ★ 這些寫錯會造成資料損壞,而不只是「不夠優雅」

★★ 判準:這個偷懶會造成「不夠優雅」還是「資料錯了」?
不夠優雅 → 可以偷懶。
資料錯了/安全問題 → 不可以,不管它是什麼子領域。

★★ 外包/委外的真實判準

★ 支撐子領域是「可以外包」的候選,但三個前提:
① ★★ 介面必須由你定義(★ 你的通用語言,不是對方的)
   → ★ 否則對方的模型會滲透進你的核心(見 [[防腐層]])
② ★★ 你要能驗收
   → ★ 沒有測試、沒有明確的驗收條件 ⇒ ★★ 外包等於把問題延後
③ ★ 它的變動頻率低
   → ★★ 一個月改三次的東西外包,溝通成本高於自己寫

★★ 實務上「外包」更常見的形態是「用現成套件 + 薄封裝」,
★ 而那時第 ① 條變成:用 閘道 把對方的詞彙隔在外面。

★ 怎麼識別支撐子領域:三個問題

① ★ 「客戶會因為這一塊比對手好而選我們嗎?」→ 不會
② ★ 「市面上有現成的可以直接用嗎?」→ 沒有(有你獨特的規則)
③ ★ 「做不好會怎樣?」→ ★★ 會出事(所以不能不做)
→ ★ 三題的答案是「不會/沒有/會出事」⇒ 支撐子領域

🧪 我實際套用的紀錄

  • (待填)

⚠️ 注意 / 什麼時候不適用

  • 別在支撐子領域過度投入雕琢,那是核心才值得的待遇。

  • 但也不能忽視:它品質太差會拖累核心運作。

  • 若某天它變成競爭差異來源,就該重新分類為核心。

  • ★★ 兩個方向都會錯:當核心做(複雜度和核心一樣高,而核心沒人力深入)、當通用買(牽涉獨特規則 → 大量客製 → 比自己寫更貴)。

  • ★★ 判準:它有沒有「你獨特的業務規則」? 有(但不是差異化)→ 支撐,自己做但用最簡單的方式。

  • ★★ 技術債容忍度高,但四件事和核心一樣嚴格:資料正確性、安全、可觀測性、交易邊界與冪等。

  • ★★ 判準:這個偷懶會造成「不夠優雅」還是「資料錯了」? 後者不可以偷懶,不管什麼子領域。

  • ★ 支撐可能變成核心,所以不要寫成無法重構的樣子——規則抽成純函式、交易邊界明確就夠。

  • ★ 外包的三個前提:介面由你定義(你的語言)、你要能驗收、變動頻率低。

  • ★ 刻意不做的事要明確:不建聚合、不做儲存庫介面、不引入領域事件——但要有測試與監控。

  • 不要用「這只是支撐」當偷懶的許可。客戶不在乎你的子領域分類。

🔗 相關工具