1

我最近遇到了一些场景,其中对代码的微小更改导致跨多个类更改前提条件,我想知道按合同设计是否应该是这种方式。

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

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

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

4

2 回答 2

3

这取决于您的调用方法究竟做了什么。先决条件的重要一点是调用者负责满足先决条件

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


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

似乎继承前置条件会使事情变得脆弱,而更改为队列或其他结构会将前置条件更改为 getNextGoal(),它是调用者,它是调用者的调用者。

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

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

于 2010-12-21T07:45:22.587 回答
0

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

记录如果没有目标会发生什么是正常的。EG 这就是 malloc() 在 C 中所做的

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

于 2010-12-20T16:39:43.497 回答