Warning: file_get_contents(/data/phpspider/zhask/data//catemap/3/arrays/12.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/3/clojure/3.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java 契约式设计和断言语句_Java_Assert_Design By Contract_Post Conditions - Fatal编程技术网

Java 契约式设计和断言语句

Java 契约式设计和断言语句,java,assert,design-by-contract,post-conditions,Java,Assert,Design By Contract,Post Conditions,我对合同设计法感兴趣。似乎对于前提条件必须使用选中的异常来强制执行它们。 但是对于post条件和类不变量我认为断言是首选。 我说得对吗?如果我是正确的,为什么允许使用可能被禁用的post条件和类不变量断言?难道不应该强制执行post条件和不变量吗?只有在组件本身编写错误的情况下,组件上的post条件和类不变量才会失败。单元测试应该包括所有这些。当然,在生产中实际检查它们是允许的,但这并不一定值得进行性能权衡 另一方面,如果组件的用户不正确,前提条件可能会失败。组件本身上的测试无法检查这些,因此有

我对合同设计法感兴趣。似乎对于
前提条件
必须使用选中的异常来强制执行它们。
但是对于
post条件
类不变量
我认为
断言
是首选。

我说得对吗?如果我是正确的,为什么允许使用可能被禁用的
post条件
类不变量
断言?难道不应该强制执行post条件和不变量吗?

只有在组件本身编写错误的情况下,组件上的post条件和类不变量才会失败。单元测试应该包括所有这些。当然,在生产中实际检查它们是允许的,但这并不一定值得进行性能权衡

另一方面,如果组件的用户不正确,前提条件可能会失败。组件本身上的测试无法检查这些,因此有必要更积极地失败,以便这些单元测试失败。

您不应该以不同的方式对待它们-它们都应该是断言。

OP说:

。。。对于先决条件,似乎必须使用已检查的异常来强制执行它们。 ... 为什么允许使用可能被禁用的post条件和类不变量断言?post条件和不变量是否也应该强制执行

您似乎建议前置条件、后置条件和类不变量应该始终处于启用状态,并由服务(方法/被调用方)始终进行检查。如果我们说的是源自Bertrand Meyer的(DBC),那么事实并非如此。Meyers认为,从生产代码的角度来看,这些条件应该只在一个地方得到保证,无论是由客户机(调用者)还是由服务(被调用者)——这是客户机和服务之间的契约。相反,防御性编程说应该在这两个地方编写检查代码(Meyers认为这是浪费,增加了不必要的复杂性)

DBC的合同部分是,规范将明确谁负责什么:如果客户机将确保先决条件(服务可以假定它们为真),那么服务将确保后决条件(调用方可以假定它们为真)。Meyers当然明白,服务检查用于测试和调试目的的前置条件/后置条件/不变量是明智的(以确保系统在测试/调试过程中运行),这就是为什么在测试/调试过程中断言这些条件并启用断言是明智的,但目的是可以禁用或删除这些检查以用于生产

例如,如果设计的堆栈使调用方负责在调用pop()之前检查堆栈是否为空(前提条件),那么也不应该在pop()中编码方法作为生产代码的一部分检查堆栈是否为空,也不应将已检查异常作为处理条件的方法签名的一部分。可以在那里使用前提条件断言来帮助验证和调试,但目的是一旦开发和测试完成(代码可能没有bug),生产代码将只在确保前提条件的调用方而不是被调用方的情况下运行(如果这是您为API设计契约的方式)

如果作为pop()方法的一部分,您有一个选中的异常,并且作为“始终打开,必须处理”生产代码的一部分,您在pop()方法中检查堆栈是否为空,那么您的意思是服务(被调用方)负责检查,并承诺在堆栈为空时抛出异常-它现在是后置条件的一部分。在这种情况下,调用方不需要显式地检查它-他们应该只处理异常。否则,如果调用者和被调用者都首先检查堆栈是否为空,那么它就不是契约式设计

最后,有些人认为这意味着Meyer说调用方应该始终负责检查堆栈是否为空或参数是否为空,等等。并非如此-Meyers只是说,您必须在规范中明确前提条件和后条件,以便客户机和服务可以正确编码。作为API设计者和实现者,您可以决定前置条件和后置条件中的内容。如果您可以合理地确保客户机(调用者)将确保前提条件(例如,因为它是一个内部类,并且您控制调用服务/方法的所有地方),那么将“stack not empty”或“parameter-a-is-not-null”作为前提条件的一部分,并将ONU放在客户机上。但是,如果您认为这不是一个合理的假设(例如,它是一个公共API,或者无法对客户进行审查或测试以确保合规性),并且前提条件失败的后果很严重,然后不要将这些假设作为前提条件的一部分:继续,在服务中进行检查,并将选中的异常作为签名的一部分-将其作为post条件的一部分,即如果调用pop()时堆栈为空,则服务将抛出选中的异常


[[很抱歉这样的回答-我是Bertrand Meyer和契约式设计的忠实粉丝。]

违反先决条件定义为编程错误。因此,最不幸的是,用检查过的异常来表示这种违反。因为正确的代码将被强制显式捕获肯定永远不会抛出的异常,并将其作为未经检查的异常重新抛出,以便可以检测到编程错误。

失败的post条件将指示在开发过程中捕获的编程错误,当断言被启用时——这是我唯一能想到的事情。使用其中一种似乎有点武断。我更可能使用aspe