How Kotlin became our primary language for Android

A couple of months ago our team decided to try something new: develop a commercial application entirely in Kotlin, a new programming language by JetBrains. Previously we had experience with Kotlin, but on a much smaller scale: converting some parts of apps to a new language or trying it on pet projects. However, developing a commercial application in a new programming language introduces some difficulties:

  • We were deeply rooted in Java-based Android development. Switching to Kotlin was rather difficult, especially for developers without prior functional programming experience
  • Some stuff just doesn’t work. Dagger did not work well from out of the box

All that may lead to missed delivery dates and stability issues of the application.

One should have strong incentives to make the transition. Our incentive was the belief that Kotlin would be the game changer for the Android Platform development. And that it’s Fun.


Keeping the Kotlin reference open, we started to develop the Voter application. Kotlin is a JVM language with 100% Java interoperability, and if you’re familiar with Java, learning Kotlin is easy. However, if you want to fully take advantage of the language, understanding functional programming concepts is essential.

Learning Functional Programming takes a while. So be patient.

And Functional Programming is not easy. At least in the beginning. Until it becomes fun. I strongly advise to take a set of courses by Martin Ordersky “Functional Programming in Scala”. Scala can be overwhelming at times, but it gives a great overview of the new functional programming mindset. You can treat Kotlin as a simpler version of Scala.

What made us turn to the Kotlin side

Functional programming style

Kotlin is 100% interoperable with Java. Also, Kotlin is a functional language. And the latter allows writing more elegant, expressive code.

  1. Function purity

The concept of a pure function (a function that does not have side effects) is the most important functional concept which allowed us to greatly reduce code complexity and get rid of most mutable states.

In Imperative Programming Languages such as Javascript, Java, and C#, Side Effects are everywhere. This makes debugging very difficult because a variable can be changed anywhere in your program. So when you have a bug because a variable is changed to the wrong value at the wrong time, where do you look? Everywhere? That’s not good.

Note that how we manipulate data without changing its content.

2. Higher-order functions

Higher-order Functions either take functions as parameters, return functions or both.

Higher-order functions are everywhere. You just pass functions to collections to make code easy to read. titles.map { it.toUpperCase()} reads like plain English. Isn’t it wonderful?

Let’s imagine a situation where we want to count the number of unread messages of different types. A typical approach would be:

As you can see, as new requirements are introduced, the code becomes unreadable and unmanageable. Let’s see how we can solve this problem with higher-order functions:

And we can imagine use cases where we would want to parametrize the fold function argument, let’s say, for calculating the product of unread messages.

Another example of using higher-order functions is replacing numerous Listeners with simple higher-order function:

BillingView : LinearLayout {
var billingChangeListener: (() -> Unit)? = null
...
}
... // in an activity far, far away
billingView.billingChangeListener { updateUI() }

3. Immutability
Immutability makes it easier to write, use and reason about the code (class invariant is established once and then unchanged). The internal state of your app components will be more consistent. Kotlin enforces immutability by introducing val keyword as well as Kotlin collections, which are immutable by default. Once the val or a collection is initialized, you can be sure about its validity. (See UPD for more accurate definition on val keyword).

data class Address(val line1: String, val city: String)
val items = listOf(Address("242 5th St", "Los Angeles"),   Address("Dovzhenka St. 5", "Kiev"))

Null-safety

This language feature made us think carefully about nullability of fields in our model classes. Previously, you were not sure whether field in DTO is initialized or not, @Nullable and @NotNull annotations helped, but not as much. Now, with Kotlin, you precisely know what field can be null, what field is are initialized later (e.g. fields injected by Dagger) and you get strict control over those fields. Result? Almost no NullPointerExceptions. (Internally we call ?. a “goose” operator, because it looks like a goose’s neck)

brand?.let { badge.enabled = brand.isNewBadge }
// Can also be written as
badge.enabled = brand?.isNewBadge?:false

Anko

Anko DSL is a great library which significantly simplifies working with views, threads, and android lifecycle. The Github description states that Anko is “Pleasant Android application development” and it truly proved to be so.

Note that when uiThread is called inside Activity, the block will not execute if isFinishing is true . We do not actually use this feature, as RxJava handles all the threading in our apps, but it is a nice feature.

Using Anko instead of XML. Although Anko is not ready to replace standard Android UI building, sometimes it is very handy.

As you can see, Anko DSL allows you to use custom views alongside Android built-in views. This is where it has a great advantage over standard XML.

Kotlin Android extensions: Removing ButterKnife dependency

Bored yet? I bet you scrolled that without reading. In Kotlin, you don’t need any of those. You can just reference your view property by its @id XML parameter, those properties would have the same name as declared in your XML file. More info can be found in official docs.

Other neat features

  1. Extension functions & Builders

apply, let, and extension functions can be easily used to create elegant builders.

2. A quick hack for beginners
During the first couple of days, you often stumble upon a problem: you don’t know how to write a rather simple Java expression in Kotlin. 
A simple trick is to write a piece of code in Java and then paste it into a Kotlin file. Thanks to guys in JetBrains, it gets automatically converted to Kotlin. Hacky, but works like a charm!

3. Getting rid of unnecessary dependencies
Kotlin replaces a lot of third-party libraries, such as ButterKnife, Google Autovalue, Retrolambda, Lombok and some of the RxJava code.

Summary

As a software development team, the main challenge we have is delivering great products and being effective at getting the job done. Although to start developing effectively in Kotlin you need some prerequisite knowledge of functional programming, investing time to learn it really pays off. I believe Kotlin is a major improvement over conventional Android development, which allows us to deliver great apps on time, and with MUCH fewer bugs.

Feel free to ask questions, we will be grad to help others make the transition. Share your thoughts / comments below!

Programming is the most fun you can have with your clothes on.
John Guttag

UPD: val does not actually mean ‘immutable’, but rather ‘read only’. See this article for details.

References

  1. Kotlin Reference
  2. So You Want to be a Functional Programmer
  3. Why Functional Programming Matters
  4. 6 Benefits of Programming with Immutable Objects in Java
  5. Anko DSL vs Android XML-First
  6. Lessons from converting an app to 100% Kotlin
  7. Result: Voter Application. 99.8% crash-free users.
  8. Kotlin: val does not mean immutable, it just means readonly