我有一个对象的验证列表,现在这些验证非常昂贵,并且涉及到对另一个服务的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验证库,但需要一些帮助。
1条答案
按热度按时间ukqbszuj1#
Optional.empty()
看起来是个不错的想法,但是我发现验证的链接有点混乱。在这种情况下,也许一个典型的条件序列会更可读。例如:另一种选择是使用像Vavr这样的库,或者实现类似的东西。结果看起来像(或类似,我不记得确切的语法):
一个没有经过测试,没有经过太多思考的手动实现可能看起来像: