我的新工作场所大量使用功能
java Either用于其错误处理(
http://www.functionaljava.org/javadoc/4.5/functionaljava/fj/data/Either.html).
几乎没有使用异常.
出于多种原因,这非常烦人.命名一:
在方法内的每个api调用(返回一个Either)必须首先检查返回的Either是否是错误,然后再继续下一行.如果它是一个错误,它将以一种Either的形式传回方法调用的堆栈中.堆栈中的每个方法都需要检查返回的Either是否有错误,直到最后我们将找到负责处理错误的方法.
这导致结构非常糟糕的java代码.我不能写一个正常的流程java代码,因为我必须在每次api调用时“停止”(所以流不可能).例如
Either<Error, Value> myMethod(String someVar) {
Either<Error, Value> valEither someService.getSomething(someVar)
if (valEither.isRight()) {
Either<Error, Value> otherValue someService.getSomethingElse(valEither.right().value())
if (otherValue.isRight()) ..... //you get the idea
} else {
//maybe log
return valEither;
}
}
当然,我可以使用Either(我这样做)的monadic方法,但这不能解决必须“询问”返回类型的核心问题,如果它是错误或值.
我认为使用Either作为错误处理的基础设施不是一个好主意(长期分配法,长方法,嵌套泛型等)有很多原因.
为了解决这个问题,我想到可能会为每个api调用抛出一个特定的异常,它会返回一个“错误”,并在当前正在处理的顶级方法上捕获异常一次.
Value val = myService.getSomething().rightOrThrow(new MyException("blaa"));
但这似乎不可能作为Either投影类型的唯一方法,它做了类似的事情,抛出一个java错误,这并不意味着(几乎)在任何情况下被捕获(我可以意外地捕获stackoverflow或outofmemory错误).
myService.getSomething().right().valueE("some error msg");
有什么建议或想法?
谢谢
最佳答案 回到我在FJ编程的时候我也简单地遇到了这个问题.我很快意识到使用这种方式并不是很有帮助,而且像Exceptions这样的更多本机构造在语法上要轻得多,并且当然更适合语言.
当使用函数方法(例如bimap和map等)构建更多功能时,我确实使用了Either,所以类似于:
return someService.getSomething(someVar)
.bimap((e)-> new Error("getSomething died for " + someVar, e),
(x)-> someService.getSomethingElse(x))
.right().map((x)-> someService.getSAnotherThing(x));
也许这种结构似乎对支持模式匹配的语言更有意义.
编辑
至于如何抛出错误,好吧,看看valueE实现,你可以简单地编写自己的静态版本,抛出任何你喜欢的