提问人:SAIKAT CHAKRABORTY 提问时间:10/13/2023 更新时间:10/13/2023 访问量:53
在 Java 中简化验证规则序列
Simplifying Validation rule sequence in Java
问:
我现在有一个对象的验证列表,这些验证非常昂贵,并且涉及对另一个服务的 API 调用。在调用验证服务时,我需要在第一次收到否定验证或错误/异常时短路验证链。 我目前所拥有的是每个验证帮助程序函数都会返回一个 Optional。当验证成功时,此可选项为空。如果由于调用的服务的响应或服务引发异常而导致验证失败,我们只需返回该 ValidationResult,在链的末尾,我们返回一个 Valid ValidationResult
这是此处的可选链接:
return checkBelongsToGroup(row)
.orElseGet(() -> checkParentToGroup(row)
.orElseGet(() -> checkLocation(row)
.orElseGet(() -> builder()
.outcome(ValidationResult
.Outcome.VALID).build())));
现在提供其中一个验证函数来体验它的外观:
public Optional<ValidationResult> checkBelongsToGroup(final Row row) {
if (Strings.isNullOrEmpty(row.getPreviousId())) {
return Optional.empty(); //valid
}
return Try.of(() -> serviceClient.getassociation(row))
.toEither()
.mapLeft(this::getThrowableError)
// helper function to change exception to ValidationResult
.fold(validationError -> Optional.of(validationError), getAssociationOutput -> {
final Association association = getAssociationOutput.getAssociation();
if (association != null && association.isActive()) {
return Optional.empty(); // Success case
} else {
return Optional.of(builder()
.outcome(ValidationResult.Outcome.INVALID)
.errorStringId(INVALID)
.build()); // Validation failed.
}
});
}
这里奇怪的部分是 Optional.empty 被用来类似于语义上错误的成功案例。有没有办法进行这种链式短路验证,直到验证的第一个异常失败。 我正在考虑 vavr 的验证库,但需要一些帮助。
答:
0赞
fjavierm
10/13/2023
#1
这似乎是一个不错的主意,但我发现验证的链接有点令人困惑。在这种情况下,也许一系列典型的条件会更具可读性。像这样:Optional.empty()
var result = checkBelongsToGroup(row);
if (result.isEmpty()) {
result = checkParentToGroup(row);
}
if (result.isEmpty()) {
result = checkLocation(row);
}
if (!result.isEmpty()) {
// manage error
}
// success code
另一种选择是使用像 Vavr 这样的库,或者实现类似的东西。结果看起来像(或类似,我不记得确切的语法):
Validation<ValidationResult, Void> result = Validation.combine(
checkBelongsToGroup(row),
checkParentToGroup(row),
checkLocation(row)
).ap((a, b, c) -> null);
if (result.isInvalid()) {
var failure = result.getError();
// manage error
}
// success code
一个手动实现,没有经过测试,没有太多思考,可能看起来像:
Stream<Function<Row, ValidationResult>> validators = Stream.of(
this::checkBelongsToGroup,
this::checkParentToGroup,
this::checkLocation
);
ValidationResult failure = validators
.map(validator -> validator.apply(row))
.filter(Optional::isPresent)
.findFirst()
.orElseGet(Optional::empty);
if (failure.isPresent()) {
// manage error
}
// success code
评论
0赞
SAIKAT CHAKRABORTY
10/13/2023
对于 vavr 验证的事情,它看起来既有趣又干净。我担心的一个问题是必须保持验证的顺序,并且它应该在从一个函数(短路)返回的第一个错误/异常时返回,我不太确定这是否会发生或可以配置为 vavr 验证。
评论