Friday, March 4, 2011

In my opinion, a responsibility of exceptions handling is a part of a business logic and enforcing a developer to process them on each layer adds inevitable problems that decrease a value gained from using exceptions. So to move an exception handling from a time when the exception occurred to a point where we need to extract a value Scala developers often use Option or Either classes instead of try/catch block. It unburdens unrelated intermediate methods from dealing with an exception and make it possible to pass such functions without any additional notations. However, this classes do not reflect the usage intention, so I propose a solution which will be more readable and at the same time less verbose.



object Exceptionable {

sealed abstract class Exceptionable[+A, +E] {

def isSuccess = this match {
case Success(_) => true
case Failure(_) => false
}

def isFailure = !isSuccess

def success = this match {
case Success(a) => Some(a)
case Failure(_) => None
}

def failure = this match {
case Success(_) => None
case Failure(e) => Some(e)
}

}

implicit def resultToSuccess[A](result: A) = Success(result)

final case class Success[A, E](a: A) extends Exceptionable[A, E]
final case class Failure[A, E](e: E) extends Exceptionable[A, E]
}

Demo:

import Exceptionable._

def divide(a: Int, b: Int): Exceptionable[Int, String] = {
if (b != 0) a/b else Failure("Negative value")
}

def main(args: Array[String]) = {
divide(10, 4) match {
case Success(a) => ...
case Failure(message) => ...
}
}