方法是否应该与它们调用的方法具有相同的前提条件?

发布于 2024-10-08 08:11:54 字数 406 浏览 9 评论 0原文

我最近遇到了一些场景,其中对代码的微小更改导致跨多个类的先决条件发生变化,我想知道契约设计是否应该是这样。

public Goal getNextGoal() {
    return goalStack.pop();
}

如果 goalStack.pop() 的前提条件是堆栈不为空,那么 getNextGoal() 是否需要显式地具有相同的前提条件?继承前提条件似乎会让事情变得脆弱,而更改为队列或其他结构会将前提条件更改为 getNextGoal() ,它是调用者,也是调用者的调用者。但似乎不继承先决条件会隐藏合约和调用者,而调用者的调用者不会知道先决条件。

那么脆弱的代码(所有调用者都知道并继承他们调用的代码的前置条件和后置条件),或者神秘的代码(调用者永远不知道更深层次的前置条件和后置条件是什么)?

I've recently had a few scenarios where small changes to code have resulted in changing preconditions across multiple classes and I was wondering if design by contract is supposed to be that way or not.

public Goal getNextGoal() {
    return goalStack.pop();
}

If goalStack.pop() has a precondition that the stack isn't empty, then does getNextGoal() need to explicitly have the same precondition? It seems like inheriting the preconditions would make things brittle, and changing to a queue or other structure would change the preconditions to getNextGoal(), it's callers, and it's callers' callers. But it seems like not inheriting the preconditions would hide the contracts and the callers, and the callers' callers, wouldn't know about the preconditions.

So brittle code where all callers know and inherit the preconditions and postconditions of the code they call, or mysterious code where callers never know what the deeper preconditions and postconditions are?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

卖梦商人 2024-10-15 08:11:54

这取决于您的调用方法的具体用途。 先决条件的重要一点是调用者有责任满足先决条件

因此,如果 GetNextGoal 方法的调用者应该负责提供非空堆栈,那么您确实还应该在 GetNextGoal 方法上设置先决条件。前提条件的清晰性是代码契约的巨大优势之一,因此我建议您将它们放在调用者必须满足前提条件的所有位置。


但是,如果您的代码看起来很脆弱,这可能表明您需要重构某些代码

看来是继承了
前提条件会使事情发生
脆弱,并更改为队列或
其他结构会改变
getNextGoal() 的前提条件是
呼叫者,而且是呼叫者的呼叫者。

如果您将队列公开给调用者并稍后将其更改(如您所说,更改为另一个结构),则调用者也必须更改。这通常是代码脆弱的标志。

如果您要公开一个接口而不是特定的队列实现,您的先决条件也可以使用该接口,并且您不必在每次实现更改时都更改先决条件。从而减少脆弱的代码。

It depends on what your calling method does exactly. The important thing with preconditions is that the caller is responsible for fulfilling the preconditions.

So if callers of your GetNextGoal method should be responsible for providing a non-empty stack, then you should indeed also set preconditions on your GetNextGoal method. Clarity of preconditions is one of the huge advantages of Code Contracts, so I'd suggest you put them in all places where callers have to fulfill the preconditions.


If your code seems brittle however, it might be a sign that you need to refactor some code.

It seems like inheriting the
preconditions would make things
brittle, and changing to a queue or
other structure would change the
preconditions to getNextGoal(), it's
callers, and it's callers' callers.

If you expose the queue to the callers and change it later ( to another structure, like you said ), it's callers would also have to change. This is usually a sign of brittle code.

If you would expose an interface instead of a specific queue implementation, your preconditions could also use the interface and you wouldn't have to change the preconditions every time your implementation changes. Thus resulting in less brittle code.

错爱 2024-10-15 08:11:54

例外是一种解决方案,但对于您的情况可能不可行。

记录没有目标时发生的情况是正常的。EG 这就是 malloc() 在 C 中所做的事情

我无法判断您使用的是 Java 还是 C++ 还是其他语言,因为每种语言对于该特定语言可能有稍微更自然的方法。

Exceptions are one solution but perhaps not feasible for your situation.

Documenting what happens if there are no goals is normal.E.G. This is what malloc() does in C

I can't tell if you are using Java or C++ or something else as each language might have slightly more natural ways for that specific language.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文