🎯 什麼情境該想到我

當某塊需求「大家做的都差不多、市面上早有成熟方案」——例如身分認證、通知寄送、金流、地圖——你在考慮要不要自己從頭刻時。

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

意圖:辨識出通用、沒有差異化價值的部分,優先用現成方案而非自建。

  1. 找出「不是你的競爭優勢、且已有成熟套件/服務」的子領域。
  2. 優先買、用現成套件或外部服務,而不是投人力自建。
  3. 若必須自建,也用最省力、最標準的方式,別過度雕琢。
  4. 把節省下來的資源集中投入核心子領域。

★★ 唯一的規則:不要自己寫

★ 通用子領域的清單(大多數系統都有):
  ★ 身分驗證與授權        ★ 寄信/推播/簡訊
  ★ 檔案儲存              ★ 金流
  ★ 排程與延遲任務        ★ 日誌與監控
  ★ 搜尋                  ★ feature flag
  ★ 匯率/稅率/地址正規化 ★ PDF 產生
→ ★★ 每一項都有比你做得好的現成方案,而且它們不會讓你多賣一塊錢

★★ 「自己寫」的隱性成本是持續的,而它總是被低估:
★ 不只是初版的兩週,還有十年的安全修補、邊界情況、新平台支援、
以及「唯一懂它的人離職」
。

★★ 自己寫身分驗證:一個具體的成本清單

★ 你以為要做的:登入、登出、密碼雜湊
★★ 你實際要做的:
  ★ 密碼雜湊(★ argon2id 的參數怎麼選?★ 要不要 pepper?)
  ★ 憑證填充攻擊(credential stuffing)防護
  ★ 暴力破解的速率限制(★ 按 IP?按帳號?★ 兩者都要)
  ★ 密碼重設流程(★ token 過期、單次使用、★★ 時序攻擊)
  ★ MFA(TOTP 的時間漂移、備用碼、★ 裝置記憶)
  ★ SSO/OIDC(★ 而這是一個完整的規格)
  ★ session 管理與撤銷(見 [[伺服器會話狀態]])
  ★ 帳號枚舉防護(★★ 「這個 email 不存在」洩漏了資訊)
  ★★ 以及每一項的安全更新
→ ★ 這是一個團隊的常態工作,★★ 而它不會讓你多賣一塊錢

★★ 判準:這一塊「做錯了會上新聞」嗎? 會(身分、金流、個資)→ 絕對不要自己寫。

★★ 但「買」也有一套紀律:三件必做的事

// ① ★★ 用 [[閘道]] 把對方的詞彙隔在外面
package mail
type Sender interface {                    // ★ 你的詞彙
    Send(ctx context.Context, m Message) error
}
// ★ 實作裡才有 sendgrid.Mail、對方的錯誤碼、對方的重試慣例
// → ★★ 換供應商只改一個檔案(見 [[閘道]] 的「必須翻譯的四件事」)
 
// ② ★★ 不要讓對方的型別出現在你的領域層
// ★ grep -rn "sendgrid" internal/domain/  → ★★ 應該是空的
 
// ③ ★ 要能在測試裡替換
// → ★ 介面定義在消費方(見 [[分離介面]]),fake 只有十行(見 [[服務樁]])

★★ 最容易違反的是 ②:
「先直接用對方的 SDK,之後再包」→ ★ 而「之後」不會來,
於是 sendgrid.Mail 出現在三十個檔案裡。
→ ★ 對策:第一次引入時就包,那時只有一個呼叫點,成本最低。

★★ 什麼時候「自己寫」是對的(很窄,但存在)

① ★★ 現成方案的成本結構不合
   ★ 一個按 MAU 計費的服務,而你有一千萬個低活躍使用者
   → ★ 這是一個財務決定,要算清楚而不是猜

② ★★ 合規/資料主權要求
   ★ 資料不能離境、不能給第三方
   → ★ 但注意:★★ 通常有「地端部署版」的現成方案,仍然不用自己寫

③ ★ 它其實已經變成你的核心
   ★ 你做的就是一個排程平台 → ★★ 那排程不是通用子領域,是核心

④ ★ 極簡的需求
   ★ 「寄一封固定格式的通知信」→ ★ 直接用 SMTP 三十行,不需要一個服務
   → ★★ 但要誠實:★ 一旦需要模板、退信處理、送達率追蹤,就該換

★★ 注意 ④ 的陷阱:★ 「極簡的需求」會長大,
而「三十行的自製方案」長成三千行的時候,沒有人會停下來說「我們應該去買」。
→ ★ 對策:引入時就在 ticket 裡寫下「什麼條件下改用現成方案」。

★★ 選型時的三個實務問題(比功能清單重要)

① ★★ 逃生門有多寬?
   ★ 資料能匯出嗎?★ 格式是開放的嗎?★★ 換掉要多久?
   → ★ 這決定了「選錯」的代價

② ★★ 它掛了你會怎樣?
   ★ 寄信服務掛了 → 使用者註冊不了?還是「稍後再寄」?
   → ★ 這決定了你需要多少降級設計(見 [[工具-服務容錯設計]])

③ ★ 它的變更節奏你跟得上嗎?
   ★★ 一個一年 breaking change 兩次的 SDK,比你自己寫更花時間

★ 兄弟辨析

差別
核心子領域★ 差異化來源,自己做,投入最多
支撐子領域★ 有你獨特的規則但不是差異化,自己做但最簡單
閘道★ 通用子領域的正確封裝方式
防腐層★ 更大範圍的隔離(含模型轉換)

🧪 我實際套用的紀錄

  • (待填)

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

  • 別把通用子領域當核心來精雕,那是資源錯配。

  • 若你的商業價值恰恰來自「把某個通用領域做得比別人好」,那它對你其實是核心,不能只買現成。

  • 選現成方案時仍要注意整合成本與供應商鎖定風險。

  • ★★ 判準:這一塊「做錯了會上新聞」嗎? 會(身分、金流、個資)→ 絕對不要自己寫。

  • ★★ 自己寫身分驗證的實際清單有十幾項(憑證填充、速率限制、時序攻擊、帳號枚舉、MFA、OIDC…),而且它不會讓你多賣一塊錢。

  • ★★ 「先直接用 SDK,之後再包」—— 而「之後」不會來。 第一次引入時就包,那時只有一個呼叫點。

  • ★★ grep -rn "<供應商>" internal/domain/ 應該是空的。 對方的型別不可出現在領域層。

  • ★ 「極簡需求」會長大,而三十行長成三千行時沒有人會停下來說「應該去買」。 引入時就在 ticket 裡寫下「什麼條件下改用現成方案」。

  • ★ 選型時的三個實務問題比功能清單重要:逃生門多寬、它掛了你會怎樣、變更節奏你跟得上嗎。

  • ★ 合規要求通常有「地端部署版」的現成方案,仍然不用自己寫。

  • ★ 按 MAU 計費不合的情況是財務決定,要算清楚而不是猜。

🔗 相關工具