【问题标题】:what to choose between require and assert in scala在scala中的require和assert之间选择什么
【发布时间】:2014-10-01 11:52:11
【问题描述】:

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

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

我看到的唯一一个是 require throws IllegalArgumentExceptionassert throws AssertionError

如何选择使用哪一个?

【问题讨论】:

    标签: scala


    【解决方案1】:

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

    • assert 表示您的程序已达到不一致的状态,这可能是当前方法/函数的问题(我喜欢将其视为 HTTP 500 InternalServerError)
    • require 表示方法的调用者有问题,应该修复它的调用(我喜欢把它想象成 HTTP 400 BadRequest)

    还有一个主要的技术区别:

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

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

    您通常会在启用所有断言的情况下构建“test”,它会更慢,因为它会始终验证所有断言,然后您可以拥有“production " 没有断言的产品构建,您将消除通过断言完成的所有内部状态检查

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

    【讨论】:

    【解决方案2】:

    这只是我的主观观点。

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

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

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

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

    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,但require 会保留。

    【讨论】:

    • 所以基本上它只是为了理解目的,没有其他区别
    • 当不满足给定条件时,它们都会抛出异常。是的,只是例外情况不同。
    【解决方案3】:

    您可以查看here 了解有关 Scala 语言的详细讨论。

    我可以补充一点,区分requireassert的关键是理解这两个。这两者都是软件质量的工具,但来自不同范例的不同工具箱。总而言之,assert 是一种软件测试工具,它采用纠正方法,而require 是一种合同设计工具,采用预防方法。

    requireassert 都是控制状态有效性的方法。从历史上看,处理无效状态有两种不同的范式。第一个是主流统称为软件测试学科方法和工具。另一种称为按合同设计。这是两个没有可比性的范式。

    软件测试确保代码具有足够的通用性,能够执行容易出错的操作,并且不会被滥用。 按合同设计控制代码不具有这种能力。换句话说,软件测试是纠正性的,合同设计是预防性的。

    • assert 用于编写单元测试,即如果一个方法通过了由 assert 表达式编写的所有测试,则代码被认定为无错误。所以assert除了操作代码之外,是一个独立的机构。
    • require 嵌入在代码中,其中一部分是为了确保不会发生任何有害的事情。

    【讨论】:

      【解决方案4】:

      用非常简单的语言:

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

      【讨论】:

        【解决方案5】:

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

        require 检查调用者在使用例程时应满足的先决条件。

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

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

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

        【讨论】:

          【解决方案6】:

          Scaladocs/javadocs 也不错:

          • 断言()

          Tests an expression, throwing an AssertionError if false. Calls to this method will not be generated if -Xelide-below is greater than ASSERTION.

          • 要求()

          Tests an expression, throwing an IllegalArgumentException if false. This method is similar to assert, but blames the caller of the method for violating the condition.

          【讨论】:

            猜你喜欢
            • 2012-02-09
            • 2017-03-04
            • 1970-01-01
            • 2013-07-06
            • 1970-01-01
            • 2011-10-31
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            相关资源
            最近更新 更多