引用另一个约定方法时是否应该重复条件?
以下是接口合约的摘录。
我的问题是:前一种方法是否应该重复后一种方法的前提条件?由于合同是公开的,是否可以省略重复?在这种情况下,它只是一个非空检查,但我可以想象这样的情况:重复大量代码并且由于在运行时重复相同的检查而导致性能受到影响。
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);
}
The following is an extract from an interface contract.
My question is: should the former method repeat the pre-conditions of the latter method? As the contracts are public, would it be acceptable to omit the repetition? In this case it's simply a non-null check, but I can imagine the situation where a lot of code is repeated and performance suffers as identical checks are repeated at runtime.
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);
}
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(3)
这在某种程度上取决于该条件(在本例中为
writeCommand != null
)是否是 CommandConsumerCount 方法和 IsOwnerOf 方法的要求,或者是否仅是 IsOwnerOf 方法的要求。如果该条件仅是 IsOwnerOf 方法真正需要的,那么可以从 CommandConsumerCount 方法中省略它。
但是,如果这两种方法都需要该条件,那么我支持下面的原始答案:
我认为因为您的两种方法都是公开的,所以应该重复合同要求。如果您有一个执行实际工作的私有方法,IsOwnerOf 方法和 CommandConsumerCount 方法都调用该方法(而不是调用 IsOwnerOf 方法的 CommandConsumerCount 方法),那么在该方法中省略对 Contract.Requires 的调用就可以了。私有方法。
就性能而言......我不会担心这些检查对性能的影响,除非检查本身的逻辑非常复杂。您可以设置编译器以从项目属性的“代码合同”部分的编译输出中排除对 Contract.Requires 的调用(假设您安装了必要的插件)。
不过,也许我没有抓住你问题的重点。您是否询问是否可以完全省略 CommandConsumerCount 方法内部对 IsOwnerOf 的调用?在这种情况下,我会将调用保留在适当的位置,但如果这是一个性能问题,那么我将配置项目以排除对发布版本的调用,假设我已经使用调试版本进行了足够的测试以确保此条件是满意。编辑:重新阅读问题后,很明显您正在询问
writeCommand != null
检查,因此我删除了上面的段落。下面的代码示例添加了执行 IsOwnerOf 方法的实际工作的私有方法。
It kind of depends on whether that condition (
writeCommand != null
in this case) is a requirement for both the CommandConsumerCount method as well as the IsOwnerOf method, or if it is only a requirement for the IsOwnerOf method.If that condition is only really required by the IsOwnerOf method, then it would be ok to omit it from the CommandConsumerCount method.
However, if that condition is required by both methods, then I stand by my original answer below:
I think that because both of your methods are public that the contract requirements should be repeated. If you had a private method that did the actual work, which both the IsOwnerOf method and the CommandConsumerCount method called (instead of the CommandConsumerCount method calling the IsOwnerOf method), then it would be fine to omit the call to Contract.Requires inside of that private method.
As far as performance goes...I wouldn't be concerned about the performance impact of these checks, unless the logic for the checks themselves is very complicated. You can set up the compiler to exclude those calls to Contract.Requires from the compiled output in the "Code Contracts" section of the project properties (assuming you have the necessary plugin installed).
Perhaps I'm missing the point of your question, though. Are you asking if it's OK to completely omit the call to IsOwnerOf inside of the CommandConsumerCount method? In that case I would leave the call in place, but if it's a performance concern, then I would configure the project to exclude that call for Release builds, assuming that I've done sufficient testing with a Debug build to ensure that this condition is satisfied.EDIT: after re-reading the question, it seems clear that you're asking about the
writeCommand != null
check, so I've struck out the above paragraph.Code example below of adding a private method that performs the actual work of the IsOwnerOf method.
一般来说,如果方法A调用方法B,那么A必须确保B上的所有合约都是true。
但是,如果该方法用在 Requires 中,那就是多余的,因为所有 Requires 都必须由该方法的调用者证明。
例如,如果您有:
没有有关
x
的信息,则静态检查器将抱怨IsOwnerOf
必须为 true。为了证明IsOwnerOf
,您的代码必须执行以下操作:或者:
在这两种情况下,也会检查
IsOwnerOf
非空合约,因此参数被证明不为空。但是,如果您将
CommandConsumerCount
改为这样:在这种情况下,
CommandConsumerCount
将需要合约,因为调用者没有义务证明IsOwnerOf
为 true,因此不会检查非空合约。Generally, if method A calls method B, then A must ensure that all contracts on B are true.
However, if the method is used in a Requires, it is redundant, since all Requires must be proven by the caller of the method.
For example, if you have:
With no information about
x
, then the static checker will complain thatIsOwnerOf
is required to be true. In order to proveIsOwnerOf
, your code must do something like this:or:
In both these cases, the
IsOwnerOf
not-null contract will also be checked, and so the argument is proven to not be null.However, if you had
CommandConsumerCount
be something like this instead:In this case
CommandConsumerCount
would need the contract, since there is no obligation for the caller to prove thatIsOwnerOf
is true, and so the not-null contract will not have been checked.我想说的是,每个方法应该只指定它需要的条件,而忽略它调用的条件方法。
因此,如果
CommandConsumerCount
需要writeCommand
不为null,那么拥有合约并不多余。但是,如果
CommandConsumerCount
需要writeCommand
不为 null 的唯一原因是将其传递给IsOwnerOf
,那么它是多余的。I would say that each method should specify only the conditions that it needs and be ignorant of the conditions methods it calls.
So if
CommandConsumerCount
needswriteCommand
to not be null, then it is not redundant to have the contract.However if the only reason
CommandConsumerCount
needswriteCommand
to not be null is to pass it toIsOwnerOf
, then it is redundant.