修正未知錯誤是否為重構

2004 年 9 月 3 日

Przemyslaw Pokrywka 提出了一個有趣的難題。在 書中 的重構之一是 引入 Null 物件,這是一個非常有用的重構(也在 Josh 的新書 中討論過)。Przemyslaw 的觀點是,此重構可能會改變行為。如果您有一個方法傳回 null,而您呼叫該 null 上的方法,您將會得到一個 Null 指標例外。如果您使用 Null 物件,您將會得到一些預設行為。

現在,許多重構確實會改變行為,它們的確是這樣設計的。如果您套用 建立範本方法,則程式會以不同的方式運作。關鍵問題是我在 DefinitionOfRefactoring 中所稱的可觀察行為是否如此。也就是說,它是否改變了程式本質上執行的動作?使用「引入 Null 物件」時,您必須在程式中尋找處理傳回參考的地方,通常是透過檢查它是否為 null。這使得這成為一個相當棘手的重構。

這個難題的有趣之處在於,如果您錯過一個有錯誤的區域會發生什麼事。在您的程式中某個地方,您呼叫一個 null 參考上的方法。在重構之前,您會得到一個例外,我們在此假設這是您不知道的例外,而且會一路傳遞到某個頂層處理常式。在重構之後,您會得到預設行為,這實際上可能會修正錯誤。如果您修正了一個您不知道的錯誤,這是否仍然是重構?

我會主張是,因為您不知道或不關心(足夠)有錯誤的行為,所以我會說該行為不可觀察。即使您知道這個錯誤,我仍然會主張,如果該錯誤不是您關心要保留的行為,那麼稱之為重構是可以的。

這是一個有趣的案例,我很容易想像自己改變主意或探索更多邊緣案例。

它指出的有趣事項之一是手動和工具驅動重構之間的差異。使用手動重構,您可以進行這樣的判斷呼叫,工具通常必須小心得多。然而,即使是工具也無法總是保證保留行為 - 即使是重新命名方法,如果該方法是由反射呼叫的,並且名稱是由檔案中讀取的,那麼在重構時也可能會中斷。