几年前,我对 Java 的 DbC 包进行了调查,但我对其中的任何一个都不完全满意。不幸的是,我没有很好地记录我的发现,我认为事情已经发生了变化。有人愿意为 Java 比较和对比不同的 DbC 包吗?
10 回答
WikiPedia上有一个关于按合同设计的很好的概述 ,最后有一个关于具有第三方支持库的语言的部分,其中包括一系列不错的 Java 库。这些 Java 库中的大多数都基于 Java 断言。
在您只需要前提条件检查的情况下,还有一个轻量级的验证方法参数解决方案,位于 SourceForge 的Java 参数验证(纯 Java 实现)下。
根据您的问题,对于字段/属性约束验证,OVal框架可能是一个不错的选择。该框架允许您以各种不同的形式(注释、POJO、XML)放置约束。通过 POJO 或脚本语言(JavaScript、Groovy、BeanShell、OGNL、MVEL)创建客户约束。并且它还参与了按合同进行编程。
Google 有一个名为contracts for java的开源库。
Contracts for Java 是我们新的开源工具。前置条件、后置条件和不变量作为 Java 布尔表达式添加到注解中。默认情况下,它们什么都不做,但通过 JVM 参数启用,它们在运行时被检查。
• @Requires, @Ensures, @ThrowEnsures and @Invariant specify contracts as Java boolean expressions • Contracts are inherited from both interfaces and classes and can be selectively enabled at runtime
我测试了一次contract4J,发现它可用但并不完美。您正在为整个类的方法调用和 invars 和之后创建合同。
合约是作为方法的断言而创建的。问题是合同本身是用字符串编写的,因此您没有合同的 IDE 支持,也没有编译时检查合同是否仍然有效。
图书馆的链接
我强烈建议您考虑 Java 建模语言 ( JML )。
有一个 Groovy 扩展,可以在 Groovy/Java 代码中启用 Design by Contract(tm) - GContracts。它使用所谓的闭包注释来指定类不变量、前置条件和后置条件。可以在项目的 github wiki 上找到示例。
主要优点:它只是一个没有外部依赖项的 jar,并且可以通过 Maven 兼容的存储库解析,因为它被放置在中央 Maven存储库中。
如果您想要一个简单明了的基本支持来表达您的合同,请查看 valid4j(在 Maven Central 上以 org.valid4j:valid4j 的形式找到)。它可以让你使用普通的 hamcrest-matchers 来表达你的合约(没有注释,也没有评论)。
对于前置条件和后置条件(基本上是断言 -> 抛出 AssertionError):
import static org.valid4j.Assertive.*;
require(inputList, hasSize(greaterThan(0)));
...
ensure(result, lessThan(4.0));
如果您对默认的全局策略(抛出 AssertionError)不满意,valid4j 提供了一种自定义机制,让您可以提供自己的 org.valid4j.AssertiveProvider 实现。
链接:
我建议结合使用一些工具:
Java
assert condition...
或它更高级的 Groovy 表亲、Guava 的Preconditions.checkXXXX(condition...)
andVerify.verify(condition...)
或类似AssertJ的库,如果您只需要在“主”或“测试”代码中进行简单检查使用OVal 之类的工具,您将获得更多功能;它可以检查对象以及方法参数和结果,您还可以手动触发检查(例如,在调用方法之前在 UI 上显示验证错误)。它可以理解现有的注释,例如来自 JPA 或
javax.validation
(like@NotNull
,@Pattern
,@Column
) 的注释,或者您可以编写内联约束,例如@Pre(expr="x >= 0 && x <= y")
. 如果注解是@Documented
,检查也将在 Javadocs 中可见(您也不必在那里描述它们)。OVal使用反射,会在Android等一些环境下产生性能问题等问题;那么你应该考虑像谷歌的 Cofoja这样的工具,它的功能较少,但依赖于编译时注释处理工具而不是反射
我认为许多 DbC 库都被内置的assert关键字所取代,自 Java 1.4 开始引入:
- 它是内置的,不需要其他库
- 它适用于继承
- 您可以根据套餐激活/停用
- 易于重构(例如,评论中没有断言)
我个人认为目前可用的 DbC 库还有很多不足之处,我看过的库中没有一个与 Bean Validation API 配合得很好。
我查看的库已在此处记录
Bean Validation API 与 DbC 的概念有很多重叠之处。在某些情况下,Bean Validation API 不能像简单的 POJO(非 CDI 托管代码)那样使用。IMO 一个关于 Bean Validation API 的 think wrapper 就足够了。
我发现现有的库添加到现有的 Web 项目中有点棘手,因为它们是通过 AOP 或字节码检测实现的。可能随着 Bean Validation API 的出现,实现 DbC 的这种复杂性是没有根据的。
我还在这篇文章中记录了我的咆哮,并希望构建一个利用 Bean Validation API 的小型库