🎯 什麼情境該想到我

當你「要改一個方法,卻卡在它的參數型別上——那個參數難以建立、難以偽裝,或根本是你改不動的標準介面」的時候。

⚙️ 怎麼用(步驟)

先判斷該不該用(p.258–259)

  • 在對方法作改動時常常會遇到一些令人頭疼的依賴,這些依賴由方法的參數導致:有時會發現難以建立所需的參數,有時是需要測試某方法對其某個參數的影響。書中說「許多時候我發現參數的型別正是帶來麻煩的根源」。
  • 如果該類別是我可以修改的,則優先用 介面提取(285頁):「在參數依賴問題上,介面提取(285頁)往往是不二之選。」
  • 但若「參數型別的抽象層次較低,或特定於某些實現技術的話,提取其介面就有可能達不到預期效果甚至根本就不可行」。
  • 因此:「當無法對一個參數的型別使用介面提取,或者當該參數難以『偽裝』的時候,可採用參數適配手法。」

核心做法:把參數型別外覆起來,改讓方法依賴一個自己定義的窄介面,「從而完全解除對 API 介面的依賴」(p.259)。書中的判準是:「介面應傳達職責而非實現細節。這樣的介面令程式碼易於閱讀和維護。」(p.260)

步驟(p.261)

  1. 建立將被用於該方法的新介面,該介面越簡單且能表達意圖越好。但也要注意,該介面不應導致需要對該方法的程式碼作大規模修改。
  2. 為新介面建立一個用於產品程式碼的實作。
  3. 為新介面建立一個用於測試的「偽造」實作。
  4. 編寫一個簡單的測試案例,將偽物件傳給該方法。
  5. 對該方法作必要的修改以使其能使用新的參數。
  6. 執行測試來確保你能使用偽物件來測試該方法。

🧪 我實際套用的紀錄

  • (待填)

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

  • 它違反簽名保持:「參數適配是一個違反簽名保持(249頁)的例子。因此,用的時候請格外小心。」(p.260)
  • 簡化過頭會出 bug:「有些時候參數適配手法也可能會帶來危險,比如你建立的簡化介面與原來參數的介面型別相差太遠。如果我們在修改的時候不小心,就可能會引入微小的 bug。」(p.261)
  • 不要追求最好的結構,要追求最有把握的改動:「記住我們是為了將測試安置到位而解開依賴。所以應該去做那些你更有信心的修改,而不是能導致最佳程式碼結構的修改。一旦測試到位,一切都好辦了,那時你自然會得到最佳程式碼結構。」(p.261)書中舉例:之後或許才想把介面改成不用檢查回傳 null(空對象模式,94頁)。
  • 安全第一:「一旦測試到位,你便可以更有信心地進行侵入性的改動了。」(p.261)
  • 整章共通的誠實取捨:「這些技術並不能立竿見影地讓設計變得更好。實際上,如果你有良好的設計感,這裡的某些技術甚至可能會令你退縮。」(p.258)
  • 與《重構》的差別:書中特別註明,本章的一些手法在 Martin Fowler 的《重構》中也有描述,「只是本章對它們的描述在步驟上有所不同,我將之適當剪裁以使得它們能夠被安全地用在沒有測試的情況下」(p.258)。所以名字接近的重構手法(如 引入參數物件改變函式宣告)目的不同:那些是在測試保護下改善結構,這裡是為了先寫得出測試而打破依賴。

🔗 相關工具