共用能力 context 會隨副作用種類膨脹

主張:當你用「一個共用的能力 context(capability ctx)」注入副作用給多個 handler,這個 ctx 會隨副作用種類線性膨脹——因為它是所有 handler 能力的聯集,而分派者又必須把每一項都備齊。這是 註冊表分派 side effect(Registry + Strategy Handler) 的最大取捨。

膨脹怎麼發生

一開始只有 2 個能力,介面與 dispatcher 都還小:

interface ClosedJobHandlerContext {
  showTransportationSegmentsToast: (runId: string) => void;
  showBulkCreatedActivityDataToast: (count: number) => void;
}

每多一種副作用(打 API、送 analytics、下載報表…),介面和 dispatcher 同時各長一條

interface ClosedJobHandlerContext {
  showTransportationSegmentsToast: (runId: string) => void;
  showBulkCreatedActivityDataToast: (count: number) => void;
  callXxxApi: (runId: string) => void;    // ← 新
  sendAnalytics: (e: Event) => void;      // ← 新
  downloadReport: (id: string) => void;   // ← 新
}
// dispatcher 也要多叫一個 provider hook、再塞進同一個 ctx

為什麼是壞味道

  1. 胖介面,違反 ISP(介面隔離):transportation handler 用不到 downloadReport,卻因共用同一個 ctx 型別而看得到、拿得到每一項。介面 = 所有人能力的聯集,每個 handler 被迫依賴無關的東西。
  2. rules of hooks 逼你無條件全叫:不能只在「剛好有這種 job」時才 useXxxApi()——hook 不能寫在 if 裡。所以就算這輪一個 job 都沒有,dispatcher 還是把每個 provider hook 全叫一次、全塞進 ctx。
  3. dispatcher 變回中央耦合點:ctx 的組裝在 dispatcher 裡,能力越多它 import/認得的 presenter/API 就越多——當初想解耦的細節,在「組 ctx」這一步又黏回來。

判斷準則

「一個共用注入容器 + 分派者全權備齊」在能力少時很優雅;一旦副作用種類會持續增加,共用 ctx 就從優點變負債。此時該把「拿依賴」的責任還給每個反應自己 → 用 reaction hook 讓副作用各自帶依賴