The Kotlin Komparisons series takes a feature implemented in Java and rewrites it in Kotlin to demonstrate improvements, language-features, migration paths, and interesting refactors.
Full code is available at: https://github.com/scottmeschke/KotlinKomparisons
Kotlin Is Official
Last Wednesday May 17, 2017 was a great birthday.
Google and the Android Team announced official support for Kotlin.
To help the community grow and embrace Kotlin, I’m starting this series.
What we are building:
We need to build a data repository for login settings.
We have to provide both observing and updating login details and a login method for the user.
We also need to persist the data over sessions.
The Java Implementation:
We’ll start with a simple value class for the login details (username and email).
There is a ton of required boilerplate here. Nullability annotations, value-type methods, toString(), and a simple constructor with assignment.
Let’s move on to the implementation of the repository itself.
The API is quite simple, but the implementation doesn’t feel great for a few reasons.
- Guava-Precondition Null checks boilerplate and nullability annotations
- Ultra-verbose anonymous classes
- Persistence-keys are in the same namespace/level as the repository
- Similar-ish logic for initialization of the relays from persistence.
- Again very similar logic for writing to persistence and then updating the relays.
The Kotlin Komparison:
Above is the entire equivalent of our LoginDetails java class.
The data modifier gives us all of the value type requirements (hashCode(), equals(), toString()).
Our fields are now properties defined as read only with val.
Notice we get the nullablity of the values built into the type system, compiler, and class definition. No annotations, or runtime checks needed.
We also have default parameters, named arguments, and read-only properties.
Let’s move on to the repository logic.
Wow, what a ridiculous difference. The outside-of-parenthesis lambda as last parameter syntax makes the code pleasant to read.
Our declarative withInitIfEmpty(), and writeThenForward() methods, are just extension functions on BehaviorRelay, and RxPaperBook.
Notice that the first function is marked “inline” which actually inserts the function body at compilation where it is used in source.
This means we get the niceness of the lambda-functional style, with the performance of doing the conditional and just calling the method normally.
No allocation of an anonymous class needed.
Bonus: Less Files
The Kotlin implementation is more readable, less boilerplate, less error-prone, and more declarative.
Another fantastic feature of kotlin is top-level declarations. We can put multiple classes/interfaces/functions in a single file.
I particularly like doing this for interfaces. Instead of three separate files for some data repository, just one file with the interface, the application implementation, and a fake for testing.
For the full code check out the Kotlin Komparisons repository on Github.
Next in the Kotlin Komparisons Series:
Enjoy the goodies?
Going to transform some Java to Kotlin?
Have burning-hot fiery opinions about some random sentence above?
I’d love to hear from you, leave your comments below!