Migrating to Kotlin on Android
It’s no secret that Kotlin is the new hotness for Android development, and for good reason. The language is more concise, handles NPEs safely, and offers features such as Higher Order Functions that have previously not been available on the platform, which is stuck on Java 7. But how do you approach a migration of this scale when dealing with a legacy codebase, all whilst simultaneously handling millions of dollars in transaction volume?
Early last year, the Android team at Blockchain started looking into the viability of moving the entire codebase to Kotlin. This version of the app was around 2 years old and at around 60k Lines of Code (LoC), so any migration would have to be done carefully. Aside from the risk of introducing new bugs, one major concern was whether Kotlin would gain any major traction. Another was whether or not new changes to the Android build and dexing process would break Kotlin in the future.
Initially, we opted to refactor some unit tests to Kotlin. This gave us a chance to get used to Kotlins syntax and idiosyncrasies, while also limiting any damage that unexpected issues could potentially cause. We also made a note of how introducing Kotlin affected our build times (a very minor negative impact).
A naive approach to migrating a Java class to Kotlin is to tell Android Studio to convert the file for you, however this can leave a lot to be desired.
Kotlin’s strict null checking has led to the insertion of double-bang (!!) operator, which is generally a code smell. Mockito’s when function has also been surrounded by backticks, because it clashes with Kotlin’s when included in the stdlib. Thankfully, this is easy to clean up.
Firstly, we add a couple of libraries: Kluent adds a whole host of testing features, and Mockito Kotlin fixes the backticked when by replacing it with whenever. Kluent’s mock function allows us to use val instead of a nullable var, and also gives us handy, human readable assertions such as `should equal`. Finally, we take advantage of Kotlin allowing spaces in function names and make the test itself more readable.
Much nicer, clearer, and more idiomatic.
As time went on, we found no major issues with Kotlin, and started looking at migrating the codebase proper. Then Google I/O happened. Official support from Google was announced, and after we were done picking our jaws off the floor we got to work.
Since then, we’ve made it a rule to build all new features in Kotlin, and generally any Java class that requires more than a minor modification should be entirely refactored into the language. Our extensive unit test suite allowed us to convert logic-handling classes with confidence, and peer code reviews helped highlight any inconsistencies or potential sources of bugs. Around the same time, our platform team adopted Kotlin too, meaning there were plenty more people to bounce ideas and problems off.
At the time of writing we’re at around 60% Kotlin, and the Android team couldn’t be happier.
We’ve not had a single major issue, and the developer team is happier, more productive, and enjoying learning new tricks in a more concise, safe, and functional language. We’re constantly impressed with the power of Extension Functions, we love making use of High Order Functions, and we like to leverage the power of Sealed Classes to represent View states and sealed class hierarchies. Data Classes are an obvious benefit too, drastically reducing the amount of code required when compared with simple POJOS.
If this sounds like heaven to you, we’re looking for awesome Android engineers to join our team.