2

我目前正在为 Java 编写一个小型参数检查库。检查以流畅的界面方式编写,如下所示:

Check.that(name).matches("hello .*!").hasLenghtBetween(0, 20);
Check.that(list).isNullOr().hasSize(0);
Check.that(args).named("arguments").isNotEmpty();

到目前为止,这些检查的语义是它们还隐式断言参数不为空。要允许 null,可以使用isNullOr()第二个示例中的修饰符方法。

我要添加的下一件事是支持这样的检查反转:

Check.that(name).not().matches("hello .*!");

但是现在我觉得默认的 nullness 处理变得奇怪和不直观。反转测试的正确方法是现在允许 null 。要禁止 null,必须isNotNull()明确地预先检查:

Check.that(name).isNotNull().not().matches("hello .*!");

因此,我正在考虑更改语义,以便始终需要显式检查空值。我知道一个也这样做的项目:Bean Validation。但不利的一面是,这可能会使大约 90% 的检查长 12 个字符,因为 null 通常是无效的参数。

所以,长话短说:支持和反对隐式空值检查的论据是什么?也许有任何其他库或标准可以这样做或以其他方式做到这一点?

4

2 回答 2

2

我会保持 API 相当简单,并且对方法调用顺序不敏感——基本上是一种流畅的 构建器模式。为此,请进行以下更改:

  • 使其有状态(使用实例而不是静态方法)
  • 进行最后一次方法调用的实际检查

每个方法调用都会建立要执行的标准,然后最后执行检查。

像这样:

new Check().matches("hello .*!").hasLengthBetween(0, 20).check(name);

这也将允许重用Check实例——这是您的无状态 ( static) 版本无法做到的。

再者,如果方法调用的顺序无关紧要,则完全避免使用“逻辑运算符”方法,这只会导致悲痛,你在哪里停下来?考虑这个荒谬的场景:

new Check().matches("hello .*!").hasLengthBetween(0, 20)
    .and().openBracket().isLowerCase().or().containsNumbers().closeBracket();
于 2012-09-23T14:02:09.367 回答
1

我想我找到了一个很好的折衷方案:所有检查进行隐式 null 检查,但 not()只反转实际检查而不是 null 检查。这样,我可以写

Check.that(message).not().containsAny(badWords);

并假设消息既非空也不包含任何坏词。我认为这涵盖了 90% 以上的用例。

当然,我仍然可以通过编写明确地允许 null

Check.that(message).isNullOr().not().containsAny(badWords);

第二个优点是这种设计将空值问题与其他检查分开,这可能也更直观。

于 2012-09-24T15:44:37.823 回答