Java | Scala | Ruby | Programming | Functional Programming Know Your Options August 4, 2014
Neil Chaudhuri (He/Him)

Neil Chaudhuri (He/Him)

LinkedIn Neil Chaudhuri (He/Him)

Imagine a method in Java that retrieves an Employee entity from the database by the employee id. Something like this:

public Employee findById(String id) {
// Try to find an Employee
}

That’s pretty straightforward. You’ve probably written hundreds of methods like this one. The problem is what to do if there is no employee with that id. Java developers usually consider two options for this scenario:

Sure, you could also apply the Null Object Pattern, but no one ever does that.

Throwing a checked exception has one huge advantage. It explicitly alerts you to the possibility you won’t find an employee with the id, and the compiler forces you to deal with that possibility by either kicking the can down the road with a rethrow or by catching the exception. The problem is that using exceptions to regulate flow control is generally considered a bad idea.

On the other hand, returning null implies using a conditional statement for flow control, which is preferred. The problem is that null is basically the worst thing ever. Even the guy who invented it thinks so. For details on why null is basically the worst thing ever, check out what the Google Guava team has to say about it.

Various languages address the issues with null in different ways. Ruby, for example, has nil, which is a singleton instance of NilClass, which can be monkey-patched in clever ways to mitigate some of those issues.

A much cleaner, more sophisticated approach is to use the concept of optional types, which is sort of utilized in Guava and has its origins in mathematical type theory and functional programming languages like Haskell and Scala, where I was first introduced to the concept. Since then, Scala’s Option type has become one of my favorite features of the language.

Let’s go back to our original example. In Scala, it would probably look like this.

def findById(id: String): Option[Employee] = {
// Return an Employee effect
}

Check out that Option[Employee] return type. The Option type has a rigorous definition, but as a practical matter, think of it as a one-item collection. If we find an employee with the given id, the collection contains the corresponding Employee instance. If we don’t, the collection contains a singleton—similar to Ruby’s nil and some applications of the Null Object Pattern.

Some and None are instances of Option. So more precisely, when we find an employee, our method returns an instance of Some[Employee]. When we don’t, our method returns None.

What’s the big deal? Two things.

First, just like with the exception approach, we have a compile-time mandate to account for both possibilities. There is no chance we will be caught by surprise at runtime and slow down our development cycle. But this compile-time checking is accomplished with type safety rather than a problematic exception.

Second, and even better, the caller’s code is really clean. You could call our method like this:

val employeeName = findById("123")
  .map(employee => employee.getName)
  .filter(name => name.length != 0)
  .getOrElse("Unknown")

If you have worked with Scala collections before, you’ll notice how similar it is to use Option. In this case, if findById returns Some, the map call extracts the Employee instance “inside” the Some, and you can do whatever you want with it. Here we get the employee’s name in the map call and run the name through a filter to make sure it isn’t blank. If it isn’t, the employee’s name is stored in the variable. The getOrElse call never happens.

However, if findById returns None, the map and filter calls never happen, and getOrElse handles this alternate flow. In fact, getOrElse executes when any method along the call chain returns None. So if there is an employee with given id but the name is blank, map returns Some but filter returns None, and getOrElse does its thing in this case as well.

All scenarios are accounted for, and the code is elegant and pretty easy to follow if you are comfortable with actual collections. You can even use flatMap if you have Option’s within Option‘s. That’s cool.

Hopefully now you know why I love Option so much. Even if you don’t program in Scala, you can think differently about your code no matter which language you use. For much more on Option, check out Daniel Westheide’s outstanding post on the topic.