Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Correct usage of Either, Try and Exceptions/ControlThrowable in scala

In my scala code (libraries as well as applications) I currently use a mixture of Option and Try, whenever either of both feels more apropriate.

I tend to implement "doSomething"-methods which can succeed with a return value or with a failure with Try. That is, they can contain code which throw, or, when I detect errors "by hand", I artificially create a Throwable and return a Failure. The return value of those methods hence is a Try[ReturnType].

Now I read that creating exceptions is somewhat suboptimal, because it creates a stack trace (and hence is slow), which I don't even need. I also saw examples using a subclass of ControlThrowable, which don't create a stack trace, however they also don't have a message, and Try of course won't catch it.

Now my concrete question would be, should I generally favour Either over Try when I want to do runtime error-handling / method return values, and use Try only in situations where I actually need to catch something (e.g. thirdparty code)?
That way I would not have to create clumsy Throwables, but instead only use e.g. strings in Left for errors.

So basically:

  • Option: every day usage for something which plain has a value or not
  • Try: catching exceptions within methods, but not used as return value
  • Either: universal return value, containing error (string) or success value

Would this concept work out well, or is there a more viable/common approach?

like image 735
user826955 Avatar asked Feb 13 '19 07:02

user826955


People also ask

How do you handle exceptions in Scala?

try/catch/finally A basic way we can handle exceptions in Scala is the try/catch/finally construct, really similar to the Java one. In the following example, to make testing easier, we'll return a different negative error code for each exception caught: def tryCatch(a: Int, b: Int): Int = { try { return Calculator.

What is try in Scala?

The Try type represents a computation that may either result in an exception, or return a successfully computed value. It's similar to, but semantically different from the scala. util. Either type. Instances of Try[T] , are either an instance of scala.


1 Answers

As Travis Brown has stated in the comments, there is no real convention and it is largely a cultural thing. Consistency is the most important thing here in order to keep your code readable. I've seen codebases which:

  • Use Options to mean "None is a success and any Some(...) contains the error message"
  • Use Try in order to return either a Success containing an empty String or a Failure containing the error message
  • Use Either the wrong way around (ie Either[?, Throwable])

Obviously these aren't good practices, but as long as you're consistent it doesn't really matter. The convention I personally use both recreationally and at work is:

  • Option for when it's valid for a value to be missing (eg when parsing JSON using playframework).
  • Try when attempting to do something that might fail (unless it's in a Future, in which case I just use .recover), where I care about matching the type of exception but also want the result of the Success where available.
  • Either when I don't want to return an Exception/Throwable in my "fail" case (though to be honest this is rare).

Regardless of which of the above I use, I personally think it's best keep it wrapped up for as long as possible. This stops unnecessary Throwables being thrown (haha) around in your code, and makes debugging easier as there aren't any hidden getOrElse lines returning default values (this can get very annoying in large codebases).

like image 64
James Whiteley Avatar answered Sep 23 '22 06:09

James Whiteley