My new workplace is heavily using functional java Either for its error handling (http://www.functionaljava.org/javadoc/4.5/functionaljava/fj/data/Either.html).
exceptions are almost not used at all.
This is very annoying imo for many reasons. To name one: Every api call (which returns an Either) inside a method, must first check if the returned Either is an error or not before continuing to the next line. If it is an error, it is propogated back in the stack of method calls in an a form of an Either. Each method up in the stack will also need to check the retunred Either for the error, until finally we will get to the method that is responsible for handling the error. This results in a very badly structued java code. i cant really write a normal flow java code as i have to "stop" on every api call (so streams are out of the question). for example
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;
}
}
I can, of course, use the monadic methods of Either (which i do) but that will not solve the core issues of having to "ask" the return type if its an error or a value. There are a lot more reasons why i think using Either as an infrastructure for error handling is not a good idea (long assigments statments, long methods, nested generics etc.).
To work around it, I thought of maybe throwing a specific exception for every api call which returns an "error" Either, and catch the exception once, on the top level method im currently working on.
Value val = myService.getSomething().rightOrThrow(new MyException("blaa"));
but that doesn't seem to be possible as the only method on the Either projection type which does something similiar, is throwing a java Error, which is not meant to be caught under (almost) any circumstances (I can accidently catch a stackoverflow or outofmemory errors).
myService.getSomething().right().valueE("some error msg");
Any suggestions or thoughts?
Thanks
Back when I programmed in FJ I briefly had this problem too. I quickly realized that using Either
this way was not very helpful, and that more native constructs like Exceptions
were much lighter syntactically and certainly fit better with the language.
I did use Either
when it made sense to compose further functionality using the functional methods (such as bimap
and map
et al), so something like:
return someService.getSomething(someVar)
.bimap((e)-> new Error("getSomething died for " + someVar, e),
(x)-> someService.getSomethingElse(x))
.right().map((x)-> someService.getSAnotherThing(x));
Perhaps this construct seems to make much more sense with languages that supports pattern matching..
As for how to throw an error, well, take a look at valueE implementation, you could simply write your own static version that throws whatever you like
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With