Exception handling in scala - scala

I am working on an application with Scala. I am trying to implement Exception Handling in the application. I tried using Either for handling the exceptions. For simple cases, it seems to be enough to handle exceptions. However, when I need to get results from multiple tables by joins, the exception handling is creating more issues than solving. My application structure is explained below:
Using repository pattern for the database operations which defines all the database interaction operations. For eg, I have a central repository which defines findAll, findById, insert, delete, update, exists etc. My findAll methods signature has been changed to Either[CustomException, List[TEntity]], similarly findById methods type is Either[CustomException, Option[TEntity]].
Now assume that, If I need to fetch employees from database in my method, i will be doing something like below :
def getVehicleById(id:Long) = {
val vehicle = repository.findById(id)
//i have one-to-one mapping with Employee table for the driver of the vehicle
val driver = empRepository.findById(vehicle.driverId)
}
Now the type of vehicle will be Either[CustomException, Option[Vehicle]] and type of driver is Either[CustomException, Employee]
If i need to do any more operation after getting the results, i have to use case Right/Left and then do that. The problem is that, may be inside the Right case, I might need to join with another table, which makes the result of that as again Either[CustomException, Entity]. if any error occurs in that operation, i need to again use try catch block.
I feel that this kind of hanling becomes very difficult to manage when the code complexity increases, and also I will have a lot of boiler plate code to handle these situations, which goes against Scala principle itself.
So my question is, how can I handle exception in a better way without much boiler plate code.
Note : I am coming from a Java background, have been working on Scala only for a couple of months now.
EDIT
Adding Sample Code with Try :
This sample is very close to the requirement I have.
import scala.util._
def checkTry:Try[List[Int]] = Success(List(2))
def checkTryStr:Try[String] = Success("Asd")
def getVehicleWithDriver = for {
a <- checkTry
c <- a
b <- checkTryStr
}yield {
(c,b)
}
getVehicleWithDriver
But with the bove code, I am getting compilation errors.
Error:(9, 6) type mismatch;
found : scala.util.Try[(Int, String)]
required: scala.collection.GenTraversableOnce[?]
b <- checkTryStr
^
Error:(9, 6) type mismatch;
found : scala.util.Try[(Int, String)]
required: scala.collection.GenTraversableOnce[?]
b <- checkTryStr
^
Error:(8, 6) type mismatch;
found : List[Nothing]
required: scala.util.Try[?]
c <- a
^

You want to use the for/yield sugar. You can either get in the habit of putting .right on all your Eithers, or as #Gangstead suggests, use \/ from Scalaz. (There are certainly scary parts of Scalaz - I've been using it for 4 years and am still intimidated by e.g. Strength - but it's perfectly possible to start with the easy parts and work your way up).
for {
vehicle <- repository.findById(id).right
driver <- empRepository.findById(vehicle.driverId).right
somethingElse <- somePossiblyFailingComputation.right
} yield somethingElse
//Don't need the .right if you're using Scalaz \/
Other vital hints: when you want to apply an effectful function to a List, you want to use Scalaz traverse:
vehicleList <- vehicleIdList.traverse(repository.findById) //assuming you're using \/
//might need a few .right if you're using Either
When you're calling Java code that might throw an exception, use scala.util.control.Exception's catching:
val myEither = catching(classOf[SomeException]) either someJavaMethodThatThrows()
// (...).disjunction if you're using \/.
If you need to work with another kind of "effectful context" at the same time as working with Either/\/, you'll have to start looking at monad transformers, but it might be best to get comfortable with just Either first.
Hope that helps; best of luck, hope you like Scala.

Take a look at Scalaz's disjunction \/.
A warning: Scalaz is hardcore scala written by hardcore guys.
Take a look at Brendon McAdams' (#Rit) presentation about "Scalaz' Gateway Drugs". He's much more approachable for programmers coming from Java, and he keeps it very practicall

You want to use Try, not Either. It is a monad, so you can map or flatMap it, or use it in a for comprehension. It looks pretty elegant actually.
def getVehicleWithDriver(id: String): Try [(Vehicle, Driver)] = for {
vehicle <- repository. findById(id)
driver <- empRepository.findById(vehicle.driverId)
} yield {
(vehicle, driver)
}

Related

Check the runtime type of Scala class instance

If I run the following code, then I get an error:
import scala.reflect.ClassTag
class General {
}
class SubGeneral extends General {
def test() = println("tested")
}
class ProGeneral[T <: General: ClassTag] {
var array = Array.ofDim[T](3, 3)
def funcForSubGeneral(): Unit =
if (array(0)(0).isInstanceOf[SubGeneral]) then array(0)(0).test()
}
That is because General does not have the function test().
I know that I can fix this with pattern matching. This instead of the above funcForSubGeneral() works:
def funcForSubGeneral(): Unit =
array(0)(0) match {
case s: SubGeneral => s.test()
case _ => println("nope")
}
But I was wondering if it is possible to get the runtime type of array(0)(0) and check if it is a SubGeneral, and if that is the case then I call test(), which shouldn't cause a problem?
That is what I was actually trying by using isIntanceOf. I want to omit pattern matching since I'm just interested in one type.
isInstanceOf doesn't change anything, you would need to do array(0)(0).asInstanceOf[SubGeneral].test() in order to force the casting.
Note that the casting may fail at runtime, so that is why you need to check with the if before. Thus the end code looks like this:
if (array(0)(0).isInstanceOf[SubGeneral]) then array(0)(0).asInstanceOf[SubGeneral].test()
But, since this is cumbersome and error-prone, we have pattern matching:
array(0)(0) match {
case subGeneral: SubGeneral => subGeneral.test()
}
However, note that type tests are considered a bad practice; mainly because they are actually class checks and may fail certain circumstances. For example:
List("a", "b", "c") match {
case numbers: List[Int] => numbers.head + 1
}
Will throw an exception in runtime since, due to type erasure, we lost the [String] part and it matches only List then it tries to read the first element as an Int which is an error.
Anyways, this is the fourth time in two days you ask a question that shows bad practices and unidiomatic code.
My advice:
I would bet you are not following an appropriate resource to learn the language. Rather, it seems you are just trying to mimic another language (Python?) with different syntax. - Thus, I encourage you to pick an appropriate book, course, tutorial, etc; that properly introduces the language and its idioms.
I would encourage you to join the official Discord server which is more suitable for newcomers than StackOverflow.
I would recommend you to explain the meta-problem you are trying to solve in detail (either here in a new question or in the Discord server), I am pretty sure there are better and more idiomatic ways to solve it.

Is returning Either/Option/Try/Or considered a viable / idiomatic approach when function has preconditions for arguments?

First of all, I'm very new to Scala and don't have any experience writing production code with it, so I lack understanding of what is considered a good/best practice among community. I stumbled upon these resources:
https://github.com/alexandru/scala-best-practices
https://nrinaudo.github.io/scala-best-practices/
It is mentioned there that throwing exceptions is not very good practice, which made me think what would be a good way to define preconditions for function then, because
A function that throws is a bit of a lie: its type implies it’s total function when it’s not.
After a bit of research, it seems that using Option/Either/Try/Or(scalactic) is a better approach, since you can use something like T Or IllegalArgumentException as return type to clearly indicate that function is actually partial, using exception as a way to store message that can be wrapped in other exceptions.
However lacking Scala experience I don't quite understand if this is actually viable approach for a real project or using Predef.require is a way to go. I would appreciate if someone explained how things are usually done in Scala community and why.
I've also seen Functional assertion in Scala, but while the idea itself looks interesting, I think PartialFunction is not very suitable for the purpose as it is, because often more than one argument is passed and tuples look like a hack in this case.
Option or Either is definitely the way to go for functional programming.
With Option it is important to document why None might be returned.
With Either, the left side is the unsuccessful value (the "error"), while the right side is the successful value. The left side does not necessarily have to be an Exception (or a subtype of it), it can be a simple error message String (type aliases are your friend here) or a custom data type that is suitable for you application.
As an example, I usually use the following pattern when error handling with Either:
// Somewhere in a package.scala
type Error = String // Or choose something more advanced
type EitherE[T] = Either[Error, T]
// Somewhere in the program
def fooMaybe(...): EitherE[Foo] = ...
Try should only be used for wrapping unsafe (most of the time, plain Java) code, giving you the ability to pattern-match on the result:
Try(fooDangerous()) match {
case Success(value) => ...
case Failure(value) => ...
}
But I would suggest only using Try locally and then go with the above mentioned data types from there.
Some advanced datatypes like cats.effect.IO or monix.reactive.Observable contain error handling natively.
I would also suggest looking into cats.data.EitherT for typeclass-based error handling. Read the documentation, it's definitely worth it.
As a sidenote, for everyone coming from Java, Scala treats all Exceptions as Java treats RuntimeExceptions. That means, even when an unsafe piece of code from one of your dependencies throws a (checked) IOException, Scala will never require you to catch or otherwise handle the exception. So as a rule of thumb, when using Java - dependencies, almost always wrap them in a Try (or an IO if they execute side effects or block the thread).
I think your reasoning is correct. If you have a simple total (opposite of partial) function with arguments that can have invalid types then the most common and simple solution is to return some optional result like Option, etc.
It's usually not advisable to throw exceptions as they break FP laws. You can use any library that can return a more advanced type than Option like Scalaz Validation if you need to compose results in ways that are awkward with Option.
Another two alternatives I could offer is to use:
Type constrained arguments that enforce preconditions. Example: val i: Int Refined Positive = 5 based on https://github.com/fthomas/refined. You can also write your own types which wrap primitive types and assert some properties. The problem here is if you have arguments that have multiple interdependent valid values which are mutually exclusive per argument. For instance x > 1 and y < 1 or x < 1 and y > 1. In such case you can return an optional value instead of using this approach.
Partial functions, which in the essence resemble optional return types: case i: Int if i > 0 => .... Docs: https://www.scala-lang.org/api/2.12.1/scala/PartialFunction.html.
For example:
PF's def lift: (A) ⇒ Option[B] converts PF to your regular function.
Turns this partial function into a plain function returning an Option
result.
Which is similar to returning an option. The problem with partial functions that they are a bit awkward to use and not fully FP friendly.
I think Predef.require belongs to very rare cases where you don't want to allow any invalid data to be constructed and is more of a stop-everything-if-this-happens kind of measure. Example would be that you get arguments you never supposed to get.
You use the return type of the function to indicate the type of the result.
If you want to describe a function that can fail for whatever reason, of the types you mentioned you would probably return Try or Either: I am going to "try" to give your a result, or I am going to return "either" a success or an failure.
Now you can specify a custom exception
case class ConditionException(message: String) extends RuntimeException(message)
that you would return if your condition is not satisfied, e.g
import scala.util._
def myfunction(a: String, minLength: Int): Try[String] = {
if(a.size < minLength) {
Failure(ConditionException(s"string $a is too short")
} else {
Success(a)
}
}
and with Either you would get
import scala.util._
def myfunction(a: String, minLength: Int): Either[ConditionException,String] = {
if(a.size < minLength) {
Left(ConditionException(s"string $a is too short")
} else {
Right(a)
}
}
Not that the Either solution clearly indicates the error your function might return

scala programming practice with option

May be my design is flawed (most probably it is) but I have been thinking about the way Option is used in Scala and I am not so very happy about it. Let's say I have 3 methods calling one another like this:
def A(): reads a file and returns something
def B(): returns something
def C(): Side effect (writes into DB)
and C() calls B() and in turn B() calls A()
Now, as A() is dependent on I/O ops, I had to handle the exceptions and return and Option otherwise it won't compile (if A() does not return anything). As B() receives an Option from A() and it has to return something, it is bound to return another Option to C(). So, you can possibly imagine that my code is flooded with match/case Some/case None (don't have the liberty to use getOrElse() always). And, if C() is dependent on some other methods which also return Option, you would be scared to look at the definition of C().
So, am I missing something? Or how flawed is my design? How can I improve it?
Using match/case on type Option is often useful when you want to throw away the Option and produce some value after processing the Some(...) but a different value of the same type if you have a None. (Personally, I usually find fold to be cleaner for such situations.)
If, on the other hand, you're passing the Option along, then there are other ways to go about it.
def a():Option[DataType] = {/*read new data or fail*/}
def b(): Optioon[DataType] = {
... //some setup
a().map{ inData =>
... //inData is real, process it for output
}
}
def c():Unit = {
... //some setup
b().foreach{ outData =>
... //outData is real, write it to DB
}
}
am I missing something?
Option is one design decision, but there can be others. I.e what happens when you want to describe the error returned by the API? Option can only tell you two kinds of state, either I have successfully read a value, or I failed. But sometimes you really want to know why you failed. Or more so, If I return None, is it because the file isn't there or because I failed on an exception (i.e. I don't have permission to read the file?).
Whichever path you choose, you'll usually be dealing with one or more effects. Option is one such effect which representing a partial function, i.e. this operation may not yield a result. While using pattern matching with Option, as other said, is one way of handling it, there are other operations which decrease the verbosity.
For example, if you want to invoke an operation in case the value exists and another in case it isn't and they both have the same return type, you can use Option.fold:
scala> val maybeValue = Some(1)
maybeValue: Some[Int] = Some(1)
scala> maybeValue.fold(0)(x => x + 1)
res0: Int = 2
Generally, there are many such combinators defined on Option and other effects, and they might seem cumbersome at the beginning, later they come to grow on you and you see their real power when you want to compose operations one after the other.

Monad transformer in Scala for comprehension to handle Option and collect error messages

I've been looking at a lot of Scala monad transformer examples and haven't been able to figure out how to do what I think is probably something straightforward. I want to write a for comprehension that looks up something in a database (MongoDB), which returns an Option, then if that Option is a Some, looks at its contents and gets another Option, and so on. At each step, if I get a None, I want to abort the whole thing and produce an error message like "X not found". The for comprehension should yield an Either (or something similar), in which a Left contains the error message and a Right contains the successful result of the whole operation (perhaps just a string, or perhaps an object constructed using several of the values obtained along the way).
So far I've just been using the Option monad by itself, as in this trivial example:
val docContentOpt = for {
doc <- mongoCollection.findOne(MongoDBObject("_id" -> id))
content <- doc.getAs[String]("content")
} yield content
However, I'm stuck trying to integrate something like Either into this. What I'm looking for is a working code snippet, not just a suggestion to try \/ in Scalaz. I've tried to make sense of Scalaz, but it has very little documentation, and what little there is seems to be written for people who know all about lambda calculus, which I don't.
I'd "try" something like this:
def tryOption[T](option: Option[T], message:String ="" ):Try[T] = option match {
case Some(v) => Success(v)
case None => Failure(new Exception(message))
}
val docContentOpt = for {
doc <- tryOption(mongoCollection.findOne(MongoDBObject("_id" -> id)),s"$id not found")
content <- tryOption(doc.getAs[String]("content"), "content not found")
} yield content
Basically an Option to Try conversion that captures the error in an exception. Try is an specialized right-biased Either that is monadic (in contrast to Either, which is not)
Try may be what you're looking for, but it's also possible to do this using the "right projection" of the standard library's Either:
val docContentOpt: Either[String, String] = for {
doc <- mongoCollection.findOne(MongoDBObject("_id" -> id)).toRight(
s"$id not found"
).right
content <- doc.getAs[String]("content").toRight("Can't get as content").right
} yield content
This may make more sense if your error type doesn't extend Throwable, for example, or if you're stuck on 2.9.2 or earlier (or if you just prefer the generality of Either, etc.).
(As a side note, it'd be nice if the standard library provided toSuccess and toFailure methods on Option that would make converting Option into Try as convenient as converting Option into Either is here—maybe someday.)
(And as another side note, Scalaz doesn't actually buy you much here—it would allow you to write .toRightDisjunction("error") instead of .toRight("error").right, but that's about it. As Gabriel Claramunt points out in a comment, this isn't a case for monad transformers.)

Why is Scalas Either not a monad?

I'm interested in knowing the design decisions why scala.Either was not done as a monad. There already exists some discussion on how to right-biasing Either, for example:
right-biasing Either
fixing Either
Fixing scala.Either - unbiased vs biased
But there are mentioned too much details and I couldn't get an complete overview about why it is done as it is done. Can someone give an overview about the benefits of having a right-biased Either, about the problems to do it that way and about the benefits of not having an right-biased Either (if they even exist)?
I think it just comes down to the Principle of Least Astonishment. Using Either to encode success or failure is clearly something people do, but it is not the only use of Either. In fact, there is not much reason to have Right be success and Left be failure other than tradition. As adelbertc's comment above mentions, scalaz has Validation which specifically encode this.
To further justify the POLA claim above, take this code:
def foo(): Either[Int, Int] = Right(1)
def bar(j: Int): Either[Int, Int] = Left(1)
def baz(z: Int): Either[Int, Int] = Right(3)
// Result is Left(1)
for (a <- foo().right; b <- bar(a).right; c <- baz(b).right) yield c
This compiles because I am using the .right projection in the for expression. It makes sense here the Left(1) in bar is the failure case and so that is the result, but imagine if Either was Right-biased. The above code would compile without the .right projections in the expression like:
for (a <- foo(); b <- bar(a); c <- baz(b)) yield c
If you used Either in your code to just be a "one-or-the-other" type, you would be surprised by (1) the fact that this would compile and (2) that it returns Left(1) and seemingly never executes baz.
In summary, use Validation if you want to use Either to encode success or failure.
I don't know if this was the original reason, but there is at least one good reason. In Scala, for comprehensions require more from the argument than that it is a monad in order to gain full functionality. In particular, there are constructs like
for (a <- ma if a > 7; /*...*/) yield /*...*/
which require that the monad be a monad-with-zero (so you can empty it if the condition fails).
Either cannot sensibly be a monad-with-zero (save for Either[Unit,B], where Left(()) can be the zero).
One way to go is to say: okay, fine, just don't use your for-comprehensions that way. Another way to go is to say: okay, fine, don't bother making Either a monad at all. It's a matter of personal preference, of course, but I can see a certain lack of elegance in having Either (uniquely among the common monads provided in Scala) fall flat on its face once you try to use the full power for gives you.