Either for error handling in java

My new workplace makes heavy use of functional java Either for error handling ( http://www.functionaljava.org/javadoc/4.5/functionaljava/fj/data/Either.html ).

exceptions are hardly used at all.

This is very annoying imo for many reasons. To name one: Every api call (that returns Either) within a method must first check if the returned Either is an error or not, before moving on to the next line. If it is an error, it is pushed back onto the method call stack in the form of an Aither. Each method on the stack also needs to check the reconfigured Either for the error, until finally we move on to the method that is responsible for handling the error. This results in very poorly structured Java code. I cannot write a normal java code stream as I have to "stop" at every api call (so streams are out of the question). eg

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 Either monadic methods (which I do), but that doesn't solve the basic problems of having to "ask" the return type if it's an error or a value. There are many more reasons why I think using both an error handling framework is not a good idea (long accounts, long methods, nested generics, etc.).

To get around this, I thought I might have thrown a specific exception for every api call that returns an "error". Or, and catch the exception once, on the top-level method in which it is currently working.

Value val = myService.getSomething().rightOrThrow(new MyException("blaa"));

      

but this is not possible, as the only method for any type of projection that does something similar is throwing a java error that is not designed to catch (almost) any circumstance (I may accidentally catch stackoverflow or outofmemory errors).

myService.getSomething().right().valueE("some error msg");

      

Any suggestions or thoughts?

thank

+3


source to share


2 answers


Back when I programmed in FJ I also briefly asked this problem. I quickly realized that using it Either

in this way was not very useful, and that more native constructs such as Exceptions

were much easier syntactically and of course better suited to the language.

I used Either

when it makes sense to make additional functions using functional methods (for example, 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 in languages ​​that support pattern matching.

Edit

As for how to throw the error, consider valueE , you can just write your own static version that throws whatever you like

+1


source


The best solution I have found for throwing an exception in case the returned Either is an error:

either.right.on(err -> {throw new MyException(err);})

      



or use a helper method to make it more readable:

 static <A> A willFailWith(String errorMsg) {
       throw new MyException(errorMsg);
 }
 either.right.on(err -> willFailWith(err))

      

0


source







All Articles