Cleanup your Kotlin: Handling nullable reference
Kotlin programming language provides developers with expressive distinction of nullable types. Nevertheless, dealing with nullability can easily become awkward. Of course we don’t need to polute our code with unnecessary null checks, question marks or exclamation marks. Let’s see how to improve our codebase with a very little effort.
In order to make my code simple, readable and predictible I actually avoid nullable references. When I review my code, I even consider nullable types a code smell. Of course, this is not an absolute statement. There are definitely some cases when leveraging nullability is totally legit. More often than not however, the nullable types crawl their way into our codebase due to our negligence and we need to be ready to deal with it.
Don’t trust your IDE (that much)
Kotlin is build upon Java and Java types are implicitly nullable. This can oftentimes confuse your IDE (I use IntelliJ IDEA). Lets inspect the following snippet. It is a result of implement members action performed by IntelliJ IDEA for a common Java interface.
Can you reason why should the ActionEvent parameter in actionPerfomed function be nullable? Otherwise just remove that question mark manually. Don’t worry, your code will compile just fine.
Note that by removing the questionmark, you conciously declare your confidence, that the function will not be invoked with null value. There is no objective guarantee that it won’t happen in some edge case though. Kotlin would throw an exception in that case.
Adjust your data model
Does that data class really need to have a nullable property? Well, if you need to ask, there is a good chance that it doesn’t. Be especially careful about adding nullable properties to your existing classes.
Imagine some developer added lastSurveyAnswers property to an existing Customer data class. This property gets probably used only in very secluded part of an application, but Customer may very well be one of the core domain classes. Declaring data classes in Kotlin is so easy, that we should never be afraid to introduce new type, one actually fitting the use case of our developed feature.
Not every Customer is a SurveyParticipant. And that’s ok. Keep the responsibilites of your classes separate, do not add optional properties to your classes.
Filter the null values out
Kotlin provides a very clear and easy to use functions that can help us with filtering of collections with nullable values. Use them:
Actually this snippet may be even simplified:
Even better than filtering might be not letting the null values into the collection in the first place:
Safe call — lambda combination
Fine, now we know a trick or two on how to avoid nullable references, but I can assure you, that won’t be enough. You will encounter it again and again and sometimes, you will just have to live with it. Let me show you a neat trick with nullable object:
This works well with any Kotlin std. lib function (let, run, also, apply). Be wary though. Less experienced developers tend to be confused with these functions and use them sparsely. If you feel this is an issue, you can always fall back to Java-like variant:
The second snippet compiles thanks to a smart cast. When you are forced to deal with nullable and mutable variables (e.g.
var data: String? = null), the simple Java-like syntax won’t work unless you add additional question marks in your code.
Elvis to the rescue
?: is a Kotlin way to include an else branch to logic that may produce null midway. Whenever my code produces null value, I prevent it to leave the scope where it appeared. Elvis is an easy way how to do it.
Follow these 3 simple rules in this order to keep your Kotlin code clean of null values:
- Create your properties, variables and function parameters as not nullable by default. Avoid null as much as possible.
- Try to minimize the scope of nullable value as much as possible when it’s appearance is unavoidable.
- Learn Kotlin functions that remove null values from collections and use them frequently.
Kotlin is fun, so keep calm and keep coding!