Early, but not an adopter
8 years ago, I was doing my internship at Info Support, my current employer. During that time, I got invited to join the rest of the team to my first meetup, the Visug Event April 2013. The main speaker that evening was Hadi Hariri developer advocate at Jetbrains.
Hadi gave 2 talks that evening. The first was about the Silver Bullet Syndrome. The other talk was about this new programming language Jetbrains was working on. That programming language…was Kotlin.
Since that time, a lot has happened for Kotlin:
- Kotlin has added support for imperative, functional and object oriented programming styles;
- Google has promoted Kotlin to a first class language for Android development;
- Venkat has written a book on it, which is a clear signal it is a programming language worth looking into;
I’ve been spending some time with Kotlin lately. Here are some of the things I like about it…so far 😇
Null Safety
Ah NullPointerException, my old nemesis. Any reference variable could be null so some codebases are equivalent to a game of minesweeper. One wrong call… and boom! NPE!
In Kotlin however, the compiler is here to help you out. Variables are either explicitly non-null or nullable, where non-null is the default 😍. This ensures you can’t assign null to a non-nullable type.
val firstName: String = "Tom" // Non-null by default
firstName = null // compilation error <3
val firstName: String? = "Tom" // type? = nullable type
firstName = null // ok
This distinction is very powerful as it forces developers to consider nullability way more than in more lenient programming languages like Java. Luckily, there are ways to work with nullable types without transforming them into non-nullables.
val firstName: String? = "Tom"
# Safe Calls
val firstNameLength = firstName?.length // Returns length or null;
# Elvis Operator (Give default value if null)
val firstNameLength = firstName?.length ?: 0 // Returns length or 0;
# !! Operator (Aka, "I <3 NPE's"-strategy)
val firstNameLength = firstName!!.length // Returns length or throws NPE;
If you ever doubt about which one of the 3 strategies above you should avoid… remember that the !!-operator is basically your code screaming out in pain. 😱 Unless if you hate your code, your collegues and, most importantly, your own sanity, I’d avoid that one.
Null Safety felt unfamiliar, even limiting, in the beginning. But once I got used to it, I really fell in love with it. I even started to get frustrated with Java, never knowing where an “NPE-bomb” might be hidden in the minefield of code. Yeah yeah, we have Optional in Java… but it’s pretty verbose and doesn’t have a concise way to do “Safe Calls”. And don’t forget… the reference itself could still be “null”, so Optional might just be giving us a safe sense of security.
More at: https://kotlinlang.org/docs/null-safety.html#nullable-types-and-non-null-types
Type Aliasses
I don’t know about you, but I really like it when terminology in code matches “the real world”.
For this blog post I’m assuming everything around us is real… a topic for another blog entry… maybe…
What really annoys me in this aspect are generic collections. While they are usefull for reusability, I feel the readability of code suffers because of them.
Say I’m building an application in which users can “host a party” (remember parties? Those weird events where people get together and… mingle.). A domain object could be a ‘guestlist’. One way to implement this in Java would be to create a generic list, and use a good variable name to signify what this “list of people” actually is meant to represent.
List<Person> guestList
While I see this code frequently, when I think about it a bit longer, it doesn’t seem right. Primitive Obsession is one thing developers (especially the DDD crowd!) often complain about. Instead of using primitives, we wrap those primitives into more descriptive classes. For example: Instead of using String.class to store an emailadres, create a class EmailAdres and use that instead.
So why wouldn’t we give Collections the same treatment. Depending on the context, I see value in wrapping Collections into dedicated descriptive classes. This might result in the following class definition. 👇
// Java: As an extension of the ArrayList class
public class GuestList extends ArrayList<Person> {
// Rest of class omited
}
Some people might argue it’s overkill to do this. In some cases I wholeheartedly agree. In other cases, I wonder if they really think it’s overkill because it actually is overkill, or because the way to achieve it is pretty verbose in Java. Would they still consider it overkill if it was easier to achieve?
Maybe we’ll get the answer to that question if more people start using Kotlin! Why? Because Kotlin makes this pretty easy by using a Type Alias. The example below shows how you can make a collection type more expressive in Kotlin.
typealias GuestList = ArrayList<Person>
// create a new guestlist
val person : Person = // initialize a Person
val guestList = GuestList()
guestList.add(person) // Add a person to the list
// Use the type as a function parameter
fun printGuestList(list: GuestList) {
// code omited.
}
I love how easy Kotlin makes it to make even the most generic of classes more expressive. While I would warn against overusing this feature… when used in the right context, it can be extremely powerful! Is it just syntactic sugar? Sure, but doesn’t sugar add a ton of flavour? :-)
Zen-level verbosity
I’ve been coding Java for quite some years now, so I got used to (or mentally manipulated to accept 😕) the verbosity of the language. Even when trying to keep my code concise and my IDE limited (IntelliJ Zen Mode), Java will always be a bit noisy. I never realized exactly how noisy until I coded a simple “Hello Spring Boot” application in Kotlin. Just have a look at this.
@RestController
@RequestMapping("/java")
public class JavaHelloController {
String greeting;
GreetingService greetingService;
public JavaHelloController(@Value("${greeting}") String greeting,
GreetingService greetingService) {
this.greeting = greeting;
this.greetingService = greetingService;
}
@GetMapping("hello")
public String getHello() {
return String.format("%s %s", greeting, greetingService.message());
}
}
If we code the same in Kotlin, we get the following.
@RestController
@RequestMapping("/kotlin")
class KotlinHelloController(@Value("\${greeting}") val greeting: String,
val greetingService: GreetingService) {
@GetMapping("hello")
fun hello():String {
return "$greeting ${greetingService.message()}"
}
}
While unfamiliar at first, once I got used to the syntax, Kotlin feels more “zen” then I had originally anticipated. The shorter constructor syntax and the string interpolation remove a lot of the bloat Java brings with it. All I can say for now: “I like this… a lot!”
So much more good stuff!
There is a more good stuff to talk about but that will be for another day! I want to get some more experience with Kotlin before I comment on other features, but Data Classes (aka Lombok Killers) look like a great language feature. Be sure to take a look at the official docs and let me know what your favorite features are!
Until the next time...lots of 💖
Tom