Kotlin, rockin’ in production
Nabeel Ali MemonArguably, Kotlin has been getting a lot more attention in Android circles compared to otherwise. The reasons mostly cited are:
- It has rich and succinct syntax
- Null-safety is built into the language
- It comes with a compact runtime (~736 KB)
- It’s interoperability with Java (and standard/OSS Java libraries) actually works
- It generates efficient bytecode
Seasoned Kotlin developers generally add two more:
- Extension functions are game changers
- Kotlin community is very helpful and diverse (https://kotlinlang.slack.com/)
What might actually surprise you is, “being mobile first/friendly” was the reason I chose Kotlin to do the backend stuff over other choices on the JVM. The design decisions you make at various levels reflect in the code you write and ultimately manifest themselves in the quality of work you produce. Kotlin allows rich, clean and succinct constructs with very low to no allocataion overhead in the generated bytecode. Of course if you overdose yourself with declarative paradigm and use it where you shouldn’t, Kotlin will try to be as efficient as possible but the responsibility of all those extra GC pauses are on you.
Let me elaborate on that. For the sake of brevity, consider writing a loop over a range of values, say, 0..100
. Out of various possibilities, we will consider two way which are arguably clean and expressive:
- For loop with range:
//Kotlin
for (i in 0..100) {
println(i)
}
which generates the bytecode that is equivalent to the following Java code (taken straight from Intellij Idea’s decompiler):
//Java
int i = 0;
byte var1 = 100;
if(i <= var1) {
while(true) {
System.out.println(i);
if(i == var1) {
break;
}
++i;
}
}
- Declarative ForEach loop with range:
//Kotlin
(0..100).forEach(::println)
who’s Java equivalent would be:
//Java
Iterable $receiver$iv = (Iterable)(new IntRange(0, 100));
Iterator var1 = $receiver$iv.iterator();
while(var1.hasNext()) {
int element$iv = ((IntIterator)var1).nextInt();
System.out.println(element$iv);
}
Notice how both approaches achieves the same result but have different performance metrics because of required object allocations.
You might really need to use the declarative style when you’re using a framework which handles the iteration for you and does a lot more stuff besides iteration. For example, Apache Spark’s RDD operations. For everything else, avoiding unnecessary allocation isn’t a bad idea.
To add more capabilities to thefor
loops, currently there’s an open feature request to “Support guards/filters in foor loops”.
But, add the same time, do not underestimate the power of inline
'ed Extension Functions and the kind of optimizations Kotlin’s compiler does to allow for some very neat constructs like:
val user: User? = ...
user?.let {
user.name = "Nabeel"
}
And it’s implicit version:
val user: User? = ...
user?.apply {
name = "Nabeel"
}
Both of these constructs generate bytecode which simply performs null-check on reference followed by conditional assignment. Verification is left as an exercise to the reader.
Pro-tip: Use Intellij IDEA Kotlin bytecode viewer/decompiler and see the Java equivalent code.
So far, I’ve had the following backend/server-side artifacts serving happily in production that involve Kotlin:
- A legacy server, now with mixed Java & Kotlin code. It is user-facing and has to scale horizontally on-demand.
- An ETL utility purely written in Kotlin which talks to remote REST services as well. It’s has some strict memory and performance requirements.
- An upcoming Spring boot based server. It’s core components are security (Spring Security with OAuth2) and microservice-architecture style services. It’s being written entirely in Kotlin and is targeted for mid 2017 release.
Kotlin team at JetBrains has done a great job so far and has been putting a lot of effort to polish 1.1 release by Q1 2017. Features like coroutines in the upcoming Kotlin 1.1 will allow writing clean and easier-to-reason-about concurrent code which is otherwise infamous to be hard and bug-prone. If you want to take a sneak peak at coroutines, check the following:
https://github.com/Kotlin/kotlinx.coroutines
For all the Kotlin related news, keep checking: https://blog.jetbrains.com/kotlin