What we’ve learned at KotlinConf 2018

Rares Musina
InsideN26
Published in
11 min readOct 25, 2018
N26 Employees at KotlinConf 2018

SHOUT OUT to Nicolas Ioannou who contributed with his perspective as an Android developer at the conference

This year’s KotlinConf took place between the 3rd and 5th of October in Amsterdam’s beautiful Beurs van Berlage, a former commodity stock exchange that features stained glass windows, amazing architecture and surprisingly decent WiFi. Many engineers from N26 attended the 2 days jam-packed with all the latest and greatest in the world of Kotlin, and we’ll try to condense our most important learnings in this article. Many of the links are carefully timed to parts of KotlinConf presentations that emphasize specific points, so we encourage you to follow them. Furthermore, Jetbrains were kind enough to publish almost all of the talks here, so feel free to gather all the Kotlin aficionados in your office and have a binge-watching marathon.

Not only were people from N26 participating, but our company was a silver partner this year woot. We’re happy users of Kotlin ourselves and during these days we were excited to talk to so many people who were curious about our transition to Kotlin, the tools we use, and how the hell we managed to build a bank using CI/CD and deploy it in the cloud. Because, you know, building a bank has to involve pain, suffering, and writing code in a plaintext editor on a VM in some private cloud with poor internet connection and no auto-save function, right?

How N26 moved to Kotlin

This was actually one of the most frequent question that we got asked during our 2 days of KotlinConf. The story is slightly different for Android and the backend, so we’ll split it in 2 parts:

Backend ❤ Kotlin

On the backend, the transition was started by a group of mutinous developers who converted a microservice to Kotlin during their Get Stuff Done Days and got the conversation started. Other backend devs were thrilled about the idea and joined their rebellious ways, bringing the conversation up with our CTO who gladly gave them room to experiment in the framework of a tech-radar (moving the tech choice between 4 levels of buy-in: adopt, trial, asses, hold, with sanity checks on each level change). So they deployed this new service to production and realized that it worked exactly the same as its Java counterpart, but the code was more concise and expressive while allowing them to reuse a lot of existing Java libraries without any pain. As the experiment was successful, we soon expanded it and N26 devs are now allowed to choose whether they write new services in Java or Kotlin (cough, cough everybody is choosing Kotlin). We also encouraged people to start writing tests in Koltin even for existing Java services, just to get a feel of the language and train themselves for the blissful moment when they will write production code in Kotlin.

Android ❤ Kotlin

Similarly to our backend devs, Kotlin adoption started out small but quickly gained traction on Android; one day Kotlin was added to the project and a single class was refactored. That spark urged other developers to experiment with Kotlin and some new tools, like Koin, during their Get Stuff Done Days and soon Kotlin code spread like wildfire in our codebase. Sealed classes help us represent state and remove ambiguity, enforcing immutability helps us reduce defects, Data classes remove boilerplate code, and extension functions encapsulate functionality and hide implementation details (e.g. the usage of RxInterop library). But that’s not all! Our test code has seen a lot of love from Kotlin and JUnit5 and we found ways in which we can improve even more after watching Philipp Hauer’s great talk “Best practices for Unit Testing in Kotlin” (companion blog post here). At the time of this writing, Kotlin makes up almost 50% of production code on Android and growing! All new code is being written in Kotlin, existing Java classes are refactored, and tests are revamped! At N26 Android❤ Kotlin indeed

N26 being mentioned during the keynote

Highlights from KotlinConf 2018

A lot of this year’s talks were focused on Kotlin 1.3 that’s just around the corner, and the young but vibrant ecosystem that has developed around the language. There are many interesting patterns that have emerged as more and more people are using Kotlin in production.

Going forward, the language design will be shaped by 5 different pillars, so expect new features to be guided by:

  • Readability over concision
  • Reuse over expressiveness
  • Interoperability over originality
  • Safety and tooling over provable soundness

Unfortunately we could not attend all talks and our list of learnings will only cover a fraction of the great presentations that were on the schedule. Nevertheless, we hope that our interest areas coincide with yours and that we will provide some useful pointers on how to get started with the topics below.

Coroutines

Coroutines are the poster child of Kotlin 1.3 and they promise to bring support for pain-free asynchrony and non-blocking programming to the language. As expected, they were covered extensively throughout many talks here, here, here, aaaaand here. We won’t go into too much details on all the constructs that build up coroutines, but there are plenty of resources lying around the web, of which we can definitely recommend this excellent talk by Venkat Subramaniam that was also voted one of the top-3 presentations at the conference by our N26 attendees.

The main arguments for introducing coroutines as a first-class citizen in the language are nicely laid out in the informal design document. This document also describes coroutines as

A coroutine can be thought of as an instance of suspendable computation, i.e. the one that can suspend at some points and later resume execution possibly on another thread.

In practice, this allows us to avoid callback hell as it allows the the structure of imperative, synchronous code to be the same as asynchronous code. The difference is almost seamless, with an emphasis on almost. The code still has to express the fact that it’s being run asynchronously (i.e. the code is not being run sequentially even if the structure is similar to its sequential counterpart). Another argument in favor of coroutines is that they allow for cleaner handling of exceptions in functions that are intrinsically non-pure like I/O, where error handling in a functional style setup becomes cumbersome.

Of course, you might be wondering whether you should stop everything and re-write all your code to use coroutines NOW. And the nice part about it is that you can easily defer this decision (and probably should) to a later point when your resource consumption demands it. This is primarily enabled by the similarity in structure mentioned above. The code snippets below illustrate the similar structure (taken from the kotlin docs here with some highlighting applied).

Synchronous:

fun doSomethingUsefulOne(): Int {
delay(1000L) // pretend we are doing something useful here
return 13
}
fun doSomethingUsefulTwo(): Int {
delay(1000L) // pretend we are doing something useful here
return 29
}
fun main(args: Array<String>) {
val time = measureTimeMillis {
val one = doSomethingUsefulOne()
val two = doSomethingUsefulTwo()
println("The answer is ${one + two}")
}
println("Completed in $time ms")
}

Will output:

The answer is 42
Completed in 2017 ms

Asynchronous using Coroutines:

suspend fun doSomethingUsefulOne(): Int {
delay(1000L) // pretend we are doing something useful here
return 13
}
suspend fun doSomethingUsefulTwo(): Int {
delay(1000L) // pretend we are doing something useful here
return 29
}
fun main(args: Array<String>) = runBlocking<Unit> {
val time = measureTimeMillis {
val one: Deferred<Int> = async { doSomethingUsefulOne() }
val two: Deferred<Int> = async { doSomethingUsefulTwo() }
println("The answer is ${one.await() + two.await()}")
}
println("Completed in $time ms")
}

Will output:

The answer is 42
Completed in
1017 ms

What about if you’re already using a reactive architecture and you’re not sure how to start migrating or whether coroutines play nicely with the likes of RxJava? You’ve guessed it, there’s a talk for it. What you can do is wrap your Observables around a suspend function and start treating your reactive code as synchronous. Small code snippet taken from Chris Banes:

RxJava:

interface RemoteService {
@GET("/trendingshows")
fun trendingShows(): Single<List<Show>>
}
service.trendingShows()
.scheduleOn(schedulers.io)
.subscribe(::onTrendingLoaded, ::onError)

Coroutines:

interface RemoteService {
@GET("/trendingshows")
suspend fun trendingShows(): List<Show>
}
val show = withContext(dispatchers.io) {
service.trendingShows()
}

Pro Tip: Don’t miss out on the combination of the Lifecycle Observer and the Coroutine Scope to create lifecycle-aware jobs.

Concurrency in Kotlin/Native

Coroutines are just one of the tools provided by Kotlin with the aim of making concurrent applications easier to write and less error-prone. Many talks at KotlinConf 2018 emphasized additional tools that will be included in the Kotlin/Native (no Kotlin/JVM sigh) runtime like Channels, Workers and Any.freeze() to help you in your quest for more reliable concurrent code. The seminal talk around this was Nikolay Igotti’s Kotlin/Native Concurrency Model, but a fair bit of warning — don’t jump into this talk without first reading up on your Kotlin/Native concurrency primitives or else you’ll abandon it in the first 10 minutes and feel a sudden urge to weep softly.

The gist of the above presentation is that workers, not threads are the preferred concurrency primitives in Kotlin/Native. They favor working with immutable objects (see Any.freeze()) or mutable objects owned by a single worker. This means that the model does not require synchronization primitives by ensuring that, at any time, there is only one worker that can mutate the data in question. If it sounds similar to the Actors model, well it’s because it’s inspired by it. All these primitives were moved to the recently rebranded kotlin.native package that’s in v0.9. This is still quite an early beta, so we won’t recommend using this in production just yet.

Domain Specific Languages (DSLs)

Another star of this year’s conference were Domain Specific Languages (DSLs). Even though the main tools for writing DSLs were available in the language for quite some time (extension functions, infix functions, operator overloading, lambdas outside of parentheses and lambdas with receivers), the full breadth of what they enable is just starting to become apparent, as more and more libraries are starting to make use of them. You gotta count on Venkat to deliver a great introduction to DSLs here, but there was another great presentation that explains their use in practice by Aaron Sarazan called Next Level DSLs.

So what are people actually using them for? The main use case we’ve seen is replacing libraries’ reliance on XML or imperative-style code used for configuration and building complex object trees with expressive, declarative and type safe DSLs. Some great examples of this include anko’s layouts DSLs which have been around for a while, with some new kids on the block like kofu’s bean registration (incubated under the spring-fu project that aims to achieve better spring-boot <-> kotlin integration and removing the magic from spring-boot applications), ktor’s and http4k’s routing DSLs. Another very convincing use case for the use of DSLs is html generation, which is best exemplified by kotlinx.html, that also provides the backbone for ktor’s templating sytem.

But probably the most talked-about framework adoption of Kotlin DSLs came from Gradle in the form of its build DSL. In the spirit of full transparency we are actually a maven shop, but the DSL that Gradle showcased looks pretty compelling and is definitely something to look into, especially if you’re already using its groovy-based counterpart. Here’s a cool presentation to get you started. Be advised that we’ve heard that the IntelliJ tooling is still not on-par with the groovy version, but JetBrains are moving quickly to address the small quirks.

Another aspect that was mentioned repeatedly was the importance of the @DSLMarker annotation and the possible scoping hell that you can end up in if you don’t use it. Don’t believe me? Here’s a nice Kotlin puzzler for you, taken from the hilarious Kotlin Puzzlers presentation by Anton Keks.

Kotlin on the Backend

If you’re like us and have already embraced Kotlin bliss on the server-side, you might be interested in what else is there besides, you know, spring-boot. There were many talks showcasing the most popular contenders (spring boot with spring-fu, ktor, http4k), and even a talk that tried to do a comparison of what’s available on the market. We’ve taken all of these and condensed it into the table below. Please note that this is by no means an exhaustive comparison of all server frameworks that support Kotlin, nor does it cover all the features of the frameworks that we chose to present. It’s just a stripped-down list of essential features that we think you might use in your services and their availability:

Kotlin server framework comparison

The fine print for the table above:

  • We’ve used spring-boot v2.0.5 with Kotlin and it works just fine. It’s probably the most mature and feature-rich of the bunch, but it all comes at a price. It’s also a bit awkward to use with Kotlin, but the promise is that spring-fu will change that. It’s encouraging to see that spring-boot itself is going for more explicit and hopefully faster configuration, however, Kofu only works for reactive web apps for now.
  • Ktor is the least mature of the frameworks we’ve looked into, but development is advancing at a rapid pace. It is expected to come out of beta soon (the official release was waiting for coroutines to be released, as it relies heavily on them)
  • Http4k shows a lot of promise, it’s already at v3.39.0 as of this writing, and we’ve discussed with many people happily using it in production. We’ve also started experimenting with it in the hope that it will yield faster boot times and less configuration magic for our services and will let you know about the results in a subsequent post.
  • Eclipse Vert.x is at v3.5.4, it’s already a mature and established framework and we’ve also heard of many people happily using it in production with Kotlin

Regardless, as you can see above there are plenty of viable alternatives and you should experiment with the one that best fits your use cases.

N26ers enjoying the 80s themed after party at KotlinConf

Top 3 presentations as voted by N26 attendees

It is impossible for us to cover a 3-day workshop in a finite blog post, but we hope that we conveyed the main takeaways as well as some use cases and best practices we adopt at N26. Finally, we asked our colleagues who attended KotlinConf 2018 to vote on their top talks; we present them here for you and urge you to have a look:

Interested in joining one of our teams as we grow?

If you’d like to join us on the journey of building the mobile bank the world loves to use, have a look at some of the roles we’re looking for here.

--

--