如果通过合同进行设计,除了成员函数中的不变量之外还需要先决条件和后置条件吗?
-
10-07-2019 - |
题
据我所知,在DbC方法中,前置条件和后置条件附加到函数中。
我想知道的是,这是否适用于会员功能。
例如,假设我在每个公共函数末尾的开头使用不变量,成员函数将如下所示:
编辑:(清理我的例子)
void Charcoal::LightOnFire() {
invariant();
in_LightOnFire();
StartBurning();
m_Status = STATUS_BURNING;
m_Color = 0xCCCCCC;
return; // last return in body
out_LightOnFire();
invariant();
}
inline void Charcoal::in_LightOnFire() {
#ifndef _RELEASE_
assert (m_Status == STATUS_UNLIT);
assert (m_OnTheGrill == true);
assert (m_DousedInLighterFluid == true);
#endif
}
inline void Charcoal::out_LightOnFire() {
#ifndef _RELEASE_
assert(m_Status == STATUS_BURNING);
assert(m_Color == 0xCCCCCC);
#endif
}
// class invariant
inline void Charcoal::invariant() {
assert(m_Status == STATUS_UNLIT || m_Status == STATUS_BURNING || m_Status == STATUS_ASHY);
assert(m_Color == 0x000000 || m_Color == 0xCCCCCC || m_Color == 0xEEEEEE);
}
是否可以仅使用全局/泛型函数的前提条件和后置条件,只使用类中的不变量?
这看起来有点矫枉过正,但也许我的榜样很糟糕。
编辑:
后置条件不仅仅是检查不变量的子集吗?
在上文中,我遵循 http://www.digitalmars.com的说明/ctg/contract.html 表示,<!> quot;当类构造函数完成时,在类析构函数的开头,运行公共成员之前以及公共函数完成之后,将检查不变量。 QUOT <!>;
感谢。
解决方案
是
C类的不变是其所有实例(对象)的公共属性。当且仅当对象处于语义有效状态时,不变量的计算结果为真。
电梯的不变量可能包含ASSERT(IsStopped() || Door.IsClosed())
等信息,因为电梯处于不同于停止状态(例如,上升)和门打开的状态无效。
相反,MoveTo(int flat)
等成员函数可能CurrentFlat()==flat
作为后置条件;因为在调用MoveTo(6)之后,当前的平面是6.同样,它可能IsStopped()
作为前提条件,因为(取决于设计)你不能调用函数MoveTo电梯已经在移动。首先,您必须查询其状态,确保它已停止,然后调用该函数。
当然,我可能完全过分简化了电梯的运作方式。
无论如何,一般来说,先决条件和后置条件作为不变条件是没有意义的;电梯不需要在6楼处于有效状态。
可以在这里找到一个更简洁的例子:截取和属性:Sasha Goldshtein的按合同设计的样本。
其他提示
将类中的合同限制为不变量并非最佳。
前提条件和后置条件不仅仅是不变量的一个子集。
不变量,前提条件和后置条件具有非常不同的作用。
不变量确认对象的内部一致性。它们应该在构造函数的末尾以及每次方法调用之前和之后有效。
前置条件是检查对象和参数的状态是否适合执行方法。前提条件是不变量的补充。它们涵盖了对参数的检查(更强的检查类型本身,即非空,<!> gt; 0,...等),但也可以检查对象的内部状态(即对file.write的调用(<只有当file.is_rw和file.is_open为真时,em> <!>“hello <!>”才是有效的调用。)
后期条件正在使该方法满足其义务后置条件也是不变量的补充。当然,对象的状态必须在方法执行后保持一致,但后置条件检查是否执行了预期的操作(即list.add(i)应该具有list.has(i)为真的结果和list.count = old list.count + 1)。
嗯,不变量的意思是它始终描述了对象的真实。在这种情况下,烤架上是否有东西(两者之间没有任何东西)。它们通常描述对象整个状态的属性。
前置条件和后置条件描述了在方法执行之前就已经存在的事情,以及之后,并且将关注仅仅应该被方法触及的状态。据推测,这与对象的状态不同。前后条件可能被认为是描述方法的足迹 - 正是它所需要的,只是它触及的内容。
所以,对于具体的问题,这些想法做了不同的事情,所以你可能都想要两者。你当然不能只使用不变量而不是前后条件 - 在这个例子中,对象不变量的一部分是<!>“;有些东西在格栅上或者不是<!>”,但是lightOnFire的前提条件需要知道这个项目在烤架上。你永远无法从对象不变量中推断出这一点。确实,从前置条件和后置条件以及已知的开始状态,您可以(假设对象结构只能通过方法变化,并且前后条件描述所有环境变化),推断对象不变。但是,这可能很复杂,当您在语言<!>中指出<!>“;”时,更容易提供两者。
当然,在声明布尔项的变体中执行true或false是有点无意义的 - 类型系统确保了。