在scala中的require和assert之间选择什么

what to choose between require and assert in scala

requireassert都用于在运行时执行某些检查以验证某些条件。

那么它们之间的基本区别是什么?

我唯一看到的是require抛出IllegalArgumentException,而assert抛出AssertionError

如何选择使用哪一个?


正如Kigyo提到的,在语义上存在差异

  • assert表示您的程序已进入不一致状态,这可能是当前方法/函数存在的问题(我想将其视为HTTP 500 InternalServerError)
  • require意味着该方法的调用者有错误,应该修复它的调用(我喜欢将其视为HTTP 400 BadRequest)

还有一个主要的技术差异:

assert@elidable(ASSERTION)注释
这意味着您可以使用-Xelide-below ASSERTION-Xdisable-assertions编译程序,并且编译器将不会为断言生成字节码。如果您有大量的断言,这可以显着减小字节码的大小并提高性能。

知道了这一点,您可以使用assert来验证程序中所有地方的所有不变量(每个方法/函数调用的所有前提条件/后置条件),而无需付出生产上的代价。

通常,您将启用所有断言的"测试"构建,这会变慢,因为它将始终验证所有断言,然后您可以在没有断言的情况下进行产品的"生产"构建,这将消除通过断言完成所有内部状态检查

require是不可省略的,对于在库(包括内部库)中使用来通知调用方调用给定方法/函数的前提条件更有意义。


这只是我的主观观点。

每当我想对参数进行约束时,都使用require

例如,我们可以将阶乘用于自然数。由于我们不想处理负数,因此我们想抛出IllegalArgumentException

每当您要确保某些条件(如不变式)在执行期间始终为真时,我将使用assert。我认为这是一种测试方式。

这是使用requireassert的阶乘的示例实现

1
2
3
4
5
6
7
8
9
10
11
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为true时,循环至少执行一次。因此,结果必须大于或等于k。那将是一个循环不变式。

当您确定代码正确无误时,可以删除assert,但require会保留。


用非常简单的语言:

require用于对某个类的函数的调用者或对象的创建者强制执行先决条件。而assert用于检查函数本身的代码。
因此,如果前提条件失败,那么您将得到一个illegal argument exception。而如果断言失败并且不是调用者的错,那么您将得到一个assertion error


需求,确保和不变性是按设计合同(CBD)开发过程中的概念。

需要检查调用者使用该例程应满足的前提条件。

确保检查返回值的正确性(并仅验证是否发生了所需的更改,仅此而已)

不变在所有关键时刻检查类的有效性。

CBD是一种构建正确/强大软件的开发方法。有关CBD Google的更多详细信息,您应该点击Eiffel Software的链接。希望这可以帮助。