Be precise and not clever: Kotlin Null Handling

Bill Tsapalos
3 min readFeb 6, 2023

--

Back in 2009, Tony Hoare at a software conference apologized for inventing the null reference.

I call it my billion-dollar mistake. It was the invention of the null reference in 1965. At that time, I was designing the first comprehensive type system for references in an object oriented language (ALGOL W). My goal was to ensure that all use of references should be absolutely safe, with checking performed automatically by the compiler. But I couldn’t resist the temptation to put in a null reference, simply because it was so easy to implement. This has led to innumerable errors, vulnerabilities, and system crashes, which have probably caused a billion dollars of pain and damage in the last forty years.

Photo by Ben Hershey on Unsplash

The worst thing you can do to fix a mistake is to create tricky parts around it, instead of writing a very simple working solution.

The example

For this demonstration article we have to create an application that counts the letters in a String value and print the amount of the letters in console.

The sut will be the String value that we are going to count the letters it contains. If val sut = null it prints the errorMsg to the console. If val sut = abc2 it prints The item is: 3 which is also the expected output. But what if val sut = ""? It prints The item is: 0 and the errorMsg as well. Why it it enters in both code parts?

Kotlin scoped function for null

Kotlin has improved the handling of null a lot, but this does not mean that we should forget its existence. The only truth to understand what is happening behind the scenes in Kotlin is to read the decompiled bytecode, so let’s do this in this example.

The returned value of countLetters(sut) is var10000 which is checked explicitly if it is null or not. Continuing the reading we see that it also checks for nullability the returned value of printAndReturn() at if (printAndReturn(it) != null), so in case this value is not null it returns from main() function otherwise it proceeds to System.out.println(errorMsg);. In our case, the returned value of printAndReturn(it) is a null so it continues the execution instead of exiting main(). We have found our culprit, let’s proceed to the fix!

Before proceeding with the fix, there is something more important to mention. Imagine that the function printAndReturn() has no bad behavior, this means that you would not be able to find any issue at all. Let’s say that 6 months later a new developer is implementing a feature and puts a buggy printAndReturn() function there! Can you see the real problem?

Write your Kotlin for any Kotlin developer and not for Kotlin experts only!

Old school null handling

Here is the most simple and precise fix for this issue!

It is very simple to be written and even simpler to be read. It always should be simpler to be read because it is going to be written once, but it will be read a lot of times!

Keep improving

Now that we have fixed the null issue it is time to fix another code smell. We are returning Unit? from printAndReturn(), this means that we are returning either null or Unit. Explaining even further we returning one value or another! Every time we need to return one of two value it means that we need a Boolean. If there is any corner case scenario in which you need to return Unit? just refactor it to Boolean, not even Boolean?.

More

Do you want to see more refactoring/design ideas? Here is the table of contents.

--

--