🎯 什麼情境該想到我
當某塊功能「核心運作少不了它,但它本身不是你的競爭賣點」——例如報表、後台設定——你在猶豫該投多少資源、要不要外包時。
⚙️ 怎麼用(步驟 / 公式)
意圖:辨識出「支援核心但不構成差異化」的部分,給它剛好夠用的投入。
- 找出那些「核心需要、但市面上沒有現成方案能直接套」、又不是你獨門價值的子領域。
- 給它足夠但不過度的投入:能可靠支撐核心即可,不必追求最精緻的建模。
- 適合交給次要團隊、外包或用較低成本方式實作。
- 把省下的頂尖資源集中回核心子領域。
★★ 它是三種子領域裡最容易被做錯的一個(兩個方向都錯)
★★ 錯誤一:把它當核心做
★ 「訂單履約雖然不是我們的差異化,但也很重要,所以要好好設計」
→ ★ 引入聚合、值物件、資料對應器、事件溯源…
→ ★★ 結果:★ 一個沒有人真正在意的模組,複雜度和核心一樣高
而核心那邊因為人力被吃掉而沒有深入
★★ 錯誤二:把它當通用做(去買)
★ 「這不是我們的優勢,用現成的 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 的理由
★★ 可觀測性 —— ★ 出事時你要查得到
★★ 交易邊界與冪等 —— ★ 這些寫錯會造成資料損壞,而不只是「不夠優雅」
★★ 判準:這個偷懶會造成「不夠優雅」還是「資料錯了」?
不夠優雅 → 可以偷懶。
資料錯了/安全問題 → 不可以,不管它是什麼子領域。
★★ 外包/委外的真實判準
★ 支撐子領域是「可以外包」的候選,但三個前提:
① ★★ 介面必須由你定義(★ 你的通用語言,不是對方的)
→ ★ 否則對方的模型會滲透進你的核心(見 [[防腐層]])
② ★★ 你要能驗收
→ ★ 沒有測試、沒有明確的驗收條件 ⇒ ★★ 外包等於把問題延後
③ ★ 它的變動頻率低
→ ★★ 一個月改三次的東西外包,溝通成本高於自己寫
★★ 實務上「外包」更常見的形態是「用現成套件 + 薄封裝」,
★ 而那時第 ① 條變成:用 閘道 把對方的詞彙隔在外面。
★ 怎麼識別支撐子領域:三個問題
① ★ 「客戶會因為這一塊比對手好而選我們嗎?」→ 不會
② ★ 「市面上有現成的可以直接用嗎?」→ 沒有(有你獨特的規則)
③ ★ 「做不好會怎樣?」→ ★★ 會出事(所以不能不做)
→ ★ 三題的答案是「不會/沒有/會出事」⇒ 支撐子領域
🧪 我實際套用的紀錄
- (待填)
⚠️ 注意 / 什麼時候不適用
-
別在支撐子領域過度投入雕琢,那是核心才值得的待遇。
-
但也不能忽視:它品質太差會拖累核心運作。
-
若某天它變成競爭差異來源,就該重新分類為核心。
-
★★ 兩個方向都會錯:當核心做(複雜度和核心一樣高,而核心沒人力深入)、當通用買(牽涉獨特規則 → 大量客製 → 比自己寫更貴)。
-
★★ 判準:它有沒有「你獨特的業務規則」? 有(但不是差異化)→ 支撐,自己做但用最簡單的方式。
-
★★ 技術債容忍度高,但四件事和核心一樣嚴格:資料正確性、安全、可觀測性、交易邊界與冪等。
-
★★ 判準:這個偷懶會造成「不夠優雅」還是「資料錯了」? 後者不可以偷懶,不管什麼子領域。
-
★ 支撐可能變成核心,所以不要寫成無法重構的樣子——規則抽成純函式、交易邊界明確就夠。
-
★ 外包的三個前提:介面由你定義(你的語言)、你要能驗收、變動頻率低。
-
★ 刻意不做的事要明確:不建聚合、不做儲存庫介面、不引入領域事件——但要有測試與監控。
-
不要用「這只是支撐」當偷懶的許可。客戶不在乎你的子領域分類。