An intelligent bet on Kotlin

This article was originally published at https://bell-sw.com/announcements/2020/11/16/An-intelligent-bet-for-Kotlin-part-one/

If you’re a Software Developer or any kind of professional working in the IT sector, you’ve probably heard of Kotlin language

Kotlin language has been gaining a lot of traction and popularity among developers in the industry in the last four years. Among its benefits, its supporters enumerate its conciseness, expressiveness and simplicity and mainly that it makes their lives easier when writing code compared to other languages. The fact that it has a very flat learning curve for Java developers is also a fact to take into account for some developers and organisations before making the decision of switching to Kotlin.

In this article we’ll be going through the main characteristics of Kotlin language. We’ll also talk about its brief history, but more importantly about its future!

History

Kotlin language was first released in 2011 by the company JetBrains; if you don’t know about them, they were firstly known for being the creators of the popular IntelliJ IDEA and now they’re also very well-known as the creators of Kotlin language.

Although their first release was in 2011, it wasn’t until 2016 when Kotlin v1.0 was released, the first official release from which JetBrains will provide backwards compatibility; you can check Kotlin release versioning scheme here. Kotlin is currently on version 1.5 and in the next timelines we can compare Kotlin’s release cycle with JDK’s release cycle.

After JDK 9, JDK switched from a feature-based release cycle to a date-based cycle where a new release will come every six months independently of the state of the features. In addition to that it’s been defined that a new LTS version will be released every three years within this release cycle.

On the other hand, Kotlin’s release cycle also started as a feature-based cycle but JetBrains has decided to switch to a date-driven cycle starting from version 1.5 in Spring 2021.

If we look closely at the language features, we can notice that Kotlin has supported from the very beginning most of the features that Java is currently trying to bring onboard. Another aspect that we can notice is that Kotlin now seems to be stable and mature as a language, being its releases more focused on improving performance and developers experience. 

According to different sources, the main reason that led JetBrains engineers to start writing their own language was mainly due to not finding any existing language which fulfil their needs; the goal was to build a concise, elegant and expressive language also able to be compiled fast.

Another important characteristic of this new language would be that it had to be able to interoperate with Java language to allow a slow and painless adoption of the new language. By doing that, and especially with Kotlin being a 100% Open-source language, it’d still have access to all the work done by the Java Open Source community in the last decades.

Writing a new language is not easy, but writing a new language with full interoperability with an existing language like Java is even more difficult. However, despite the challenges, JetBrains seems to be doing a very good job so far, according to the good welcome that their language has received from the community.

What’s the reason why Kotlin is becoming so popular and widely adopted in our industry? Let’s go through its main characteristics to understand the reasons behind its popularity.

Simplicity and pragmatism above all

If there’s one thing that characterises Kotlin, this is its focus on pleasing developers’ wishes, an obsession in making their lives and their day-to-day work as smooth and simple as possible. When we write code at a professional level on a daily basis, it’s the small and apparently unimportant things that we face very often the ones that kill our productivity and produce a constant sense of waste of time and demotivation in us.

Kotlin has removed some of these unnecessary annoyances, very well-known and recognised by all of us, although for one reason or another nothing had been done until now.

Let’s go through some of them briefly.

Multiplatform

Kotlin is a multiplatform language which can be executed in different supported platforms; you can target different runtime environments like JVM, Android, JS or many others with the use of Kotlin/JVM, Kotlin for Android, Kotlin/JS and Kotlin/Native. However, keep in mind that the status of the Multiplatform project is still in “Alpha” state; that means that it’s not stable yet and you could expect some migration issues. For additional information please check this link.

Types

Kotlin types are very similar to Java (numbers, characters, booleans, arrays and strings) with one main difference: primitives do not exist in Kotlin. Although primitives can’t be explicitly defined, Kotlin’s compiler will translate types into primitives in the JVM bytecode every time that it’s possible to favour a lower memory footprint.

You can find more about Kotlin types here.

Creating a new instance

Some languages like Java or C++ require the use of the “new” operator to create a new instance of an object. We’re all used to it, but is it really necessary? Why not just call the constructor?

This is precisely what Kotlin does, we no longer need to use “new” in Kotlin, calling an object’s constructor is enough to create a new instance.

For example, we can create an instance of an Order object like this:

val order = Order("id", 10, BigDecimal(12.5), OrderType.BUY)


End of statements

For instance, why are we forced to write a semicolon at the end of each line in some languages? Providing the ability to write multiple statements in one single line is unnecessary and possibly not recommended for readability purposes, so why not accept a break line as the standard to represent the end of a statement? If you’re a Java or C++ developer you’ve probably missed a semicolon thousands of times, think about all the time wasted. Kotlin doesn’t require using semicolon to close a statement, although if you do it, it will still compile. 

Type inference and immutability

Kotlin also reduces the verbosity of having to declare the type of variables twice; type inference allows us to just declare the creation of a new variable, inferring the type from the right-hand side part of the statement.

Another improvement in terms of variable declarations is that we don’t have to use any additional modifier to declare a variable as immutable; Kotlin provides just two keywords: var and val. Much simpler than in other languages, if you need a mutable variable use var; if you need an immutable variable use val, as simple as that.
For instance, the following snippet would be allowed, we can override the value of a mutable variable defined with “var”.

var order: Order = Order("id1", 10, BigDecimal(12.5), OrderType.BUY)
order = Order("id2", 12, BigDecimal(15.5), OrderType.SELL)

On the other hand, this situation won’t be allowed, as “order” is a immutable variable:

val immutableOrder: Order = Order("id1", 10, BigDecimal(12.5), OrderType.BUY)
immutableOrder = Order("id2", 12, BigDecimal(15.5), OrderType.SELL) //Compilation error!

Data classes

Kotlin provides a very neat and concise way of defining immutable objects, they’re called “data classes” in Kotlin. Declaring a class with immutable fields has always been specially over-complicated and verbose in Java, in Kotlin you can achieve this in a single line:

data class Employee(val id: String, val name: String, val age: Int)


The NullPointerException dilemma

If you’re a Java developer, you’ve definitely suffered the issues of having null as a possible value for an object or variable; what would be the simplest solution to this problem? Common sense tells us that not allowing nulls in the first place would probably be the simplest and safest solution; that’s precisely what Kotlin does. If you try to assign a null value to an object in Kotlin you’ll get a compilation error, so by default objects are not nullable, you’d have to explicitly tell the compiler that the object is nullable to allow nulls. That’s great, isn’t it? Once more, simplicity and safety first.

val order: Order = null //Compilation error!val nullableOrder: Order? = null

String interpolation

I bet you’ve missed this feature hundreds of times if you use a language with no support for string interpolation, having to concatenate different parts of a string to build the expected format is quite cumbersome. Kotlin provides a very simple and nice way to do string interpolation. For instance, you could do this:

val name = "John"
val surname = "Smith"
println("My name is $name $surname")

Object destructuring

Kotlin brings to us one of the coolest features available in JavaScript, object destructuring. We can do something like this:

val (name, age) = Employee("id1", "John", 35)

This is great, although unfortunately this can only be done with data classes. If we wanted to use string interpolation without data classes, we are forced to implement component1() and component2() operators in our Order object, something that personally I’m not very happy with.

For instance, if our Employee class wasn’t a data class, we would have to do the following to be able to use object destructuring:

class Employee(val id: String, val name: String, val age: Int) {
  operator fun component1(): String = name
  operator fun component2(): Int = age
}

You could also use Kotlin extensions to implement the required operators for the Employee class:

private operator fun Employee.component1(): String = name
private operator fun Employee.component2(): Int = age

You must be wondering why we have to do that to be able to use object destructuring; the actual reason is that Kotlin compiler compiles a data class to the following if you decompile the corresponding class file:

// IntelliJ API Decompiler stub source generated from a class file
// Implementation of methods is not available

package com.coding.kotlin

public final data class Employee public constructor(id: kotlin.String, name: kotlin.String, age: kotlin.Int) {
  public final val age: kotlin.Int /* compiled code */

  public final val id: kotlin.String /* compiled code */

  public final val name: kotlin.String /* compiled code */

  public final operator fun component1(): kotlin.String { /* compiled code */ }

  public final operator fun component2(): kotlin.String { /* compiled code */ }

  public final operator fun component3(): kotlin.Int { /* compiled code */ }
}


You can see that Kotlin provides a component operator for each property defined in the data class. However, if you modify Employee class to not be a data class, just a simple Kotlin class, then you will see that Kotlin doesn’t override those operators.

// IntelliJ API Decompiler stub source generated from a class file
// Implementation of methods is not available

package com.coding.kotlin

public final class Employee public constructor(id: kotlin.String, name: kotlin.String, age: kotlin.Int) {
  public final val age: kotlin.Int /* compiled code */

  public final val id: kotlin.String /* compiled code */

  public final val name: kotlin.String /* compiled code */
}

One thing that Kotlin’s object destructuring solves nicely is the complex and messy manner that Java provides to iterate through the entries in a Map. In Kotlin we can simply do the following:

for ((key, value) in myMap) {
  println("$key, $value")
}

This is definitely much nicer and still as fast!

Default arguments

In some languages we have to duplicate constructors to allow the optionality of some of its arguments, something that adds clutter to our classes.

Kotlin solves this problem by allowing the option of providing default values for our arguments when they’re not specified.

For instance, if we define a default value for our order type:

constructor(userId: String, quantity: Int, price: BigDecimal, type: OrderType = OrderType.BUY)

We can now instantiate an Order object without specifying the order type:

val buyOrder = Order("id", 10, BigDecimal(13.2))

Named arguments

If you’ve worked with complex domains with a considerable number of fields, it’s often difficult to keep track of what argument in the constructor corresponds to what field in the component.

Kotlin solves this by providing the ability of naming arguments in the constructor, this allows a more explicit declaration of arguments in a constructor, improving its readability considerably. Also we wouldn’t have to place arguments in the same order in this case.

For example:

val sellOrder = Order("id", type = OrderType.SELL, price = BigDecimal(3.0), quantity = 1)

In general, we have less rigidity and a more expressive and readable language.

Async programming – Coroutines and Channels

Kotlin takes a different approach to languages like Java to run multi-threaded applications; the way Kotlin works is very similar to what Golang does.

Golang provides goroutines and channels in the same way that Kotlin provides coroutines and channels.

To help you understand why coroutines are so important, I’ll talk briefly about the way current Java threads work. The current implementation of Java threads relies on the OS kernel threads and this brings a few problems: 

  1. Threads are very heavy, mainly because when a thread is suspended its native call stack and its Java’s call stack have to be stored or retrieved.
  2. The OS scheduler doesn’t have a way to differentiate threads to be able to group them per user or unit of work. What this means is that two threads that process the same data will very likely be executed by different CPUs.

This results in a big problem, context switching between threads is quite expensive and degrades performance, because transferring data between CPUs is expensive. Ideally we’d want those two related threads to be processed by the same CPU, but that’s not possible using the OS scheduler. That brings us to Kotlin’s solution for this problem: Kotlin’s coroutines.

Kotlin’s coroutines are very lightweight components used to run tasks concurrently; they’re very small in size compared to Java Threads and in contrast with them, they’re not managed by the operating system but by the Kotlin runtime. This means that we can create a lot of them and having a “thread” per user or transaction would now be possible, in contrast with Java’s limitation due to Java threads being so heavy.

Let’s look at a coroutines example to understand them a bit better:

val start = System.nanoTime()
runBlocking(Dispatchers.Default) {
   (1..2_000_000).map { index ->
       launch {
           delay(100)
           println("I'm a lightweight thread number $index! running on ${Thread.currentThread()}")
       }
   }
}
println("Done in ${(System.nanoTime() - start) / 10e09} seconds!")

In this example we are creating 2 million “threads”, each of them simulating a delay of 100 milliseconds. These threads will run concurrently and they’ll be handled by the Kotlin runtime. Kotlin allows us to create a huge number of threads with no problem at all; this is absolutely not doable in Java, you’d need a limited size thread pool and reuse threads for different invocations as they’re expensive to create and to keep in memory. 

The way coroutines work simplifies writing asynchronous tasks for developers considerably; threads management is hidden behind Kotlin’s runtime and also async tasks can be written in the same way as synchronous tasks.


Kotlin also provides channels as a way of communication between coroutines. To understand the way they work easily, you can imagine them as a messaging system; there’s an emitter that sends messages to a channel and one or more receivers that process those messages. The communication between these coroutines always takes place within this channel.

This is a much efficient and simpler approach to deal with concurrency and parallelism; instead of sharing resources, the stakeholders communicate between them to achieve a common goal!

Kotlin’s coroutines and channels are a very interesting topic that probably deserves a sole article to talk about them, but for the time being this is enough to have a clear understanding of their concept. One last thing to mention is that Kotlin has some nice libraries to help us develop asynchronous applications, for example Ktor, an asynchronous framework for microservices and web applications in general.

We could definitely go on for much longer showing all the existing nice features that Kotlin has come up with, but this is probably enough to give you a good idea of the radical change of mindset that this language has brought to us in the JVM world. A language design driven by developers, focused on productivity, simplicity and comfortability to make us enjoy what we do. A battle against boilerplate code and unnecessary clutter.

This is the kind of pragmatism that Kotlin is aiming for, very little things that may seem insignificant by themselves, but when put together they make a huge difference in terms of productivity! 

Now that we know something about Kotlin as a language, let’s see how Kotlin is currently doing.

Its present, a really good start

If you look at the market trends and comments in social media among developers, you’ll clearly see that Kotlin has received a very warm welcome by the community. Kotlin has been a breath of fresh air for many; its radical and very intelligent approach has made a big difference.

In the image shown below you can see the worldwide interest in Kotlin according to Google Trends:

Providing what it almost looks like a complete new language but at the same time having full interoperability with the Java language and being able to use the JVM as its runtime environment means a huge advantage and it was a very smart move. Although there are other JVM languages capable of interoperating with Java code, Kotlin’s flawless interoperability is far superior in some cases and in the cases where the level of interoperability is similar, other characteristics in the language tilt the balance in favour of Kotlin.

Most of the companies are afraid of big changes, they’re scared of finding themselves stuck in an uncomfortable situation where everyone dislikes the new changes, there’s a whole sense of regret within management and no one sees an easy way of going back.

Kotlin has allowed these companies to take small steps, keep using the same libraries and frameworks they currently use and slowly move to Kotlin and see how things go, with no rush and minimal risks.

This has given companies the ability to try things out following a more conservative approach, not taking as many risks as they could be taking if they were moving to a complete new language.

Although Kotlin allows switching from Java in a smoother manner, it’s worth mentioning that transitioning to a new language in production is never an easy task; you’ll need to set up an appropriate plan with clearly defined goals. It’s very important to understand what we want to achieve, why we are making the choice we’re making and try to take everyone on board, including management. We will also have to consider what the risks are before undertaking the migration; risks as the potential lack of experience in the team with the new language or difficulties to bring new developers into the team.

Once the risks are clearly identified, it’ll be easier to prepare to be able to minimise those risks or even have a backup plan ready.

One important aspect to consider when migrating to Kotlin is that Kotlin has become a first-class citizen in Spring framework after Pivotal (now part of VMWare Tanzu) decided to start supporting Kotlin since version 5.0 in 2017. This allows using Kotlin features in the Spring integration, being able to achieve a more concise and expressive code when working with Spring and Kotlin and experiencing a smoother transition from Java to Kotlin for all those projects using Spring framework. 

Another big step in Kotlin’s adoption has been its tremendous success in the mobile development industry. In 2017 it was first announced by Google the Kotlin support for Android development and then, only two years later, Google publicly stated that its new preferred language for Android development is now Kotlin. A huge step towards a wide adoption of Kotlin among developers in our industry. This means that now we can use the same language and the same libraries for backend and mobile applications as we do with Java, but writing a more concise, expressive and elegant code and taking advantage of cool language features as null-safety or coroutines.

As we can see, Kotlin’s present looks bright, but what future lies ahead for Kotlin?

Its future

If someone made me bet for one language in the next few years, it’d definitely be Kotlin. 

In our sector being agile and achieving a sufficiently fast pace to stay ahead of the competition is key to achieve business goals, that’s why betting for Kotlin could become a competitive advantage. The adoption of Kotlin could mean a boost in productivity for the teams in your organisation; why wait for the next Java LTS release to be able to use some features which are already available in Kotlin? To make things worse, some of the features that we’ve been really missing for years in Java have been supported by Kotlin for years and they are not even in Java’s roadmap for the next releases.

Good examples of these missing features could be Java records, which are still feature previews and we’ll have to wait at least 6-12 months before being able to use them safely, or also Java’s Project Loom. Java Threads have been a problem for a very long time and despite that this work hasn’t started until late 2017. Although they’re making progress and there are some early-access builds available to start trying it out, this is still far from being completed. On the other hand, JetBrains managed to have something production-ready in a much more reasonable timeframe; this is one of the reasons why some developers are losing their patience with Java and making the decision of switching to Kotlin.

When we write code in Kotlin we can get all the system benefits of Java as a JVM language, for example in terms of performance, and at the same time benefit from one of the nicest syntaxes in terms of conciseness, readability, expressiveness and the main important thing, productivity.

We all know that Kotlin’s main uses are server-side and Android development, but what makes Kotlin even more interesting is that it’s been designed as a multiplatform language in a way that goes beyond our traditional understanding of being multiplatform from a JVM-world point of view. We can for example make use of Kotlin/JS to transpile our code to JavaScript, being able to write web frontend applications or even React applications! Without going into too much detail, I think that this could bring many benefits to full-stack development but above all this could fill an existing gap between backend and frontend development that could improve things looking forward.

In addition to that we could also use Kotlin/Native to write applications in Kotlin on platforms where running a JVM is not possible or desirable (embedded devices, iOS, etc), something that could be useful for some use cases.

All of this provides increased flexibility for developers, with the extra of a fantastic tooling support provided by JetBrains; I think we can all agree that a language designed by a tooling manufacturer has great advantages for a good developer experience.

But the reasons behind a promising future for Kotlin are not purely technical; they’re also structural and organisational. From my point of view, JetBrains is a fairly small, dynamic and fast-paced company with clear objectives and huge ambitions. On the other hand, there are some other companies that are either too big or they might not have the right level of organisation required to gain the right traction and achieve enough speed to make things happen quickly.

This is something very difficult to beat by big companies. It might be their size that makes them go slower or maybe just being afraid of going faster and making big changes, but that’s the main reason why they can’t compete with Kotlin and JetBrains.

I also see Kotlin being supported by a more dynamic and open-minded part of the community, many of them avid for changes in the JVM world!

What I see happening in the near future is that Kotlin will keep coming up with nice features and innovation that will improve the language experience even further. The more developers embrace Kotlin in the Open Source community, the faster this change will take place. Languages like Java will keep their slow but steady pace, but I don’t see them being able to catch up with Kotlin.

JetBrains has proven with their success with IntelliJ IDEA, becoming the favourite IDE among developers worldwide, that they understand developers and their needs. This is and it will be the cornerstone in their success with Kotlin as well; understand your “customers” and they’ll love your product.

We’ve also seen that the number of companies interested in Kotlin or partnering with JetBrains has been growing in the last few years. For instance, Bellsoft and JetBrains agreed a strategic collaboration in 2019 in which Bellsoft provides security patches and critical updates to JetBrains runtime, a fork of JRE used in all language IDEs. These are the same updates and the same process as for BellSoft’s own distribution called Liberica JDK. That’s one of the reasons why I’d recommend using Liberica JDK with Kotlin due to their close relationship and collaboration.

I can only see this kind of trend of mutual collaborations become more active and intense in the following years. 

In terms of growth, the dynamic and fast-paced environment provided by a company like JetBrains could be a very important factor in the upcoming years. As I mentioned earlier, I think JetBrains knows what developers want, they understand developers very well and they’ve proven that by building the most popular IDE in many years. This important experience and their clear determination in achieving their goals could be a decisive factor for a big success of Kotlin in the long run. Who knows, it might be time to break with the past and bet on the future after all!

Conclusion

In summary, I think the future of Kotlin will depend on how willing and open-minded the community is to firmly bet on Kotlin and cut their ties with other languages. Considering the beauty and simplicity of the language and its full interoperability with Java, I don’t see a clear reason to not give it a chance. Kotlin is a language that could improve a team’s productivity and the readability of the codebase; on top of that we can do that gradually and take minimal risks.

Up ↑

Take a look at our recommended books!

Ok!
X
%d bloggers like this: