Real Life Bug Prevention in Scala

Using Scala for the last 5 years to run eventsofa I’ve became a better programmer creating less bugs. Most of the code is Java++ Scala compared to more canonical functional Haskell-like Scala. So I’m interested how Scala used in this way prevents bugs that I would make in Java, Python or Ruby.

There have been two things that made a huge impact, Options and tagged types.

Lets explore both concepts with a small example:

Option vs. Null

How does one signal that there is no invoice or there is no user? In Java this is often done with Null or throwing some kind of InvoiceNotFoundException. With Nulls for error handling (Some Thoughts on Error Handling) code looks like this

Code with exceptions would look similar. This code is noisy and because developers are not forced to check for Null, sometimes developers do not test for error conditions signaled with Null. The result are hard to find NullPointerExceptions (I also blame you Java, for not printing more information in NPEs, take a look at Elm!)

In Scala one would use Option type to signal that there is no user, with returning Some(User) if a user was found and None if there wasn’t.

Code using Option does not need to check for the result type of the method call and split the code path depending on success and error as with Null. One code path is used for both the error and the success case. Error handling can be deferred to a later point and errors can be accumulated.

or

For cleaner syntax Scala provide for sugaring which expands to the code above, but is easier to read

In Scala it’s easy to compose Options compared to composing Nulls – which don’t compose. Also the code is easier to read with less noise, especially the for version is easy to understand even with more complex dependencies. Code that is easy to read and easy to understand results in less misunderstandings and less bugs. This way error handling is improved as developers do write more and better error handling code. From my experience with Scala the usage of Option instead of Null or Exceptions leads to a lot less lazyness bugs.

Tagged Types

The usage of String for accountNumber and userId is problematic.

For developers it’s hard to understand how these Strings look like or how to get or create a correct one. There might be different userIds in different String formats and it is easy to plug the wrong userId formatted String into a method. The same object might have different names in different method signatures like id, userId, or user. A little bit more nuanced the problems shines in

If you find this code, your first thought is “What is percentage?”. To represent 11.5% the Float value could be 11.5 or 0.115. This has biten me in the past when I’ve assumed 10% percent for a coupon was represented by 0.10. As a result millions of users got mails with coupons with a value 0.10% because the developer of that method represented 10% with 10.0.

Where this also rears its head is with money.

First Once and for all: Do not use double for money, second is this a Netto or Brutto amount? A bug I’ve seen several times is when variables representing netto amounts are plugged into methods expecting brutto amounts.

The classic approach would be to create abstract data types (ADTs), classes, case classes or data types classes (Value Objects).

The downside with this is (Never, never, never use String in Java (or at least less often :-)) and the reason developers don’t use this often enough: developers need to write more code plus Percentage is harder to understand, to reuse and to calculated with than Float. I can plug in Float into more methods than Percentage.

In Scala I’m using Tagged Types instead of case classes her

These have several benefits. It’s easy to see that Percentage is a Float, creation can be documented (10% represented by 0.10) and controlled plus the API is easier to read. All of this leads to less misunderstandings and from my experience therefor to less bugs.

Other examples are

Tagged types have made my code much better than before.

How about other Scala features to prevent bugs? As I am writing server side, request isolated code, immutable data structures didn’t help to prevent concurrency bugs in the last years. My only concurrency is fire and forget usage of actors for logging, database side effects, sending mails etc. Limited concurrency is used to get data from different data sources, neither of these use cases share data though.

Sealed traits have helped with checking if switch statements are exhaustive, especially in larger code bases this helps when adding new features. Case classes prevented hashcode bugs as they generate correct hashcode methods by themselves.

All in all my Scala code has a reduced level of bugs due to some Scala features compared to my code in Java, Ruby or Python. Any new language I am using would need to support both Option and tagged types.

“For” hack with Option monad in Java

There has been some discussion going on in the blogosphere about monads, and especially about the Haskell Maybe monad or the Scala option class. Those are ways to prevent problems with NULL and NPEs that Java lacks. Java returns NULL form many methods to indicate failure or no result. Suppose we have a method which returns a name:

The problem with this method is that we don’t know if it returns null. So the developers needs to deal with length == null, though the compiler doesn’t force the developer to deal with the returned NULL. A lazy developer then leads to null pointer exceptions. Other languages deal in different ways with this problem. Groovy has safe operators and Nice has option types.

Some posts like the one from James show how to use options in Java. All have the problem that you need to unwrap the value inside the option / maybe. Scala ans Haskell do that automatically for you, with the case classes in Scala for example.

But there is a construct with syntactic sugar in Java which unwraps the value from inside another class: the for loop from Java 1.5.

To make this work we need our option class to implement Iterable.

And the None and Some sub classes to return an empty iterator

or an iterator with one item.

Then voila Java does the unwrapping for us and instead of

we can write (sacrificing the else):

Thanks for listening.

Update: Completely ignoring the point of this post, Euxx posted a correction for the single element list creation I did.

Happens all the time in IT, people missing the point but nitpicking on something irrelevant. Other than that, if we start arguing performance, “The java.util.Collections class also have number of other utility methods that allow to shorten code like this and help to improve performance of your application.” I’d write (or reuse) a OneElementIterator something like this (could probably be optimized with some further thinking)

(Or again using google collections)

“I can’t not notice the ugly use of ArrayList to create collection with a single element, but what made matter worse, is that author suggested to use 3rd party library to replace those 3 lines of code.”

As far as I know, the JDK does not help you very much with Iterators or Iterables as third party libraries do. So, yes, I’d suggest using a third party library to implement an Iterator/Iterable for Option.