Discovering Kotlin

Some time ago, I realized that basically all my career is centered around Java, Java-based tools and Java frameworks. Sure, as a software engineer I’ve always believed that the particular programming language is not important; the logic and your problem solving skills matter more. But believing wasn't making it true for me, since all my projects, at work and at home, were in Java.

Enter Kotlin.

My interest in Kotlin was sparked the day it was announced by JetBrains. I've been using IntelliJ IDEA since 2006, and I’ve used PHP Storm to edit my blog from time to time. I've been fond of this company for many years because of the wonderful development tools they produce. So, clearly, Kotlin had to be another awesome product. But only after seeing Josh Long's "Bootiful Kotlin" presentation at the Spring IO conference in Barcelona, did I decide that this was a programming language I needed to learn.

So when my first training day at NCR came, I knew exactly what to do.

What I needed:

  • a good tutorial.
  • a computer — I have a Mac, this will do ;).
  • a little time — roughly 8 hours.
  • an idea — NCR's representative animal is the bear, so let's save bear instances to a database.

The Kickoff

I installed the Kotlin compiler. I didn’t really need it, since I was using IntelliJ IDEA, but I wanted to explore the command line as well. I created my new Kotlin project and wrote my first few lines of code:

fun main(args: Array<String>) {
println("Hello world!")
val s = sum(2,3)
println("Result $s")
}

fun sum(a: Int, b: Int) = a + b

And I compared it to the same code written in Java:

import static java.lang.System.*;

public class HelloWorld {
public static void main(String[] args) {
out.println("Hello World!");
int s = sum(2,3);
out.println("Result " + s);
}

public static int sum(int a, int b) {
return a+b;
}
}

And for completeness, I compared it to the same code in Scala:

object HelloWorld {
def main(args: Array[String]): Unit = {
println("Hello world!")
val s = sum(2, 3)
println(s"Result ${s}")
}

def sum(a: Int, b:Int) = a + b
}

And concluded that the Kotlin version was definitely the most compact and readable.

After that, I spent about two hours reading about the Kotlin syntax, and was able to compile a list of things that impressed me (I am not so easy to impress, btw):

  • Default immutability.
  • Everything is by default not null, so no more NPEs.
  • Less "{}" and no more ";".
  • Simple syntax, no more getters, setters, no constructors needed.
  • No "new" operator.
  • Ranges.
  • Placeholders.
  • Inline functions.
  • Awesome type casting and type inference.
  • The when expression.

I am just scratching the surface, but I am already in love.

The code

After writing more code to do trivial things like traversing arrays and manipulating strings, I had enough confidence to write my application.

I wanted to start fast, so I used Spring Initializr to generate my project.

This gave me a functioning Gradle project with all the plugins I needed to get started.

The entry-point Application.kt file looked like this:

package com.td

import org.springframework.boot.autoconfigure.SpringBootApplication
import org.springframework.boot.runApplication

@SpringBootApplication
class Application

fun main(args: Array<String>) {
runApplication<BearkDemoApplication>(*args)
}

Next, I created an entity class in a file named Bear.kt:

package com.td.ent

import com.td.Species
import javax.persistence.Entity
import javax.persistence.GeneratedValue
import javax.persistence.GenerationType
import javax.persistence.Id

@Entity
data class Bear(var name: String = "",
var species: Species = Species.BLACK,
@Id @GeneratedValue(strategy = GenerationType.AUTO)
var id: Long = 0)

No setters, getters, toString() or constructor needed. Pretty neat, huh?

And since I wanted to limit the species of bears to just a few, I created an enum. Behold the Species.kt file:

package com.td

enum class Species(val code: Int) {
BLACK(0),
BROWN(1),
POLAR(2),
ASIATIC(3),
ANDEAN(4),
PANDA(5),
SLOTH(6),
SUN(7)
}

Next came some Spring Data JPA:

package com.td.repo

import com.td.ent.Bear
import org.springframework.data.jpa.repository.JpaRepository

interface BearRepository : JpaRepository<Bear, Long>

Boom! A repository. Look ma', no curly braces!

Then I could modify the Application class to create a few Bear instances and save them to the database before extracting them and printing them just to prove it all worked.

package com.td

import com.td.ent.Bear
import com.td.repo.BearRepository
import org.slf4j.Logger
import org.slf4j.LoggerFactory
import org.springframework.boot.CommandLineRunner
import org.springframework.boot.autoconfigure.SpringBootApplication
import org.springframework.boot.runApplication
import org.springframework.context.annotation.Bean

val logger: Logger = LoggerFactory.getLogger(Application::class.java)

@SpringBootApplication
class Application {

@Bean
fun init(repo: BearRepository) = CommandLineRunner {
logger.info("Saving a few bears ...")
repo.save(Bear("Silverhair", Species.BROWN))
repo.save(Bear("Silverlocks", Species.ASIATIC))
repo.save(Bear("Goldenlocks", Species.POLAR))
repo.save(Bear("Goldilocks", Species.POLAR))

logger.info("Bears found with findAll():")
logger.info("-------------------------------")

repo.findAll().forEach {logger.info(it.toString())}

logger.info("All done.")
}
}

fun main(args: Array<String>) {
val ctx = runApplication<Application>(*args)
ctx.close()
}

We run the application and our bears are created:

INFO 25701 — — [ main] com.td.ApplicationKt : Starting ApplicationKt on WGBIG185029–21L with PID 25701 (…)
INFO 25701 — — [ main] com.td.Application : Bear(name=Silverhair, species=BROWN, id=1)
INFO 25701 — — [ main] com.td.Application : Bear(name=Silverlocks, species=ASIATIC, id=2)
INFO 25701 — — [ main] com.td.Application : Bear(name=Goldenlocks, species=POLAR, id=3)
INFO 25701 — — [ main] com.td.Application : Bear(name=Goldilocks, species=POLAR, id=4)
INFO 25701 — — [ main] com.td.Application : All done.

Conclusion

I think Kotlin is the future for a lot of Java projects. Its readable and concise syntax will greatly reduce development time.

Also, since it can be easily integrated with Java code, the migration of a Java project can be done gradually while the project is still being shipped to the clients with little risk of failures.