Java 返回可选值,具体取决于流内部使用的方法引发的异常
我正在尝试实现用于处理事件的验证模块。验证模块基于简单的界面:Java 返回可选值,具体取决于流内部使用的方法引发的异常,java,exception,code-cleanup,Java,Exception,Code Cleanup,我正在尝试实现用于处理事件的验证模块。验证模块基于简单的界面: public interface Validator { Optional<ValidationException> validate(Event event); } public interface Validator { void validate(Event event) throws ValidationException; } 这件作品看起来不错,但我对它的外观感到不舒服。我
public interface Validator {
Optional<ValidationException> validate(Event event);
}
public interface Validator {
void validate(Event event) throws ValidationException;
}
这件作品看起来不错,但我对它的外观感到不舒服。我最关心的是将整个流处理放在一次尝试中是否是一种好的做法。此外,我不认为这种异常捕获+返回选项的混合是优雅的
对于这种情况,我可以使用一些建议和/或最佳实践。返回异常而不是返回异常很奇怪,但不管怎样。(为什么不返回一个
ValidationResult
对象呢?异常通常被抛出并捕获)
但是您可以将私有方法更改为也返回可选的
实例,这样可以更容易地组合它们。它还可以避免混合投掷和返回以及流。不确定这是否就是你要找的
public class ValidBallsOnlyValidator implements Validator {
@Override
public Optional<ValidationException> validate(Event event)
return event.getToys()
.stream()
.filter(Optional::isPresent)
.findFirst()
.map(ex -> new ValidationException(ex.getMessage()));
}
private Optional<InvalidToyException> validateSingleToy(Toy toy) {
// In real code the optional here is kinda mandatory
Optional<Toy> potentialBall = castToyToBall(toy);
if(potentiallBall.isPresent()) {
return checkIfBallIsOfValidSize(potentialBall.get(), "exampleSize");
} else {
return Optional.of(new InvalidToyException("The toy is not a ball!"));
}
}
private Optional<InvalidToyException> checkIfBallIsOfValidSize(Toy toy, String size) {
if(toyTooLarge(toy, size)) return Optional.of(new InvalidToyException("The ball is too big!"));
return Optional.empty();
}
}
public类ValidBallsOnlyValidator实现验证器{
@凌驾
公共可选验证(事件)
return事件。getToys()
.stream()
.filter(可选::isPresent)
.findFirst()
.map(例如->新建ValidationException(例如getMessage());
}
私人可选validateSingleToy(玩具玩具){
//在实数代码中,这里的可选项是强制性的
可选电位球=卡斯托球(玩具);
if(PotentialBall.isPresent()){
返回checkIfBallIsOfValidSize(potentialBall.get(),“exampleSize”);
}否则{
返回可选。of(新的InvalidToyException(“玩具不是球!”);
}
}
私人可选checkIfBallIsOfValidSize(玩具、字符串大小){
如果(ToyToolage(玩具,尺寸))返回可选的(新的无效ToyException(“球太大了!”));
返回可选的.empty();
}
}
返回异常而不是返回异常很奇怪,但无论如何。(为什么不返回一个ValidationResult
对象呢?异常通常被抛出并捕获)
但是您可以将私有方法更改为也返回可选的
实例,这样可以更容易地组合它们。它还可以避免混合投掷和返回以及流。不确定这是否就是你要找的
public class ValidBallsOnlyValidator implements Validator {
@Override
public Optional<ValidationException> validate(Event event)
return event.getToys()
.stream()
.filter(Optional::isPresent)
.findFirst()
.map(ex -> new ValidationException(ex.getMessage()));
}
private Optional<InvalidToyException> validateSingleToy(Toy toy) {
// In real code the optional here is kinda mandatory
Optional<Toy> potentialBall = castToyToBall(toy);
if(potentiallBall.isPresent()) {
return checkIfBallIsOfValidSize(potentialBall.get(), "exampleSize");
} else {
return Optional.of(new InvalidToyException("The toy is not a ball!"));
}
}
private Optional<InvalidToyException> checkIfBallIsOfValidSize(Toy toy, String size) {
if(toyTooLarge(toy, size)) return Optional.of(new InvalidToyException("The ball is too big!"));
return Optional.empty();
}
}
public类ValidBallsOnlyValidator实现验证器{
@凌驾
公共可选验证(事件)
return事件。getToys()
.stream()
.filter(可选::isPresent)
.findFirst()
.map(例如->新建ValidationException(例如getMessage());
}
私人可选validateSingleToy(玩具玩具){
//在实数代码中,这里的可选项是强制性的
可选电位球=卡斯托球(玩具);
if(PotentialBall.isPresent()){
返回checkIfBallIsOfValidSize(potentialBall.get(),“exampleSize”);
}否则{
返回可选。of(新的InvalidToyException(“玩具不是球!”);
}
}
私人可选checkIfBallIsOfValidSize(玩具、字符串大小){
如果(ToyToolage(玩具,尺寸))返回可选的(新的无效ToyException(“球太大了!”));
返回可选的.empty();
}
}
但是我对它的样子感到不舒服
您正在使用的API是疯狂的设计。处理愚蠢API的方法通常是相同的:
public interface Validator {
Optional<ValidationException> validate(Event event);
}
public interface Validator {
void validate(Event event) throws ValidationException;
}
更一般地说,验证不是一种“最多有一件事出错”的情况,而这正是您的问题所在,即“围绕整件事编写一个try/catch感觉很奇怪”
很多事情都可能出错。可能有5个玩具,其中一个是球,但太大,其中一个是吱吱作响的玩具。只报告一个错误(可能是任意选择的错误)是很奇怪的
如果您打算不抛出验证异常,而是返回验证问题,那么问题首先应该不是异常,而是其他对象,并且,您应该使用列表
,而不是可选
。你已经摆脱了一个选择,这永远是一个胜利,你现在可以处理多个问题,在一次去。如果处理所有这些问题的“终点”基本上无法同时处理多个问题,那没关系:他们可以将该列表视为有效的可选选项,使用list.isEmpty()
作为“一切正常”的指示器,而list.get(0)
否则用于处理第一个问题(这是这个一次一个错误的系统能够处理的唯一问题)
这涉及到代码优雅,这是定义“优雅”一词的唯一有意义的方式:它是更容易测试、更容易理解和更灵活的代码。它更灵活:如果稍后处理验证错误的端点代码被更新为能够处理多个错误,您现在可以在不接触代码t的情况下执行此操作hat使验证问题成为对象