2012-06-17 58 views
15

我想知道,在哪裏 - 以及如何頻率 - 在代碼驗證方法的參數。驗證方法參數的地方?

在下面的示例類(.dll庫)中,您認爲最好的方法是什麼?假設我想驗證一些對象不能是null(但它可以是方法正常運行所需的任何其他驗證)。在第一點檢查它是否更好,在用戶可用的公共方法中,稍後「相信自己」,在其他私人方法中,它不會爲空,或者最好是有點偏執,並且每隔一段時間檢查一次時間將被使用(在點2. 3.和4.)

在使用對象之前檢查它(在點2,3,4)在未來保護我,如果我決定改變某些東西該類,使用這些私有方法,並「忘記」傳遞有效的對象。如果我在將來添加一些新的公開方法,我也不必記住驗證。另一方面 - 它一遍一遍地檢查相同的情況。或者,也許你有其他建議?

public class MyClass() 
{ 
    public MyClass() 
    { 
    } 

    public void ProcessObject(SomeObject obj) 
    { 
     //1. if (obj == null) throw new ArgumentException("You must provide valid object."); 

     DoSomething(obj); 
     DoMore(obj); 
     DoSomethingElse(obj); 
    } 

    private void DoSomething(SomeObject obj) 
    { 
     //2. if (obj == null) throw new ArgumenException("You must provide valid object."); 
     //do something with obj... 
    } 

    private void DoMore(SomeObject obj) 
    { 
     //3. if (obj == null) throw new ArgumentException("You must provide valid object."); 
     //do something with obj... 
    } 

    private void DoSomethingElse(SomeObject obj) 
    { 
     //4. if (obj == null) throw new ArgumentException("You must provide valid object."); 
     //do something with obj.. 
    } 
} 

回答

12

如果這是一個您正在公開給其他開發人員使用的API,那麼在您的每種方法中,您確實應該拋出ArgumentExceptionArgumentNullException

如果是其他開發人員不會直接與之交互的內部類或方法,那麼我將使用Debug.Assert,因此在調試模式下,您將獲得更多調試信息,並且在發佈模式下它將被忽略,並且您會收到沒有到處進行所有這些論證檢查。

+1

+1''Debug.Assert' –

+0

您可能需要SuperAssert:http://msdn.microsoft.com/en-us/magazine/cc188701.aspx – zmbq

3

每個公共方法都應驗證其輸入。

私人方法可以依賴恕我直言,驗證其他公共方法在類中,如果你只是傳遞一個先前驗證的對象。由於私有方法被封裝在類中,所以驗證的責任在類中。但是,如果您有一個私有方法需要一些計算參數(不是傳遞給公共方法的參數),那麼應該實施額外的驗證。

您的單元測試將測試該類的公共接口,如果您的驗證僅在ProcessObject中,那麼它們將失敗,如果您的SomeObjectnull。在這種情況下,我不會在私有方法中重複驗證。

5

在一個好的軟件設計方法中需要彼此獨立。 您必須能夠以任意順序使用它們並將其彼此分開。所以是的,你必須一遍又一遍地檢查所有方法中的相同條件。

編輯: 我會使用CodeContract與檢查obj不爲空的前提條件。因爲這似乎是方法正常工作的先決條件。

+0

這也是我的想法,但它似乎與其他答案相反......讓我們等待其他意見。 – mj82