在没有断言的情况下在运行时检查无内容
check with no content at runtime without assertions
据我在 Eiffel 中的理解,如果语句 returns False
,则以下没有断言的代码会失败
check
i_m_alive: i.alive
then
do_nothing
end
可能是我用得不好,但有时我只想检查一下,什么都不做。
- 这条语句有断言和没有断言的确切行为是什么?
- 我应该使用带有
if
语句的 raise
吗?
- 我有时会尝试向
check ... then
添加一个 else 语句,但它没有实现我确定是有原因的,可能是因为没有其他选择,因为在语句 [=33 的情况下会引发异常=] True
特别是在 EWF(Eiffel Web 框架)上,我看到的报告错误和处理错误的唯一方法是写入日志或将详细信息发送给 referrer,其中一些详细信息有时不足以发送到用户。向管理员发送电子邮件也是一种可能性......我有点迷茫,但知道 raise 和 Exception mecanisms 不是 Eiffel 推荐的处理错误的方式。
我将进一步深入探讨 available documentation,但像我一样,TL;DR 会很乐意对此有一个更简洁的答案或更多观点。
将断言视为在您的代码中指定程序当前状态的语句。例如:
这里变量x
等于5
;
此处列表的所有元素都附加到现有对象;
这里两个结构有如下关系等
断言只是描述程序的行为(即它们是声明性的)。它们没有定义行为(即它们不是强制性的)。
断言可以有不同的形式:class不变量、前置条件和后置条件、循环变体等。但是它们都是当执行到[=69=对应点时程序状态的声明]-时间。删除此类声明不会改变行为。是否检查断言由编译器和 运行-time 选项控制。如果程序是正确的,即没有任何断言被违反,这样的删除不会影响最终结果(除了,也许,性能)。此外,一些工具可以在编译时验证断言,因此根本不需要 运行-时间检查。换句话说,断言用于指定程序行为,而其他代码用于实现该行为。
但是,如果程序不正确,则会触发异常。它告诉程序员有错误,应该修复。
这同样适用于结构check ... then ... end
。它表示总是满足指定的条件(如果实现正确)。如果违反条件,则程序中存在错误。这就是为什么没有 else
部分的原因:这个结构不控制程序执行,它只是检查执行是否按预期进行。
如果编译器足够聪明,如果可以在编译时检查条件并报告错误,或者完全删除条件(如果可以证明从未违反)。但是,目前的技术还没有。结果,在 运行 时生成并检查了检查条件的代码(我们称之为 "assumption")。特别是,它确保 then
部分中的代码可以安全地依赖已检查的假设。当编译器无法正确推断(对您作为开发人员而言)始终附加的表达式的附加状态时,此类检查在 void-safe 代码中变得至关重要。与其他断言不同,这个断言不能关闭(事实上,一些先决条件在 SCOOP 中也不能关闭——它们是语义的一部分)。
如果您想使用异常来控制程序行为,断言不是正确的工具。正如您提到的,应该使用对 raise
异常的显式调用。
总结一下:
断言描述程序行为,它们无意影响行为;
控制程序行为的异常应该明确提出(这应该避免);
check ... then ... end
是强制性的,无论编译器和 运行-time 设置如何都会被检查;
没有 else
部分,因为断言不控制程序行为。
据我在 Eiffel 中的理解,如果语句 returns False
check
i_m_alive: i.alive
then
do_nothing
end
可能是我用得不好,但有时我只想检查一下,什么都不做。
- 这条语句有断言和没有断言的确切行为是什么?
- 我应该使用带有
if
语句的raise
吗? - 我有时会尝试向
check ... then
添加一个 else 语句,但它没有实现我确定是有原因的,可能是因为没有其他选择,因为在语句 [=33 的情况下会引发异常=]True
特别是在 EWF(Eiffel Web 框架)上,我看到的报告错误和处理错误的唯一方法是写入日志或将详细信息发送给 referrer,其中一些详细信息有时不足以发送到用户。向管理员发送电子邮件也是一种可能性......我有点迷茫,但知道 raise 和 Exception mecanisms 不是 Eiffel 推荐的处理错误的方式。
我将进一步深入探讨 available documentation,但像我一样,TL;DR 会很乐意对此有一个更简洁的答案或更多观点。
将断言视为在您的代码中指定程序当前状态的语句。例如:
这里变量
x
等于5
;此处列表的所有元素都附加到现有对象;
这里两个结构有如下关系等
断言只是描述程序的行为(即它们是声明性的)。它们没有定义行为(即它们不是强制性的)。
断言可以有不同的形式:class不变量、前置条件和后置条件、循环变体等。但是它们都是当执行到[=69=对应点时程序状态的声明]-时间。删除此类声明不会改变行为。是否检查断言由编译器和 运行-time 选项控制。如果程序是正确的,即没有任何断言被违反,这样的删除不会影响最终结果(除了,也许,性能)。此外,一些工具可以在编译时验证断言,因此根本不需要 运行-时间检查。换句话说,断言用于指定程序行为,而其他代码用于实现该行为。
但是,如果程序不正确,则会触发异常。它告诉程序员有错误,应该修复。
这同样适用于结构check ... then ... end
。它表示总是满足指定的条件(如果实现正确)。如果违反条件,则程序中存在错误。这就是为什么没有 else
部分的原因:这个结构不控制程序执行,它只是检查执行是否按预期进行。
如果编译器足够聪明,如果可以在编译时检查条件并报告错误,或者完全删除条件(如果可以证明从未违反)。但是,目前的技术还没有。结果,在 运行 时生成并检查了检查条件的代码(我们称之为 "assumption")。特别是,它确保 then
部分中的代码可以安全地依赖已检查的假设。当编译器无法正确推断(对您作为开发人员而言)始终附加的表达式的附加状态时,此类检查在 void-safe 代码中变得至关重要。与其他断言不同,这个断言不能关闭(事实上,一些先决条件在 SCOOP 中也不能关闭——它们是语义的一部分)。
如果您想使用异常来控制程序行为,断言不是正确的工具。正如您提到的,应该使用对 raise
异常的显式调用。
总结一下:
断言描述程序行为,它们无意影响行为;
控制程序行为的异常应该明确提出(这应该避免);
check ... then ... end
是强制性的,无论编译器和 运行-time 设置如何都会被检查;没有
else
部分,因为断言不控制程序行为。