2009-11-10 57 views
1

我正在修改一些遺留代碼。我有一個對象,它有一個方法,讓我們說doSomething()。當特定的斷言失敗時,此方法會引發異常。但是由於新的要求,在某些情況下,不拋出異常並繼續使用該方法是可以的。我在這裏使用全局狀態,有沒有更好的方法來做到這一點?

現在我不是直接從我需要忽略異常的地方調用此方法。這個doSomething()就像是一個審計方法,可以通過很多其他方法在內部調用,例如method1(),method2()等。

在我需要忽略異常的地方,我調用method1 ),現在我不想讓method1()拋出異常。所以我修改了method1()以接受默認參數method1(ignoreException = false)並調用method1(true)。

我還修改了doSomething()來接受額外的參數,而method1只是將ignoreException傳回給doSomething(ignoreException)。

潛在地,我需要改變所有的方法,方法2,方法3等以及採取這個額外的參數。

在看到這段代碼時,有人建議不要傳遞此標誌,而是可以將它作爲類的成員變量,然後在調用method1()之前調用setter。可以說我的對象是obj,那麼我應該做 obj.setIgnoreXXXException(true); obj.method1(); obj.setIgnoreXXXException(false);

在我看來,這似乎保持了一些全球性的狀態,看起來並不錯。但傳遞論據的另一種方式似乎也很笨拙,我必須改變很多地方(這個類有子類,有些方法是虛擬的,所以我需要隨處修改)

有沒有更好的方法來做這個。既然它是遺留的,並且沒有單元測試,我不想修改很多現有的代碼。

回答

4

你當然應該用函數參數來做這件事,而不是成員 - 是否忽略檢查的選擇是函數調用的屬性,而不是對象的屬性。

使用持久狀態保持一種臨時狀態會給你兩個主要問題:

  • 異常安全 - 如果函數拋出未處理的異常,那麼你的代碼將離開「忽略」標誌設置。
  • 重入 - 調用函數遞歸,或從多個線程,可能會有意想不到的效果

你可以把它異常安全使用析構函數重置標誌:

class IgnoreException 
{ 
public: 
    explicit IgnoreException(Object &o) : object(o) 
    { 
     object.setIgnoreException(true); 
    } 
    ~IgnoreException() 
    { 
     object.setIgnoreException(false); 
    } 
private: 
    Object &object; 
}; 

void callMethodOneIgnoringException(Object &object) 
{ 
    IgnoreException ignore(object); 
    object.method1(); 

    // the flag is restored here, even if an exception was thrown. 
} 

你可以用」讓它重新折入。任何訪問持久化狀態的函數都是不可重入的,所以唯一的解決方法是使用函數參數。

+0

感謝您在此解釋警告,我將使用函數參數 – Arvind 2009-11-11 06:33:03

0

在類上指定一個靜態布爾變量,並在該類上指定一個靜態成員,該成員允許您將布爾值設置爲您選擇的任何值;您可以使用該靜態布爾值來抑制拋出異常,並且可以從您的代碼中設置它,而無需修改任何現有接口。

0

你可以去創建某種包裝(類或函數閉包)的路線。然後,你可以定義一個變量,它是你已經得到的類的一個使用。它會包裝類的使用,所以你可以避免一些管理步驟。

var wrapper = yourClass.WrapWithThrowOption(true); 
wrapper.method(); 

var wrapper = wrapWithOption(true, method1); 
wrapper(); 

您沒有說明您正在使用的語言,所以我只是用一些僞語法。

+0

語言是C++ – Arvind 2009-11-10 17:49:58

+0

如果您發佈了一些相關的代碼(或者類似的例子),我們可能可以編寫代碼來說明這個想法。 – 2009-11-10 18:31:52

1

我還建議使用函數參數而不是類變量。

method1(true); 
// true means do throw an exception? 
// do supress an exception? 

enum ExceptionSuppressionType 
{ 
    SUPPRESS_NO_EXCEPTIONS, 
    SUPPRESS_ALL_EXCEPTIONS 
}; 
method1(SUPPRESS_ALL_EXCEPTIONS); 
// I'm pretty sure this will suppress the exceptions. 

這也爲您提供了更多的自由,將來如果你決定要一些變化......也許只有抑制一些例外:

不過,我一般用枚舉,而不是一個布爾值推薦,或者以新形式重新推出它們等。布爾表現非常出色,它只能提供兩種選擇,但返回值和參數的範圍通常會隨着時間的推移而增長。

相關問題