views:

79

answers:

3

My application's persistence layer is formed by a Storage trait and an implementing class. I'm vacillating on this issue: should the fetchFoo(key: Key) methods should return Option[Foo], or should they throw FooNotFound exceptions if the key cannot be found?

To add flavour to the issue, the persistence layer - it is written in Scala - is called by Java code. Dealing with scala.Option in Java code? Hmmm.

In fact, until yesterday, the persistence layer was written in Java; I've just re-written it in Scala. As a Java code base, it relied on exceptions rather than returning nulls; but now that I've encountered scala.Option, I'm reconsidering. It seems to me that Scala is less enamoured of exceptions than Java.

+1  A: 

In Java, you can call Option's isEmpty, isDefined and get without any special hassle (the really useful Option methods, such as getOrElse, are another matter.) Checking the result of the isDefined method in an if-clause should be faster than checking exceptions in a try-catch block.

MJP
+3  A: 

My take on the general problem is that it depends on where the keys are coming from.

If they are being entered by some user or untrusted system, then I use Option so I can meaningfully denote the possibility of an unknown key and deal with it appropriately.

On the other hand, if the keys are coming from a known system (this includes things like keys embedded in links that originally came from the system), and are assumed to be valid and exist, I would leave it as a runtime exception, handled by a catch-all at the outer level. For the link example, if someone manually changes the key in a url for one reason or another, it should be considered as undefined behaviour and an exception is appropriate, IMO.

Another way to think of it is how you would handle the situation when it arises. If you're using Option and are just delegating the None case to some catch-all error handling, then an exception is probably more appropriate. If you're explicitly catching the NotFound exception and altering the program flow (eg, asking the user to re-enter the key), then use Option, or a checked exception (or Either in Scala) to ensure that the situation is dealt with.

In relation to integrating with Java, Option is easy enough to use from there once the Scala runtime library is available on the classpath. Alternatively, there's an Option implementation in the Functional Java library. In any case, I would steer clear of using null to indicate "not found".

Kristian Domagala
A: 

In some cases (like your example) an Option is fine and the "monadic" behavior (map, flatMap, filter...) very convenient, but in other cases you need more information about the cause of problem, which can be better expressed with an exception. Now you probably want your error handling as "uniform" as possible, so I would suggest to use Either, which gives you both a behavior similar to Option and an expressiveness like an exception.

In Java, you need just a helper function which "unpacks" an Either. If it finds a Right(value), it gives the value back, if it finds a Left(Exception), it re-throws it. After this, your back to normal Java behavior.

Landei