Read Time: 6 mins

I recently wrote about how we adopted Kotlin as the main development language for Android on the mobile team at Udacity.

No Title

Just in time for @kotlinconf See how we’ve been using @kotlin for #androiddev on the mobile team @udacity

Check out the original posts here:

Udacity Engineering Blog

Udacity India Blog

If you’re an Android developer, you’ve most likely heard about Kotlin sometime during this past year.

For those who aren’t familiar, Kotlin is a programming language developed by JetBrains that targets the JVM and is 100% compatible with Java for Android development.

*Kotlin is actually capable of much more than just Android development. For more info checkout the language webpage.

On the mobile team here at Udacity, we’ve been using Kotlin in production for ~9 months, and have adopted it as our primary development language moving forward.

Recently, we’ve been asked a number of times about our usage of the language and why we’ve invested in it, so we thought we would share a bit about the following:

  • Why we’ve invested in Kotlin
  • Our adoption process
  • How are we using Kotlin today
  • Tips for incorporating Kotlin into your project

Why have we invested in Adopting Kotlin?

If you ask each member of our team this question, you’d get a slightly different response, but the general consensus would likely sound something like this:

“Kotlin provides a more enjoyable developer experience by allowing us to express our features & ideas using safer, more concise code. This, in turn, enables us to build a better product for our users”

More concretely, we believe Kotlin provides several key benefits to our team:

  1. Improved crash rate
  2. Reduction in lines of code written
  3. Decreased time spent in code review
  4. Renewed excitement around experimentation and innovation

Ultimately, our goal is to provide our users with the best learning experience possible. We believe these items help us do that.

How did we start adopting Kotlin?

Our adoption of Kotlin started through the recognition of “pain points” that we experienced on a regular basis. During code review, comments like this started to crop up often:

“this 10 line block could be done in 3 lines using Kotlin”
 “it would be great here if we could avoid checking for null in 4 different places”

Having experimented with Kotlin outside Udacity, we knew the language might help us solve these problems and build better Android apps. Because of this, it wasn’t long before we had our first Kotlin PR

A small feature was implemented in Java, and a pull-request opened; but along with that PR another was created that provided the same feature; only written in Kotlin. The Kotlin PR wasn’t merged in that instance, but it demonstrated that we could easily integrate Kotlin into our existing app without compatibility issues or a slowdown in development time.

That was the jumping off point. We decided we would migrate a single, small feature in the app to Kotlin and see how it did in production.

We started by migrating our Settings screens in a separate develop branch. This branch received a lot of internal testing while we evaluated closely for 2 types of issues:

  1. Usability issues: what impact did Kotlin have on crashes/bugs?
  2. Development process: did Kotlin cause CI issues, slow down our build, or slow down feature development?

When nothing arose, we shipped the new Kotlin feature to users and crossed our fingers. Thankfully, as we expected, no major issues were found. We were now happily using Kotlin in production.

After that, we slowed down a bit. We loved using Kotlin, but recognized the potential risks of going all-in on an unofficially supported language. We continued to add/convert some tests to Kotlin, but no new feature code was using it.

Then Google announced support for Kotlin as a first-class language for Android development.

Team buy in

Google’s backing was the push we needed to fully embrace Kotlin.

We met with our PM and expressed our desire/plan to adopt Kotlin as our primary development language. Understandably, we were met with a healthy dose of pragmatism and asked a few important questions:

  • Is the language stable/safe to be using now?
  • Will it slow down development?
  • Are there tangible benefits?

“what is the value prop?”

We benefitted here from having already successfully shipped production Kotlin, and could point to ourselves as an example of production usage
of the language.

After expressing our beliefs that we could write safer, less error-prone code with a Google-backed language, and that it wouldn’t slow down our development process we received the thumbs up we were looking for.

Migration plan

From this point we decided Kotlin would be our language going forward and created a migration plan:

  1. All new dev work in Kotlin
  2. If anything larger than a small bug fix must be done to a class, consider migrating the class to Kotlin
  3. Start migrating existing code

Where feasible, the in-progress features began using Kotlin, and all new work began being written with it.

Our plan for migrating existing code, was to tackle the low hanging fruit first (utilities, helpers, isolated classes) then work towards migrating enough code that the majority of our daily development would be in Kotlin.

We identified the packages we thought were good candidates, and spent ~ 2 months migrating code while still pressing forward with new feature development.

For most Java classes, we started by using the Java to Kotlin conversion tool within Android Studio. We would then make manual adjustments focusing on a few things:

  1. Avoiding the use of !! operator
  2. When possible, convert helper methods to top-level functions
  3. Avoid companion object where possible
  4. Reorganize the generated code
  5. Expressing code in a more Kotlin idiomatic way

Reevaluating our handling of nullability was probably the most time consuming part of these manual adjustments, but lead to some of the greatest wins regarding stability and code maintenance.

In many places we focused on leveraging statements such as object?.let {...} rather than using if(object != null) { ... }.

We also tried to leverage the great collections stdlib that Kotlin provides. These apis allowed us to replace large blocks of code with a few lines of concise functional code.

When used together, these two features of Kotlin allow us to write code like this:

val recentQueries:List<String?>? = listOf()
val recentsToDisplay = recentQueries
?.filter{ it.isNotBlank() }
?: listOf()

This snippet is short, easy to follow and has fewer possible points of error than the equivalent Java code would have.

Where are we today?

Today we have about 1/3 of our main codebase written in Kotlin. As we touch features we continue to migrate that code, but we’ve slowed down on migrating existing code.

This is largely due to us shifting dev cycles to several experiments that are being carried out in separate codebases.

These new codebases are 100% Kotlin, and will ideally stay that way.

Working in an exclusively Kotlin codebase also means we don’t have to concern ourselves as much with java interoperability. This allows us to more fully explore the language.

Our aim is to discover and try what is possible with the language, rather than simply writing our familiar Java code; but in Kotlin.

We’ve enjoyed experimenting with new patterns that may have been not possible, or too cumbersome in Java. For example, the freedom to have top-level functions or easy property delegation have lead to cleaner and more semantically correct code.

Tips for adopting Kotlin

Having gone through the process of incorporating Kotlin into an existing codebase, migrating a large portion of the codebase to Kotlin, and starting a new project from scratch using 100% Kotlin; here are a few tips that we’ve learned along the way.

  • If new to the language, start with the conversion tool
  • Don’t be afraid to further modify the converted code
  • Starting with tests can help work out any issues with your build and start giving a feel for the language, but writing feature code will give a more comprehensive picture of how it can affect your code
  • Don’t go wild trying to write “idiomatic” Kotlin. As you progress with the language, it’s likely your opinion of whats readable vs what’s possible will evolve.

Just because you can doesn’t mean you should

  • As you migrate existing code, re-visit previously converted code from time to time. You may find that newly discovered conventions/patterns could be applied.
  • Don’t forget to thoroughly test any interop layers between Java and Kotlin. Nullability issues can crop up during runtime when dealing with nullableplatform types.

Explore, experiment, migrate, refactor

Lastly, take advantage of this period of exploration while learning the language. Question existing patterns/conventions for writing Android apps and ask yourself if/how Kotlin might enable you to write alternative solutions.

— can your code be refactored to avoid null properties?

— can you replace helper classes/methods with top-level functions?

— can you avoid handling null properties by using a delegate?

— could a logical path be expressed using functional concepts to reduce a class’s state?

How can Kotlin help improve your product?

Confidence in adopting Kotlin moving forward

We are very comfortable with our investment into Kotlin for the foreseeable future.

The language and tooling continue to improve. Between JetBrains, Google, and the community, there is a great team behind improving these developer stories.

As documentation and samples continue to be added for the language, it will become increasingly less daunting to try Kotlin which we believe will increase adoption and make it an even more viable option going forward.

We look forward to further exploring Kotlin and everything it can do to help us build great education products for our users.

I love to meet/talk/discuss and help where I can. If you want to chat or ask a question you can follow me on Twitter, YouTube, Instagram and Facebook.

Check Out My YouTube Channel

Leave a Reply

Back to Top