Feedback - Kotlin on the server-side - the good, and the bad

I've used Java as my primary server-side programming language for years. Before joining Qovery, I worked at SAP, where Java was the default choice to bootstrap new projects. Besides its known limitations and cumbersomeness.

Patryk Jeziorowski

Patryk Jeziorowski

July 23, 2020 · 7 min read
Feedback - Kotlin on the server-side - the good, and the bad - Qovery

JVM ecosystem, decent performance, and stability make Java a common choice in enterprises. From a developer's point of view, all of these come with the cost of working with old language, lacking some of the essential features that newer languages provide (which Java tries to fix with the recent changes and more rapid, 6-month release cadence).

Convincing colleagues to consider a new language (like Kotlin) was impossible, especially after our negative experiences with Scala. That's the main reason why my experience with Kotlin before changing the job was limited to playing with it in micro side projects and reading articles.

In April, I started working at Qovery, a container as a service platform where a considerable part of the backend code is in Kotlin. In this post, I'll describe the last months of my journey from Java to Koltin, my experiences and thoughts on this process, and Kotlin as a server-side programming language.

From a developer experience point of view, Kotlin is a significant improvement, especially if you jump from 'old' Java - Patryk J.

#My feedback

#From Java to Kotlin

For me, a Java developer with basic knowledge of other languages (like JS, Go, and other popular programming languages), moving from Java to Kotlin was natural. It was more like a gradual transition/upgrade rather than jumping into something new. Most of the right parts from Kotlin that are missing in Java can be found in other programming languages. Suppose you are not limited to just one language (Java). In that case, there will be little in Kotlin that will surprise you (for the people thinking the transition from Java to Kotlin is hard - I recommend trying to use Rust without reading the Rust Bible twice - you'll change your mind quickly.).

#Reading/Writing Kotlin code

Reading Kotlin code came without any effort. If you can't guess what the 'new' syntax means, all you need to do is take a quick look at the basic syntax page, and you are good to go. Writing idiomatic Kotlin code, however, is a bit trickier. After years of using Java, you may have habits that will lead you to write Java-like Kotlin code. Writing idiomatic code, at least in my case, requires more time spent with the language. I found this document invaluable to speed up this process.

#How did I ramp up on Kotlin?

Getting ready to use Kotlin did not require more than spending a few days to get used to the codebase I would later work with and slowly read the Kotlin documentation in the meantime. This gives you all the basics to be productive with the language - proficiency and expertise will come with time.

#After a few months

After switching from Java to Kotlin, my first impressions were that I deal with a modern programming language. Pascal notation, type inference, extension functions, no semicolons, immutable collections, coroutines, channels, and more - this all added to a feeling of using a powerful, modern language (even though most of the concepts are pretty old, borrowed from other languages, you can see similar trends in other new, modern programming languages).

Another thing that I could quickly notice is the improvement in code readability (in the majority of cases) and conciseness. The most striking, simple examples are, of course, data classes and null checks, which cost much more work (and lines of code) in Java.

Data Classes (Kotlin vs. Java):

Kotlin

data class Person(var name: String, var surname: String, var id: String)

Java

public class Person {
    private String name;
    private String surname;
    private String id;
    public String getName() {
        return name;
    }
    public void setName(String name) {
        this.name = name;
    }
    public String getSurname() {
        return surname;
    }
    public void setSurname(String surname) {
        this.surname = surname;
    }
    public String getId() {
        return id;
    }
    public void setId(String id) {
        this.id = id;
    }
    @Override public boolean equals(Object o) {
        if (this == o) return true;
        if (o == null || getClass() != o.getClass()) return false;
        Person person = (Person) o;
        if (name != null ? !name.equals(person.name) : person.name != null) return false;
        if (surname != null ? !surname.equals(person.surname) : person.surname != null)
            return false;
        return id != null ? id.equals(person.id) : person.id == null;
    }
    @Override public int hashCode() {
        int result = name != null ? name.hashCode() : 0;
        result = 31 * result + (surname != null ? surname.hashCode() : 0);
        result = 31 * result + (id != null ? id.hashCode() : 0);
        return result;
    }
    @Override public String toString() {
        return "Person{" +
                "name='" + name + ''' +
                ", surname='" + surname + ''' +
                ", id='" + id + ''' +
                '}';
    }
}

Null checks (Kotlin vs. Java):

Kotlin

fun main() {
    val outer = OuterClass(null)
    print(outer.inner?.someValue ?:DEFAULT VALUE)
}

Java

public class Example {

  public static void main(String[] args) {
    OuterClass outer = new OuterClass(null);
    if (outer.inner != null && outer.inner.someValue != null) {
        System.out.println(outer.inner.someValue);
    } else {
        System.out.println(DEFAULT VALUE);
    }
  }

}

After working with the language, I noticed another thing - the null safety, does make the difference. It does not solve all the issues with NPEs, but it drastically reduces this problem. Most of the time, when I get NPE, I intentionally cut corners due to my laziness. After the code is ready to go to production, it's improbable to throw an NPE.

#Java-Kotlin interop

Java-Kotlin interop is excellent. You can use anything you would use in plain Java. Sometimes you may fall into a pitfall; you need to take care of nulls (they may come from Java libraries, which are not null-safe) or may need to use a plugin to make a given framework work properly. Still, in general, it's a very good interop between two languages. You can even copy-paste Java code, and IntelliJ will convert it to Kotlin on the fly - it works pretty well; most often, it produces working code - from time to time, you may need to correct something manually.

Automatic Java -> Kotlin code conversion
Automatic Java -> Kotlin code conversion

#The good and the bad

#Why you should consider it

The list of good things about Kotlin is very long. I'll name just a few that are my favorite, and those alone should justify at least considering using Kotlin for server-side programming on the JVM:

  • null is a different type - String (non-null) and String? (nullable String) are two different styles in Kotlin. If you don't mess with the compiler, you are pretty much safe from null pointer exceptions. The fewer 500 InternalServerErrors due to NPE, the better!
  • Extension Functions - Kotlin allows you to add new functions to any type (e.g., the String class). It's just syntactic sugar that replaces Java's static util functions, making the code much more readable.
fun String.myOwnStringFunction() = this.toUpperCase() + " | Made with Extension Function"

fun main() {
    print("HelloWorld!".myOwnStringFunction()) // OUTPUT: HELLOWORLD! | Made with Extension Function
}
  • Functional programming support - default immutability in collections, value objects, higher-order functions, useful helper functions in the standard library - FP support in Kotlin is much better than in Java.
  • Type inference - most often, you don't need to provide the variable type - the compiler is smart enough to know. One could say it's the same in Java since Java 10, but Kotlin took it to the next level - it can infer method return type or class property type, which is not the case in Java.
class Example {
    fun functionReturningString() = "NO RETURN TYPE SPECIFIED"
}

#The dark side

Moving all language specificities aside, the thing that disappoints me the most is IntelliJ's performance while working with Kotlin. Code completion, syntax highlighting, refactoring - I can always feel a slight delay while working with Kotlin. The problem is not existing while working with any other language (besides the performance, JetBrains IDE works excellent with the language).

Renaming method parameter in Kotlin (pay attention to how long the red frame around the variable name after renaming action lasts):

renaming in kotlin with intellij
renaming in kotlin with intellij

There are a few language design choices that some people dislike and/or find disappointing. Lack of possibility to extend data classes, lack of Java-like static methods & fields, classes that are final by default (which is inconvenient while using specific frameworks) - this kind of thing is bugging some people. For me, these are not critical and certainly do not outweigh all the pros that come with using Kotlin on the server. However, you should be aware that Kotlin, just like any other tool, is not perfect.

#Final thoughts

From a developer experience point of view, Kotlin is a significant improvement, especially if you jump from 'old' Java (by old, I mean 8, which is still very common in big enterprises). By using Kotlin, you end up writing less code. The code is more readable and safer - which is critical in the backend, server-side applications. The transition from Java to Kotlin is very smooth - you can quickly become productive and develop your expertise with time. You don't need to learn new frameworks, as the same frameworks and libraries you have used before with Java do work with Kotlin as well. If you want to improve your server applications on the JVM - you should give Kotlin a try.

Your Favorite Internal Developer Platform

Qovery is an Internal Developer Platform Helping 50.000+ Developers and Platform Engineers To Ship Faster.

Try it out now!
Your Favorite Internal Developer Platform
Qovery white logo

Your Favorite Internal Developer Platform

Qovery is an Internal Developer Platform Helping 50.000+ Developers and Platform Engineers To Ship Faster.

Try it out now!