Skip to main content
Source Link
Karl Bielefeldt
  • 148.4k
  • 38
  • 284
  • 482

Nulls are problematic because they must be explicitly checked for, yet the compiler is unable to warn you that you forgot to check for them. Only time-consuming static analysis can tell you that. Fortunately, there are several good alternatives.

Take the variable out of scope. Way too often, null is used as a place holder when a programmer declares a variable too early or keeps it around too long. The best approach is simply to get rid of the variable. Don't declare it until you have a valid value to put in there. This isn't as difficult a restriction as you might think, and it makes your code a lot cleaner.

Use the null object pattern. Sometimes, a missing value is a valid state for your system. The null object pattern is a good solution here. It avoids the need for constant explicit checks, but still allows you to represent a null state. It is not "papering over an error condition," as some people claim, because in this case a null state is a valid semantic state. That being said, you shouldn't use this pattern when a null state isn't a valid semantic state. You should just take your variable out of scope.

Use a Maybe/Option. First of all, this lets the compiler warn you that you need to check for a missing value, but it does more than replace one type of explicit check with another. Using Options, you can chain your code, and carry on as if your value exists, not needing to actually check until the absolute last minute. In Scala, your example code would look something like:

val customer = customerDb getByLastName "Goodman"
val awesomeMessage =
  customer map (c => s"${c.firstName} ${c.lastName} is awesome!")
val notFoundMessage = "There was no customer named Goodman.  How lame!"
println(awesomeMessage getOrElse notFoundMessage)

On the second line, where we're building the awesome message, we don't make an explicit check if the customer was found, and the beauty is we don't need to. It's not until the very last line, which might be many lines later, or even in a different module, where we explicitly concern ourselves with what happens if the Option is None. Not only that, if we had forgotten to do it, it wouldn't have type checked. Even then, it's done in a very natural way, without an explicit if statement.

Contrast that with a null, where it type checks just fine, but where you have to make an explicit check on every step of the way or your entire application blows up at runtime, if you're lucky during a use case your unit tests exercise. It's just not worth the hassle.

Post Made Community Wiki by Karl Bielefeldt