穿透型變數(pass-through variable):被一連串方法層層往下傳的變數。
範例#
某資料中心服務:
- 命令列參數描述了用於安全通訊的憑證(cert)
- 只有最底層的
m3真正用到(呼叫函式庫開 socket) - 但 cert 出現在
main → m1 → m2 → m3路徑上每個方法的簽章中

Figure 7.2: 處理穿透變數的四種做法——(a) 層層傳遞;(b) 存進共享物件;(c) 全域變數;(d) 集中於 context 物件
為什麼這樣有害#
- 強迫所有中間方法都「意識到」這個變數的存在,即便它們根本沒用到
- 一旦有新變數要加(例如系統初版沒有憑證,後來才加) → 必須修改大量介面與方法
消除穿透型變數的策略#
方法 1:找已經共享的物件#
如果上下層之間已經有共享物件(例如都能存取的某個與網路通訊相關的物件),就把資訊放進該物件,不用層層傳遞。
但這個物件本身可能就是個穿透變數——否則
m3怎麼存取它?
方法 2:全域變數#
把資訊存成全域變數。但全域變數幾乎總是製造其他問題:
- 不能在同一個 process 中建立兩個獨立實例(全域變數會打架)
- 看似正式環境用不到雙實例,測試時卻很常用
方法 3:context 物件(推薦)#
作者最常用的解法:引入 context 物件。
- 把所有原本可能成為穿透變數或全域變數的應用全域狀態,全部存進 context
- 多數應用本來就有多個全域狀態(設定選項、共享子系統、效能計數器等)
- 每個系統實例擁有一個自己的 context → 多實例可在同一 process 共存
怎麼讓 context 不變成另一個穿透變數#
- 在系統的多數主要物件中,儲存對 context 的參考作為 instance 變數
- 建立新物件時,由建立方法把自己的 context 參考傳入子物件的建構式
- 這樣 context 就到處可用,但只在建構式中以明確參數出現
context 的好處#
- 統一處理系統全域資訊
- 新增變數只要動 context 的建構 / 解構
- 全域狀態集中管理
- 方便測試:測試碼可改 context 內欄位來改設定(用穿透變數很難做到這點)
context 的限制與注意事項#
context 不是理想解。
- 仍具備全域變數的多數缺點:「為什麼有這個變數?」、「它在哪裡被用?」可能不顯而易見
- 若沒有紀律,context 會膨脹成大雜燴,造成系統各處不顯而易見的依賴
- 可能造成執行緒安全問題;最好的避險方式是讓 context 中的變數不可變(immutable)
但作者目前還沒找到比 context 更好的解法。