2012-02-13 14 views
2

以下是接口合同摘錄。當引用另一個合約方法時應該重複條件嗎?

我的問題是:前一種方法應該重複後一種方法的前提條件嗎?由於合同是公開的,忽略重複是否可以接受?在這種情況下,它只是一個非空的檢查,但我可以想象出這樣的情況,即重複了很多代碼,並且在運行時重複進行相同的檢查時性能會受到影響。

public int CommandConsumerCount(IWriteCommand writeCommand) 
{ 
    Contract.Requires(writeCommand != null); // redundant? 
    Contract.Requires(this.IsOwnerOf(writeCommand)); 

    Contract.Ensures(Contract.Result<int>() >= 0); 

    return default(int); 
} 

public bool IsOwnerOf(IWriteCommand writeCommand) 
{ 
    Contract.Requires(writeCommand != null); 

    return default(bool); 
} 

回答

2

這種依賴於條件(writeCommand != null在這種情況下)是否是用於兩個CommandConsumerCount方法以及該方法IsOwnerOf要求,或者如果它是隻爲IsOwnerOf方法的要求。

如果這種情況只是IsOwnerOf方法真正需要的,那麼可以從CommandConsumerCount方法中省略它。

但是,如果通過這兩種方法要求的條件,那麼,我堅持我的下方原來的答覆:

我認爲這是因爲您的兩個方法是公開的,合同要求,應重複。如果你有一個私人方法做了實際的工作,IsOwnerOf方法和CommandConsumerCount方法都被調用(而不是調用IsOwnerOf方法的CommandConsumerCount方法),那麼可以忽略對那個內部的Contract.Requires的調用私人方法。

就績效而言......除非檢查邏輯本身非常複雜,否則我不會擔心這些檢查的性能影響。您可以設置編譯器,以便在項目屬性的「代碼合同」部分(假設您已安裝必要的插件)中從編譯輸出中排除對Contract.Requires的調用。

雖然我也許錯過了你的問題。你問是否可以在CommandConsumerCount方法中完全省略對IsOwnerOf的調用?在這種情況下,我會保留這個調用,但是如果這是性能問題,那麼我會配置項目以排除對Release版本的調用,假設我已經使用Debug構建完成了足夠的測試,以確保此條件是滿意。

編輯:重新閱讀這個問題後,似乎很清楚你在問關於writeCommand != null檢查,所以我已經刪除了上面的段落。

添加執行IsOwnerOf方法實際工作的私有方法的代碼示例如下。

// you may want to choose a different name for this method 
    private bool _IsOwnerOf(IWriteCommand) 
    { 
     // actual work is done here in this private method 
     return default(bool); 
    } 

    public bool IsOwnerOf(IWriteCommand writeCommand) 
    { 
     Contract.Requires(writeCommand != null); 

     // call the private method to perform the actual work 
     return _IsOwnerOf(writeCommand); 
    } 

    public int CommandConsumerCount(IWriteCommand writeCommand) 
    { 
     Contract.Requires(writeCommand != null); 
     Contract.Requires(_IsOwnerOf(writeCommand)); // call the private _IsOwnerOf method instead of the public method 

     Contract.Ensures(Contract.Result<int>() >= 0); 

     return default(int); 
    } 
1

我會說,每種方法應該只指定它需要的條件,並且不知道它所調用的條件方法。

因此,如果CommandConsumerCount需要writeCommand不爲空,那麼擁有合同並不是多餘的。

但是,如果CommandConsumerCount需要writeCommand不爲空的唯一原因是將其傳遞給IsOwnerOf,那麼它是多餘的。

2

通常,如果方法A調用方法B,則A必須確保B上的所有契約都爲真。

但是,如果該方法用於需求,則它是多餘的,因爲所有需求必須由方法的調用者證明。

例如,如果您有:

CommandConsumerCount(x); 

由於沒有有關x,那麼靜態檢查器會抱怨IsOwnerOf必須是真實的。爲了證明IsOwnerOf,你的代碼必須做這樣的事情:

if (IsOwnerOf(x)) 
{ 
    CommandConsumerCount(x); 
} 

或:

IWriteCommand GetWriteCommand() 
{ 
    Contract.Ensures(IsOwnerOf(Contract.Result<IWriteCommand>())); 

    //... 
} 

var x = GetWriteCommand(); 
CommandConsumerCount(x); 

在這兩種情況下,IsOwnerOf不是空的合同也將被選中,因此,其論證被證明不是空的。

但是,如果你有CommandConsumerCount是這樣,而不是:

int CommandConsumerCount(IWriteCommand command) 
{ 
    Contract.Requires(command != null); 

    if (IsOwnerOf(command)) 
    { 
     // ... 
    } 

    return 0; 
} 

在這種情況下CommandConsumerCount需要的合同,由於呼叫者證明IsOwnerOf是真的沒有義務,所以非空合約不會被檢查。

+0

如果本網站允許我接受2個答案,我會:) – 2012-02-14 09:56:31

+0

關於靜態檢查器的非常酷的信息。我自己就開始使用契約。有趣的是,可以如何使用一種方法的確保條件來滿足隨後調用的方法的要求條件,例如在GetWriteCommand代碼示例中。 – 2012-02-15 17:27:45

相關問題