Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Either for error handling in java

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

like image 557
yaarix Avatar asked Nov 08 '22 22:11

yaarix


1 Answers

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..

Edit

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

like image 80
Shlomi Avatar answered Nov 15 '22 05:11

Shlomi