🎯 什麼情境該想到我
當你「想換掉某個方法內部自己建立出來的那個物件,好做感知或分離」的時候。
⚙️ 怎麼用(步驟)
書的設定:假設你有一個方法,該方法在內部建立了某個物件,而你想要透過替換該物件來實現感知或分離。往往最簡單的辦法就是從外面將你的物件傳進來(p.301)。
書中另外點出一個保命技巧:借助於一點函式轉發技巧,我們就可以完全保留原來的那個函式簽名——把原來那個無參數的版本改成只做一件事,即建立一個物件並呼叫參數化之後的版本(p.301)。
書中列的步驟(p.302):
- 找出目標方法,將它複製一份。
- 給其中一份增加一個參數,並將方法體中相應的物件建立語句去掉,改為使用剛增加的這個參數。
- 將另一份複製的方法體刪掉,代以對被參數化了的那個版本的呼叫,記得建立相應的物件作參數。
命名的取捨(p.301):C++、Java、C# 以及許多其他語言都允許同一個類別上有多個同名方法,前提是它們的簽名各不相同。書中的例子就利用了這個便利,使原方法和參數化之後的方法具有同樣的名字。「儘管這省了點事,但有時也會帶來混亂。一個替代方案是將新參數的型別名嵌入方法名中」——例如原方法名保留不變,把加了參數的那個版本改叫「帶某型別參數的某方法」。
🧪 我實際套用的紀錄
- (待填)
⚠️ 注意 / 什麼時候不適用
- 會擴散型別依賴,且書給了替代方案:「與參數化建構函式手法一樣,參數化方法也可能會導致客戶程式碼依賴於新出現的那個參數的型別。如果你覺得這的確會帶來問題的話,可以考慮改用提取並重寫工廠方法」(p.302)。
- 同名多載可能造成混亂:見上「命名的取捨」——省事與可讀性之間要自己選(p.301)。
- 與《重構》的分界:外觀上很像《重構》的「加入參數/改變函式宣告」,但動機完全不同:這裡不是為了讓介面更好,而是為了在測試中把物件從外面換進去,好進行感知或分離。書甚至教你用轉發技巧把原簽名原封不動保留下來——正因為目的只是開一道測試用的門,不是改設計。
🔗 相關工具
- 工具-打破依賴以便測試 — 這條技術屬於的大類
- 參數化建構函式 — 姊妹技術,同一招套用在建構函式上,書中兩者共用同一個型別依賴的警告
- 提取並重寫工廠方法 — 書指定的替代方案:當「客戶程式碼依賴新參數型別」真的造成問題時改用它(p.302)
- 樸素化參數 — 當連傳物件進去都做不到(類別本身無法納入測試)時的更極端手段
- 回連 修改程式碼的藝術