Kotlin is so nice – it prevents bugs 🐛 before you add them…
Tags: kotlin, bugs, tooling
Published: 2020-06-19 15:57:03

You all know those awesome colleagues who don't let go - after your team fixes a bug, they go the extra mile and make changes that no team member will fall into that trap again. They prevent future developers from making the same mistakes!

Well, Kotlin and IntelliJ are doing exactly that - for millions of developers worldwide! These are just a few examples of how Kotlin prevents bugs before you even make them.

## No more `switch/case`

If you start with Java (or C or C++), you'll make this mistake a few times before learning how to avoid it. Let's see some Java code:

```java
static void printOperatingSystem(OperatingSystem operatingSystem) {
    switch (operatingSystem) {
        case windows:
            System.out.println("Windows");
        case mac:
            System.out.println("Mac");
        case linux:
            System.out.println("Linux");
    }
}
```

If you call `printOperatingSystem(OperatingSystem.linux)`, this will print `Linux`. But if you call it with `printOperatingSystem(OperatingSystem.windows)`, this will actually print:

```plain
Windows
Mac
Linux
```

That's because we need to put a `break` at the end of each case to not fall into the next one. For many developers, this might seem like a simple mistake - because once you learn about it, you learn to avoid it, and it goes into your muscle memory.

But what if the language would not let you do these mistakes in the first place? Let's see how you would write this in Kotlin:

```kotlin
fun printOperatingSystem(operatingSystem: OperatingSystem) {
    when (operatingSystem) {
        OperatingSystem.windows -> println("Windows")
        OperatingSystem.mac -> println("Mac")
        OperatingSystem.linux -> println("Linux")
    }
}
```

No more `break` to forget, and it's easier to read as well.

## Equality instead of instance check

In Java, if you use `==`, this will actually check the instance of an object - not the content. What's really weird is that when you try this out with a simple check like in the third line of the next example, this will actually 'work' - because Java will optimize the Strings to exist only once in memory:

```java
String one = "1234567";
String two = "1234567";
System.out.println("one == two: " + (one == two)); // prints true

String three = two.replace('7', '8').replace('8', '7'); // that's still the same
System.out.println("two == three: " + (two == three)); // prints false
```

Modern IDE tools thankfully warn you about this by giving you a message *String values are compared using '==', not 'equals()'* and an auto-fix, but it would be nice if the language itself would choose the most-used equality operator as the default. Kotlin does:

```kotlin
val one = "1234567"
val two = "1234567"
println("one == two: " + (one == two)) // prints true

val three = two.replace('7', '8').replace('8', '7')
println("two == three: " + (two == three)) // true, as we would expect :-)
```

## NullPointerExceptions

This is old news for Kotlin devs, but still: every time you avoid nullable types in your codebase prevents these bugs from happening. Every time you hit the `.` on a variable or a long expression and Kotlin tells you: "Wait a second, actually that could be null!" is another bug being prevented.

This is a win-win-win: Users love stable applications, developers love if they don't have to go on a multi-hour bug hunt how that `null` value actually made it into the database, and product owners love it as well when developers can use their time to implement new features (and not go on multi-hour bug-hunts instead).

Here's some Java code:

```java
String city = user.getAddress().getCity();
```

But actually, the user does not have an address, so `getAddress()` can return null. If you didn't develop the best practice to use `@NonNull` and `@Nullable` annotations, these bugs are going to happen. And they do - all the time. Tony Hoare did call the null reference a [billion dollar mistake](https://en.wikipedia.org/wiki/Tony_Hoare#Apologies_and_retractions) for a reason.

Kotlin will save you here:

![Kotlin preventing you from introducing a NullPointerException](https://dev-to-uploads.s3.amazonaws.com/i/f78lmvrrvmyicx6pkimc.png)

The beauty about these prevented errors is how Kotlin and the IDE do this. They prevent you from making these mistakes *while you are typing*. And usually, it feels so nice when they offer you an auto-fix directly at your fingertips.

## Coroutines

I have to say I made this mistake in Java quite more times than I thought I would. Let's see some Java code:

```java
new Thread() {
    @Override
    public void run() {
        // do something cool here
    }
}.run();
```

Do you see the mistake? Of course, I called `run()` instead of calling `start()`. So the code will just do the thing you defined in `run` - but it will not do that on the thread, like you expected it to. Today, IntelliJ and other IDEs give you a warning here - but wouldn't it be nice if you didn't need to learn the difference in the first place? What if the tooling would prevent you from making this mistake?

With Kotlin Coroutines, the IDE will write an error directly when you try to call a suspending function from your regular, non-suspending code:

![IDE showing a compile error when calling a suspend function from non-suspend context](https://dev-to-uploads.s3.amazonaws.com/i/mwqu338cf0qrcs7xdnr2.png)

EDIT: I want to highlight a [good comment](https://dev.to/androiddeveloperlb/comment/10kmo) by [AndroidDeveloperLB](https://dev.to/androiddeveloperlb): Of course Coroutines are something very different than Java Threads. He mentioned that there is a nice [thread()](https://kotlinlang.org/api/latest/jvm/stdlib/kotlin.concurrent/thread.html) utility method in Kotlin's stdlib. With that, you can write the code above correctly like this (and automatically starting the thread as well):

```kotlin
thread {
    // do something cool here
}
```

I think this is another great example how Kotlin makes existing APIs easier to handle - with less code and less possible bugs! ❤️

## Code you don't have to write/generate is code without bugs (usually)

When we write code, we will make mistakes. That's even true for Kotlin code. 😉

But it's nice if we don't have to wrote some code (mostly boilerplate) in the first place. More often than you'd like, you'll find projects with code like the following (even if tools like Lombok exist, some projects don't use them).
Of course, this is a really bad legacy project, so let's say there are no unit tests either.

I added an error in the Java code – let's see if you can spot it!

```java
class User {

    private final String firstName;
    private final String lastName;
    private final Address address;
    private final PhoneNumber phoneNumber;

    User(String lastName, String firstName, Address address, PhoneNumber phoneNumber) {
        this.firstName = firstName;
        this.lastName = lastName;
        this.address = address;
        this.phoneNumber = phoneNumber;
    }

    public String getFirstName() {
        return firstName;
    }

    public String getLastName() {
        return firstName;
    }

    public Address getAddress() {
        return address;
    }

    public PhoneNumber getPhoneNumber() {
        return phoneNumber;
    }

    @Override
    public boolean equals(Object o) {
        if (this == o) return false;
        if (o == null || getClass() != o.getClass()) return false;
        User user = (User) o;
        return Objects.equals(firstName, user.firstName) &&
                Objects.equals(address, user.address) &&
                Objects.equals(phoneNumber, user.phoneNumber);
    }

    @Override
    public int hashCode() {
        return Objects.hash(firstName, lastName, address, phoneNumber);
    }

    @Override
    public String toString() {
        return "User{" +
                "firstName='" + lastName + '\'' +
                ", lastName='" + firstName + '\'' +
                ", address=" + address +
                ", phoneNumber=" + phoneNumber +
                '}';
    }
}
```

Did you find it? There, in the `equals` method, the first line should actually return `true` in the instance check. Because right now, it will wrongfully return false for the same instance. Wait, you found a different error? That's because I actually tricked you a little. There are actually two errors here! There, in the `getLastName` method, I wrote `return firstName`.

Oh wait, there are more: I exchanged `firstName` and `lastName` in the constructor as well. That's not an error in itself, but I'll guarantee you that some colleagues will have a small look at the class, see the members, and instantly conclude that `firstName` is the first parameter of the constructor. And they'll wish me to the ground of the deepest sea when they find out what I've done. 😇

Oh, and in the `toString()` method, this will actually print the last name as the first and vice-versa. Good luck finding that bug.

And did I mention that I removed the `lastName` from the `equals` method because that felt like a good idea to fix an entirely unrelated function, that now depends on this mistake to be there? These things happen all the time. At least I kept the `hashCode()` function correctly. But with a developer like me, you can never know.

All in all, there are 5 errors in this code! And that with only 4 members. And in big projects, you will only find out about these bugs later on when some user reports a weird behavior. And then the bug-hunt begins.

With 20 or more members, it becomes extremely common to forget to re-generate this code, or manually add the appropriate lines in the specific functions. Sometimes, some of the necessary changes get lost due to someone not resolving a Git merge conflict properly. 😱

Long story short: not having to write this code in the first place is a blessing! In Kotlin:

```kotlin
data class User(
    val firstName: String,
    val lastName: String,
    val address: Address,
    val phoneNumber: PhoneNumber
)
```

There. Constructor, `equals`, `hashCode`, `toString`, getters, setters, `copy` function, `@NonNull` annotations - all done for you under the hood. Not giving someone like me the opportunity to mess this up. 😅

## Sealed classes with `when`

In the Java `switch/case` and `if/else` world, it's easy to forget to handle a particular case. Let's say we have this Java code:

```java
CreateUserResult result = createUser(credentials);

if (result instanceof Success) {
    User user = ((Success) result).getUser();
    System.out.println("User " + user.username + " created");
} else if (result instanceof OtherError) {
    String message = ((OtherError) result).getMessage();
    System.out.println("Other error occurred: " + message);
}
```

This creates a user, prints it out on success, and prints the error if it couldn't be created. The type `CreateUserResult` is actually a Kotlin sealed class, and one developer added another case that is not handled yet by the Java code - but the IDE does not show any errors. The type is defined like so:

```kotlin
sealed class CreateUserResult {
    class Success(val user: User) : CreateUserResult()
    class OtherError(val message: String) : CreateUserResult()
    class UserDoesAlreadyExist(val username: String) : CreateUserResult()
}
```

So there actually is another type, called `UserDoesAlreadyExist`, which handles the special case that the username is taken already. Let's say the Java code above was written with a Kotlin `when` statement, the developer who added `UserDoesAlreadyExist` would have gotten an error instantly and could have fixed it directly:

```kotlin
val result = createUser(credentials)
val message = when (result) {
    is Success -> "User ${result.user.username} created"
    is OtherError -> "Other error occurred: ${result.message}"
}
println(message)
```

The `when` is used as an expression here, and that way Kotlin says it must be exhaustive. So this will show up in your IDE:

![when must be exhaustive](https://dev-to-uploads.s3.amazonaws.com/i/kzzkzwd936ho93sitp35.png)

Easy enough, the IDE can add the remaining branches automatically for you and it's easy to add the remaining code:

```kotlin
val message = when (result) {
    is Success -> "User ${result.user.username} created"
    is OtherError -> "Other error occurred: ${result.message}"
    is UserDoesAlreadyExist -> "Error: user ${result.username} does already exist"
}
```

Another possible bug, prevented before it could even ship to production!

## Final thoughts

These are only a few examples how Kotlin prevents bugs from happening. But actually, Kotlin is full of these. If you use Kotlin: what are your favorite examples of Kotlin preventing bugs before you could even write them? I'd be happy to read your comments!

If you didn't start using Kotlin yet, I hope you got a small taste of how it could make your developer life better! Because not adding bugs 🐛🐛🐛 in the first place is much better than having to spend days or weeks in hunting them down.

Have an awesome Kotlin! 🎉

If you liked this post, please give it a ❤️, click the `+FOLLOW` button below and follow me on [Twitter](https://twitter.com/mreichelt)! This will help me stay motivated to create many more of these posts! 😊

*Cover photo by [Louis Tsai](https://unsplash.com/@louis993546) on [Unsplash](https://unsplash.com/photos/lqcvMiBABHw).*