A problem like destructuring declarations

I’m a huge fan of Kotlin — it’s powerful, concise and makes it fun to write code. But even our biggest heroes aren’t perfect and there’s one thing I don’t like about Kotlin: destructuring declarations. Let’s see why, and what they do!

What are destructuring declarations?

Destructuring declarations are a convenient way of destructuring an object into multiple variables. So what does that mean? Let’s take a look at this simple data class:

data class Song(
  val artist: String, 
  val name: String
)

What if we want to get a variable of the artist and the name from this? One option is to just create two variables in two lines:

val artist = song.artist
val name = song.name

There’s quite a lot of repetition here. A more concise way is to create a destructuring declaration:

val (artist, name) = song

Both snippets of code will do the exact same thing — assign both the artist and name properties to a variable each. So this is great! With a destructuring declaration we only need to write one line of code and don’t have to repeat the variable name.

Where’s the catch?

Let’s say we also want to add an album to the song:

data class Song(
  val artist: String, 
  val album: String, 
  val name: String
)

With this change the two snippets we wrote will actually behave differently.

// 1
val artist = song.artist
val name = song.name// 2
val (artist, name) = song

In the first example, the artist variable will refer to the artist property and the name variable will refer to the name property. In the second snippet, though the name variable will refer to the album property. Wait… what? 🤨

Let’s take a look at what’s happening here. The compiled code of a destructuring declaration will actually address the componentN functions on the class, like this:

val artist = song.component1()
val name = song.component2()

So after we added a new property, component2 actually refers to the album instead of the name as it’s the second component.

So should I use them?

Using destructuring declarations is convenient and looks clean, but there is some danger attached to it. If you’re aware of it you can mitigate some of the danger by ensuring your code is well tested. Whenever you update the properties your tests should fail. If you miss to test a usage it might result into unexpected behaviour, though.

Another way to avoid some mistakes is to always specify the type of each variable:

val (artist: String, name: String) = song

This won’t help in this specific example, as the new property is aString as well, but it can be helpful in some cases.

My rule of thumb is to only use destructuring declarations for classes that shouldn’t change any properties, like Pair or Triple:

val (key, value) = getPair()

This is still quite useful, but doesn’t come with the risk of reading the wrong properties. In general, anything in the Kotlin framework should be safe, as new versions of Kotlin will be backwards compatible.

What is your take on destructuring declarations? Which Kotlin features do you dislike?

A problem like Maria

Findings about Android and Kotlin by Maria Neumayer

Maria Neumayer

Written by

European living in London. Android Developer at @DeliverooEng. Tweeting at @marianeum.

A problem like Maria

Findings about Android and Kotlin by Maria Neumayer