在scala中,在require和assert之间选择什么
在scala中,在require和assert之间选择什么,scala,Scala,require和assert都用于在运行时执行某些检查,以验证某些条件 那么它们之间的基本区别是什么呢 我唯一看到的是requirethrowsIllegalArgumentException和assertthrowsAssertionError 如何选择使用哪一种?这只是我的主观观点 每当我想要对参数进行约束时,我就使用require 以自然数的阶乘为例。由于我们不想处理负数,我们想抛出一个IllegalArgumentException 只要您想确保某些条件(如不变量)在执行过程中始终为真,
require
和assert
都用于在运行时执行某些检查,以验证某些条件
那么它们之间的基本区别是什么呢
我唯一看到的是require
throwsIllegalArgumentException
和assert
throwsAssertionError
如何选择使用哪一种?这只是我的主观观点 每当我想要对参数进行约束时,我就使用
require
以自然数的阶乘为例。由于我们不想处理负数,我们想抛出一个IllegalArgumentException
只要您想确保某些条件(如不变量)在执行过程中始终为真,我就会使用断言。我认为这是一种测试方式
下面是一个带有require
和assert
def fac(i: Int) = {
require(i >= 0, "i must be non negative") //this is for correct input
@tailrec def loop(k: Int, result: Long = 1): Long = {
assert(result == 1 || result >= k) //this is only for verification
if(k > 0) loop(k - 1, result * k) else result
}
loop(i)
}
当result>1
为真时,循环至少执行一次。因此结果必须大于或等于k
。这将是一个循环不变量
当您确定代码是正确的时,可以删除断言
,但要求
将保留。如前所述,存在语义差异
- assert表示程序已达到不一致的状态这可能是当前方法/函数的问题(我喜欢将其视为HTTP 500 InternalServerError)
- require意味着方法的调用方出错,应该修复它的调用(我喜欢把它看作HTTP 400 BADDREQUEST)
还有一个主要的技术区别:
assert
用@eliable(ASSERTION)
这意味着您可以使用断言下方的-Xelide
或-xdisableassertions
编译程序,编译器不会为断言生成字节码。如果有大量断言,这可以显著减少字节码大小并提高性能
知道了这一点,您可以使用断言来验证程序中的所有不变量无处不在(每个方法/函数调用的所有先决条件/后决条件),而不必在生产过程中付出代价
您通常会在启用所有断言的情况下进行“测试”构建,速度会慢一些,因为它会始终验证所有断言,然后您可以在没有断言的情况下进行产品的“生产”构建,这将消除通过断言进行的所有内部状态检查
require
是不可删除的,在库(包括内部库)中使用它可以更好地通知调用方调用给定方法/函数的先决条件。用非常简单的语言:
Require
用于对函数的调用者或某个类的对象的创建者强制执行前提条件。而,assert
用于检查函数本身的代码。
因此,如果先决条件失败,则会出现非法参数异常
。然而,如果断言失败,并且不是调用方的错误,因此会出现断言错误
require,则确保和不变性是契约式设计(CBD)开发过程中的概念
需要检查调用方在使用例程时应满足的前提条件
确保检查返回值的正确性(并验证仅发生了所需的更改,仅此而已)
不变性检查类在所有关键时刻的有效性
CBD是一种构建正确/健壮软件的开发方法。有关CBD的更多详细信息,请点击谷歌和埃菲尔软件的链接。希望这能有所帮助。您可以查看Scala语言中的详细讨论
我可以补充一点,区分require
和assert
的关键在于理解这两者。这两个工具都是软件质量的工具,但来自不同范例的不同工具箱。总之,assert
是一种采用纠正方法的软件测试工具,而require
是一种采用预防方法的合同设计工具
require
和assert
都是控制状态有效性的手段。从历史上看,处理无效状态有两种不同的范式。第一个是主流的,统称为软件测试规程方法和工具。另一种称为合同设计。这是两个不可比较的范例
软件测试确保代码的通用性足以支持易出错的操作,并且不会被误用按合同设计控制代码不具有此类功能。换句话说,软件测试是纠正性的,合同设计是预防性的
assert
用于编写单元测试,也就是说,如果一个方法通过了由assert
表达式编写的所有测试,则该代码被认定为无错误。因此,assert
位于操作代码之外,是一个独立的机构
require
嵌入在代码中,并作为代码的一部分,以确保不会发生有害的事情
Scaladocs/javadocs也很不错:
- 断言()
测试表达式,如果为false,则抛出断言错误。如果下面的-Xelide大于断言,则不会生成对此方法的调用。
- 需要()
测试表达式,如果为false,则抛出IllegalArgumentException。此方法类似于assert,但将其归咎于t的调用方