我知道用于检查方法前置条件的典型Groovy习惯用法 - 例如要求非空,或在可接受值的某个范围内 - 通常使用assert
。
然而,在我看来,这种方法有几个缺点,而不是使用熟悉的(对我来说)依赖Preconditions utilities in Google Guava的Java方法。
java.lang.AssertionError
。这远没有那么明确,因为失败的空检查会抛出NullPointerException
而其他参数问题会抛出IllegalArgumentException
,这可以从Preconditions
轻松完成。无论出于何种原因,如果我想尝试捕获一个糟糕的方法调用,那么调用代码将更难以理解确切原因方法失败的AssertionError
。assert
进行任何其他类型的检查 - 例如验证我的类的状态不变量 - 来自调用者再次确定{{{ 1}}它接收,而不是收到我的应用程序独有的AssertionError
或一些更具体的自定义子类型。失败是调用者的错吗?或者被称为班级车,其内部状态搞砸了?IllegalStateException
检查更容易 - 我可以在抛出的Preconditions
或其他任何地方的每个方法调用中设置一个断点,并知道它是否被击中。或者,只要抛出特定的异常类型(即,仅IllegalArgumentException
,而不是任何断言失败),我就可以在每个当前感兴趣的前提条件失败的情况下放置断点。IndexOutOfBoundsException
的调用必须是一个先决条件检查,并且调用的特定方法提供更直接的信息。 Preconditions
可以检查任何内容。关于使用assert
的唯一优势,我可以看到,不必手动添加坏参数值的打印,如assert
下面:
constrainWithPreconditions2
那我错过了什么? @Grab(group='com.google.guava', module='guava', version='18.0')
import com.google.common.base.Preconditions
static String constrainWithPreconditions(def param1) {
Preconditions.checkNotNull(param1, 'param1 can NOT be null!')
}
static String constrainWithAssertions(def param1) {
assert param1, 'param1 can NOT be null!'
}
// constrainWithPreconditions(null)
// PRODUCES:
// java.lang.NullPointerException: param1 can NOT be null!
// constrainWithAssertions(null)
// PRODUCES:
// java.lang.AssertionError: param1 can NOT be null!. Expression: param1. Values: param1 = null
static String constrainWithPreconditions2(def param1, def param2) {
Preconditions.checkArgument(param1 < param2, "param1 ($param1) MUST be < param2 ($param2)!")
}
static String constrainWithAssertions2(def param1, def param2) {
assert param1 < param2, 'param1 MUST be < param2!'
}
constrainWithPreconditions2(2, 1)
// PRODUCES:
// java.lang.IllegalArgumentException: param1 (2) MUST be < param2 (1)!
// constrainWithAssertions2(2, 1)
// PRODUCES:
// ava.lang.AssertionError: param1 MUST be < param2!. Expression: (param1 < param2). Values: param1 = 2, param2 = 1
还有其他缺点吗?我没有使用Preconditions
错过任何其他内容吗?