Kotlin code size and complexity

Photo by chuttersnap on Unsplash

Converting a Java application to Kotlin is expected to reduce the line count by 40% according to Jetbrains. Note that this isn’t accomplished by jamming more code on each line as the average line length is also reduced. Combined, this means that the total amount of code can be reduced by over 50% when leveraging the capabilities of Kotlin.

There are three main reasons for the code reduction. The first reason is due to a more concise language (eg. Kotlin data classes can replace 50 line classes with a single line). The second reason is that the Kotlin standard library enhances existing Java classes with extensions that trivialize common usage (eg. splitting a collection of items based on some custom condition or checking if a collection contains an item with certain qualities etc.). The last reason is very surprising. Kotlin actually enables higher levels of code re-use that are completely impossible in Java even when using Java 8 features. Although both languages are Turing complete, Kotlin allows you to extract more re-usable patterns than what Java allows.

As an example that’s not possible in Java, Kotlin allows you to use the return statement inside inlined lambdas so that it returns the same way that it would return from something like a for loop. In Java, returning from a lambda is misleading as it doesn’t actually return from the current function that you’re in. The high-level meaning of the return statement varies in Java based on context (return from the method vs. return from this chunk of code). This Kotlin capability almost seems like you’re defining new language constructs which make your utility functions very natural to use. As an example, something like the try with resources capability that we needed to wait for until Java 7 can be accomplished with a simple utility function in Kotlin. This allows you to write natural looking business logic while abstracting away common patterns such as exception handling or acquiring & releasing locks. Better still, unlike the scalability concerns that you would get from some Java 8 features (eg. creating lambdas in a loop), inlined lambdas in Kotlin don’t have any performance or memory overhead.

Many best practices and design patterns have been incorporated into the language so you never need to implement them yourself. This also eliminates many categories of defects. Some examples are singletons, delegation, data classes, etc. Java requires you to take the time to read, understand, and verify that the patterns were implemented correctly whereas many of these are part of the language and guaranteed to be correct. These are read as concepts instead of as a series of instructions the way you would in Java. Additionally, many Java anti-patterns were eliminated which removes the cognitive overhead of needing to watch out for them. There are additional guarantees which reduces the amount of assumptions or considerations that need to be made when reading through code (eg. can this Boolean variable ever be null and would that be accidentally interpreted as “false”?).

So in fact, the shorter Kotlin code is actually even easier to understand compared to Java code with the same behavior. This is because Java code needs to be read and mentally verified whereas Kotlin trivializes many concepts. One way of thinking about this is that reading Java code requires you to verify lower level instructions whereas reading Kotlin code requires you to verify the correct use of concepts so it’s closer to behavior-level thinking. Also, the extra patterns that can be extracted compared to Java only need to be considered 1 time instead of re-evaluating them in many places.

Therefore, converting a Java application to Kotlin and taking advantage of Kotlin features reduces code size by 50%. The code is also much easier to understand because the extra Kotlin capabilities allow you to think using higher level concepts. The possible states of the application at any given point are also reduced which reduces the possibilities that need to be considered thus reducing the cognitive effort. Combining the code size reduction with the readability effort reduction, I found that the time it takes to read and understand code is cut in half. This allows us to start producing sooner so productivity is impacted. Thus, Kotlin enables us to be 1 / (1 - 0.9 * 0.5) = 1.8 times more productive since this is where we spend over 90% of our time.

Realizing that the creation part of our time is also reduced, it’s easy to see how Kotlin could double productivity from these impacts alone!

I also noticed that since my code is closer to the concept level in Kotlin, this results in cleaner code so future maintenance / sustainability overhead is also reduced.

I was honestly shocked at my productivity after becoming familiar with the language as I didn’t expect it to have a measurable impact (I was mostly thinking about reduced defects rates). It was only after completing a large task in Kotlin that I realized my career outlook would be forever changed. As much as I enjoyed working with Java in the past, having experienced such a pragmatic and productive language, I just can’t allow myself to be held back in such a severe way now that I see what’s possible.