Use Parceler to put your parcels on a diet

kotlin-parcelize is a great tool. Its simple to use and it helps in avoiding writing a lot of boilerplate code. There are times though that we need to take control of writing and reading to/from the parcel. One of these times is to cut down a few bytes from it (TransactionTooLargeException I am looking at you).

Meet me in the middle

@Parcelize takes full control and creates everything. Without the annotation, the developer has to do this on her own. Parceler lives in the middle of this spectrum. The plugin will create all necessary methods and classes but the actual write and read to/from the parcel will be the developer’s responsibility.

Without a Parceler the write/read looks like this:

public void writeToParcel(@NotNull Parcel parcel, int flags) {
Intrinsics.checkNotNullParameter(parcel, "parcel");
parcel.writeInt(this.id);
parcel.writeString(this.description);
parcel.writeString(this.priority.name());
parcel.writeParcelable(this.status, flags);
Attachment var10001 = this.attachment;
if (var10001 != null) {
parcel.writeInt(1);
var10001.writeToParcel(parcel, 0);
} else {
parcel.writeInt(0);
}
}
@NotNull
public final Task createFromParcel(@NotNull Parcel in) {
Intrinsics.checkNotNullParameter(in, "in");
return new Task(
in.readInt(),
in.readString(),
(Priority)Enum.valueOf(Priority.class, in.readString()),
(Status)in.readParcelable(Task.class.getClassLoader()),
in.readInt() != 0 ? (Attachment)Attachment.CREATOR.createFromParcel(in) : null
);
}

with a Parceler like this (where the Companion object is acting as a Parceler):

public void writeToParcel(@NotNull Parcel parcel, int flags) {
Intrinsics.checkNotNullParameter(parcel, "parcel");
Companion.write(this, parcel, flags);
}
@NotNull
public final Task createFromParcel(@NotNull Parcel in) {
Intrinsics.checkNotNullParameter(in, "in");
return Task.Companion.create(in);
}

Cutting down parcel’s size

The above-generated code is based on Task

@Parcelize
class Task(
val id: Int,
val description: Description,
val priority: Priority = Normal,
val status: Status = NotStarted,
val attachment: Attachment? = null
) : Parcelable
@Parcelize
class Attachment(val path: String) : Parcelable
@Parcelize
@JvmInline
value class Description(val value: String) : Parcelable
enum class Priority {
Low,
Normal,
High
}
sealed class Status : Parcelable {
@Parcelize
object NotStarted : Status()
@Parcelize
object InProgress : Status()
@Parcelize
class Completed(val completedAt: LocalDate) : Status()
}

which, creates a parcel of 248 bytes. The code does not do anything weird. All primitives, which include the value classes too, are well handled. So nothing to do here. This leaves parcelables and enums.

But first, let’s use a Parceler. This means that writing and reading to/from the parcel has to be implemented by us. For starters, we will do exactly what the generated code does except for the attachment property. For that, the generated code uses parcelable’s methods and CREATOR. In the Parceler we don’t have access to the CREATOR.

companion object : Parceler<Task> {
override fun create(parcel: Parcel): Task {
return Task(
parcel.readInt(),
Description(parcel.readString()!!),
Priority.valueOf(parcel.readString()!!),
parcel.readParcelable(Status::class.java.classLoader)!!,
parcel.readParcelable(Attachment::class.java.classLoader)
)
}
override fun Task.write(parcel: Parcel, flags: Int) {
with(parcel) {
writeInt(id)
writeString(description.value)
writeString(priority.name)
writeParcelable(status, flags)
writeParcelable(attachment, flags)
}
}
}

That leaves us with writeParcelable and readParcelable but now the parcel’s size is bigger, it is 328 bytes! Turns out that writeParcelable first writes the parcelable’s name and then the parcelable itself!

We need to use the CREATOR. After searching around I found parcelableCreator. A function that solved a well-known problem and will be added to Kotlin 1.6.20.

inline fun <reified T : Parcelable> Parcel.readParcelable(): T? {
val exists = readInt() == 1
if (!exists) return null
return parcelableCreator<T>().createFromParcel(this)
}
@Suppress("UNCHECKED_CAST")
inline fun <reified T : Parcelable> parcelableCreator(): Parcelable.Creator<T> =
T::class.java.getDeclaredField("CREATOR").get(null) as? Parcelable.Creator<T>
?: throw IllegalArgumentException("Could not access CREATOR field in class ${T::class.simpleName}")
fun <T : Parcelable> Parcel.writeParcelable(t: T?) {
if (t == null) {
writeInt(0)
} else {
writeInt(1)
t.writeToParcel(this, 0)
}
}

This allows us to revert the size increment back to 248 bytes

companion object : Parceler<Task> {
override fun create(parcel: Parcel): Task {
return Task(
//
parcel.readParcelable()
)
}
override fun Task.write(parcel: Parcel, flags: Int) {
with(parcel) {
//
writeParcelable(attachment)
}
}
}

Use enum’s ordinal than its name. The generated code writes enum’s name so that it can use Enum.valueOf when reading. We can write an int instead by using enum’s ordinal

companion object : Parceler<Task> {
override fun create(parcel: Parcel): Task {
return Task(
//
parcel.readEnum()
)
}
override fun Task.write(parcel: Parcel, flags: Int) {
with(parcel) {
//
writeEnum(priority)
}
}
}
inline fun <reified T : Enum<T>> Parcel.readEnum(): T {
return enumValues<T>()[readInt()]
}
inline fun <reified T : Enum<T>> Parcel.writeEnum(t: T) {
writeInt(t.ordinal)
}

and use Enum.values() when reading. This drops the parcel’s size to 232 bytes.

Skip a class’s parcelable implementation. This of course depends on each implementation.
For instance, Status is a sealed class that only one of its children has a construction parameter. We can leverage this by writing only that value

companion object : Parceler<Task> {
override fun create(parcel: Parcel): Task {
return Task(
//
parcel.readStatus()
)
}
override fun Task.write(parcel: Parcel, flags: Int) {
with(parcel) {
//
writeStatus(status)
}
}
}
fun Parcel.readStatus(): Status {
return readLong().let { value ->
when (value) {
0L -> NotStarted
1L -> InProgress
else -> Completed(LocalDate.ofEpochDay(value))
}
}
}
fun Parcel.writeStatus(status: Status) {
when (status) {
is Completed -> writeLong(status.completedAt.toEpochDay())
InProgress -> writeLong(1)
NotStarted -> writeLong(0)
}
}

this drops the parcel’s size to 136 bytes!

Conclusion

Fortunately, the generated code does a pretty good job and making any optimizations is not that common. But when needed Parceler and parcelableCreator are great tools.

PS: for measuring the parcel’s size I was using this method

fun Parcelable.sizeInBytes(): Int {
val parcel = Parcel.obtain()
try {
parcel.writeParcelable(this, 0)
return parcel.dataSize()
} finally {
parcel.recycle()
}
}

which was shamelessly stolen from Guardian’s TooLargeTool.

I think that data classes help in violating the YAGNI principle

Let me ask you something. You are the reviewer in a PR that creates a simple calculator which needs to know how to add numbers. Just that. There are no reasons to make us think that the calculator will need more functionality.

Despite that the PR includes a calculator that can add, subtract and multiply. What do you do as a reviewer?

I want to believe that you will, respectfully, discuss the removal of the extra functionality otherwise the calculator will violate the YAGNI principle and add (a) more code for the developers to maintain and (b) more ways to couple the project with the calculator. And all that with no immediate benefit.

Do we need all that functionality?

The same goes with data classes. There is no reason to have a class that can be uniquely identified by all of its properties if we don’t use its instances this way. There is no reason to have an extra getter for every property if we don’t use, extensively, the destructuring declaration. There is no reason to have a copy mechanism if we never copy instances!

If it is there it is going to be used

I recently removed the data keyword from one of our oldest classes and I noticed that many of our newest tests started to fail in compilation. The compiler could not find the copy method which was used to create dummy values from other dummy values by changing one property per test.

When to create a data class?

Here is my thought process when trying to decide the type of class I’ll use:

Q: Is this class anything but a domain entity or value object?

A: Then a simple class is just fine.

Q: Is this class a domain entity? Meaning that it can be uniquely identified by a subset of its properties (ex: an id)?

A: Then a simple class with an implementation of equals/hashCode will be enough.

Q: Is this a value object? Meaning that it can be uniquely identified by all of its properties?

A: Yes.

Q: How many properties?

A: One. Then a value class is a must.

Q: Are you sure its just one?

A: Turns out its more! We’ll use a data class.

Don’t do it for the test

Our test code is the first consumer of our production code. Changing the production code, in this case change/create a class as data, to write more quickly a couple of tests will result in having tests that can easily break every time the production code changes since the tests know too much about the code’s internals and not its behavior.

Create a seam for testing using default values and function references

I learned about seams after reading Micheal Feathers’s book Working Effectively with Legacy Code. In essence a seam is a way to circumvent code that makes testing hard or even impossible.

For example, lets say we have a class that checks if a given task is valid. For reasons that do not interest us that same class makes a connection to another service and sends some data to it. That connection alone makes the class hard to test since we need to have and maintain a connection to that service during testing:

class TaskChecker {
fun check(task: Task): CheckResult {
if (isNotCreatedInCurrentWeek(task)) return Invalid
if (isResolved(task)) return Invalid
if (isNotAssigned(task)) return Invalid
return Valid
}
private fun isNotAssigned(task: Task): Boolean {
if (task.assignedTo != Nobody) return false
val connection = Connection()
val assigner = TaskAssigner(connection)
assigner.add(task)
return true
}
//
}

In this example, isNotAssigned() makes the necessary checks but also sends the task to TaskAssigner so if we want to write some tests for TaskChecker we need to make sure that assigner is up and running.

Object seams

According to Mr Feathers there are three types of seams. The one that fits our case is called object seam and we are going to use it in order to bypass entirely making a connection and talking to the assigner.

Following the book’s example we end up with this:

class TestingTaskChecker : TaskChecker() {
override fun sendTaskToAssigner(task: Task) {
// do nothing
}
}
open class TaskChecker {
fun check(task: Task): CheckResult {
if (isNotCreatedInCurrentWeek(task)) return Invalid
if (isResolved(task)) return Invalid
if (isNotAssigned(task)) return Invalid
return Valid
}
private fun isNotAssigned(task: Task): Boolean {
if (task.assignedTo != Nobody) return false
sendTaskToAssigner(task)
return true
}
protected open fun sendTaskToAssigner(task: Task) {
val connection = Connection()
val assigner = TaskAssigner(connection)
assigner.add(task)
}
//
}

which does exactly what we want since it provides a way to write tests that do not involve the assigner. We just need to use TestingTaskChecker in our tests and we are good to go.

The downside with this approach is that we had to open our class which might not meet the project’s standards.

Function reference

Lets see what we can do without opening the class.

Just like before we need to extract the behavior that we want to override to its own method but this time we are also going to assign this method to a value and use the value in the calling site:

class TaskChecker {
private val safeSendTaskToAssigner: (Task) -> Unit = ::sendTaskToAssigner
fun check(task: Task): CheckResult {
if (isNotCreatedInCurrentWeek(task)) return Invalid
if (isResolved(task)) return Invalid
if (isNotAssigned(task)) return Invalid
return Valid
}
private fun isNotAssigned(task: Task): Boolean {
if (task.assignedTo != Nobody) return false
safeSendTaskToAssigner(task)
return true
}
private fun sendTaskToAssigner(task: Task) {
val connection = Connection()
val assigner = TaskAssigner(connection)
assigner.add(task)
}
//
}

isNotAssigned() will keep talking with the assigner only this time it does it through safeSendTaskToAssigner.

Default value

Having this function reference means that we can force isNotAssigned() to change its behavior by simply assigning a new value to safeSendTaskToAssigner! And this is what we are going to do:

class TaskChecker(
seamToAssigner: ((Task) -> Unit)? = null
) {
private val safeSendTaskToAssigner: (Task) -> Unit = seamToAssigner ?: ::sendTaskToAssigner
fun check(task: Task): CheckResult {
if (isNotCreatedInCurrentWeek(task)) return Invalid
if (isResolved(task)) return Invalid
if (isNotAssigned(task)) return Invalid
return Valid
}
private fun isNotAssigned(task: Task): Boolean {
if (task.assignedTo != Nobody) return false
safeSendTaskToAssigner(task)
return true
}
private fun sendTaskToAssigner(task: Task) {
val connection = Connection()
val assigner = TaskAssigner(connection)
assigner.add(task)
}
//
}

By default the seam is null which leads in having safeSendTaskToAssigner referencing the original behavior allowing the entire project to keep working as before without any additional changes to other files.

If now we pass a non null value then it gets assigned to safeSendTaskToAssigner and ends up being called instead of sendTaskToAssigner. This way we remove the communication from our flow allowing us to finally write some tests.

Testing

All we need to do is to write our tests by simply creating a checker with a do nothing seam:

@Test fun `a task that is not assigned is invalid`() {
val task = Task(AssignedTo.Nobody)
val taskChecker = TaskChecker {} // <– check with seam
val actual = taskChecker.check(task)
assertThat(actual, equalTo(Invalid))
}

Use suspendCoroutine to connect callbacks and coroutines

Whenever we need to write asynchronous code we tend to use callbacks which allow us to trigger an action and, instead of waiting for it to finish, get notified through the callback for the action’s completion. Coroutines change that and help us write asynchronous code but in a sequential way.

This means that instead of writing code like this:

fun main() {
downloadTasks(
object : DownloadCallback {
override fun onDownloaded(tasks: List<Task>) {
printTasks(tasks)
}
}
)
}
interface DownloadCallback {
fun onDownloaded(tasks: List<Task>)
}
private fun downloadTasks(callback: DownloadCallback) {
println("Downloading…")
// code that makes a network call and returns the list of tasks
callback.onDownloaded(listOf(Task(1), Task(2), Task(3)))
}
private fun printTasks(tasks: List<Task>) {
tasks.forEach { task -> println(task.id) }
}

we can write it like this:

fun main(): Unit = runBlocking {
launch {
val tasks = downloadTasks()
printTasks(tasks)
}
}
private suspend fun downloadTasks() {
println("Downloading…")
// code that makes a network call and returns the list of tasks
return listOf(Task(1), Task(2), Task(3))
}
private fun printTasks(tasks: List<Task>) {
tasks.forEach { task -> println(task.id) }
}

But what do we do when there is no easy way to remove callbacks from existing code or when we use a third party library that is not coroutines ready? This is where suspendCoroutine comes to save the day.

suspendCoroutine

suspendCoroutine is a function that does exactly what is says. It suspends the coroutine that it was called from and provides a way to resume it.

Lets have an example. The code here:

fun main(): Unit = runBlocking {
launch {
print("1 ")
print("2 ")
print("3 ")
print("4 ")
println("Done!")
}
}

simply prints 1 2 3 4 Done!. If we change it to:

fun main(): Unit = runBlocking {
launch {
print("1 ")
print("2 ")
print("3 ")
suspendCoroutine<Unit> { }
print("4 ")
println("Done!")
}
}

it will print 1 2 3 and then it will just wait. We suspended the coroutine but we did not resume it. To do so we will use the continuation instance that suspendCoroutine provides:

fun main(): Unit = runBlocking {
launch {
print("1 ")
print("2 ")
print("3 ")
suspendCoroutine<Unit> { continuation ->
print("")
continuation.resume(Unit)
}
print("4 ")
println("Done!")
}
}

now it prints 1 2 3 … 4 Done!. The coroutine printed the first three numbers, got suspended, while being suspended another block of code got executed and printed the dots and then resumed the coroutine allowing it to print the final number and done.

Continuation adapter

Back to our first example. Lets say that downloadTasks cannot be changed. We still need to call it and provide a callback for its results.

What we need to do is to suspend the coroutine, call downloadTasks to.. well.. download the tasks and provide a callback that upon completion it will resume the coroutine with the tasks at hand.

To achieve that we first need to create an adapter that will connect the callback with a continuation:

private class ContinuationAdapter(
private val continuation: Continuation<List<Task>>
) : DownloadCallback {
override fun onDownloaded(tasks: List<Task>) {
continuation.resume(tasks)
}
}

and then call suspendCoroutine:

fun main(): Unit = runBlocking {
launch {
val tasks = suspendCoroutine<List<Task>> { continuation -> downloadTasks(ContinuationAdapter(continuation)) }
printTasks(tasks)
}
}

That’s it. The adapter resumes the coroutine by providing the tasks that are then returned to the suspension point.

One more thing

Along side suspendCoroutine there is also suspendCancellableCoroutine which provides a cancellable continuation. That means that in addition of resuming we can also execute code upon cancellation:

fun main(): Unit = runBlocking {
val job = launch(Dispatchers.IO) {
val tasks = downloadAllTasks()
printTasks(tasks)
}
delay(100)
job.cancel()
}
private suspend fun downloadAllTasks(): List<Task> {
return suspendCancellableCoroutine { continuation ->
continuation.invokeOnCancellation { print("Cancelled…") }
downloadTasks(ContinuationAdapter(continuation))
}
}
private class ContinuationAdapter(
private val continuation: Continuation<List<Task>>
) : DownloadCallback {
override fun onDownloaded(tasks: List<Task>) {
continuation.resume(tasks)
}
}
interface DownloadCallback {
fun onDownloaded(tasks: List<Task>)
}
private fun downloadTasks(callback: DownloadCallback) {
println("Downloading…")
sleep(150) // simulate network latency
val tasks = listOf(Task(1), Task(2), Task(3))
callback.onDownloaded(tasks)
}
private fun printTasks(tasks: List<Task>) {
tasks.forEach { task -> println(task.id) }
}
to improve the readability of the code we can hide the suspension inside another function

this will print Downloading… and then Cancelled…

Debounce user’s input in android without using rx or coroutines

There are myriads of blog posts that showcase how to debounce the user’s input by using either rxjava or coroutines. The question is how to implement such a functionality when the project does not have these dependencies?

Debounce

First of all, what is debounce? In essence debounce is a pattern that helps in preventing the repeated execution of a block of code. It does that by adding a delay between two consecutive calls to the block and by cancelling the first call when the second is requested. For example:

When the user types in her keyboard, every key stroke results in calling a block of code that renders what she typed:

without debounce

By having debounce when the user types, each call gets delayed and cancelled if a new one gets requested resulting in rendering the entire text when the user is finished typing:

with debounce

Before starting

We are going to add the debounce functionality to the example above. The initial code is very simple:

class MainActivity : AppCompatActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
val bindings = ActivityMainBinding.inflate(layoutInflater)
setContentView(bindings.root)
with(bindings) {
userInput.doAfterTextChanged { text ->
userResult.text = text
}
}
}
}

where userInput is the EditText that the user writes in and userResult is the TextView that the user’s input gets rendered.

Adding the debounce functionality

There are two ways to do this. The first uses java’s Timer and TimerTask and the second android’s Handler. Both of them help in implementing the same algorithm:

  1. on every key stroke we first cancel any previous call request
  2. then we setup some kind of timer for our delay and the code that needs to be called
  3. and finally, when the time passes, we make the call
Timer and TimerTask

We can use Timer to schedule the execution of a block of code after a given delay. The provided block must be a TimerTask which will be added to a queue and when the time comes it will be executed in a background thread. This last part is very important since we cannot set anything UI related there. That’s why we use the Timer just for the delay part and then we use the view’s Handler to execute the actual code to the main thread:

class MainActivity : AppCompatActivity() {
private var timer = Timer()
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
val bindings = ActivityMainBinding.inflate(layoutInflater)
setContentView(bindings.root)
with(bindings) {
userInput.doAfterTextChanged { text ->
timer.cancel() // cancel any previous delay
timer = Timer() // schedule a new one
timer.schedule(500L) {
// we are in a background thread here
userInput.handler.post { userResult.text = text }
}
}
}
}
}

Recommended when there is a need to do some intensive work before returning back to the main thread but besides that it could be an overkill. That’s why it might be better to use the view’s Handler for both the delay and the execution.

Handler

The Handler class packs the same functionality as the Timer. We can use it to add a block of code (being added as a callback in a Message instance) in a queue (the handler’s MessageQueue) and when the time comes the message gets removed from the queue and its callback gets executed in the thread that the handler was created in. In our case, since we are using the view’s handler we can be sure that the execution will take place in the main thread.

The Handler class provides methods for both adding and removing from the queue. So what we end up with is something like this:

class MainActivity : AppCompatActivity() {
private var counter = 0
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
val bindings = ActivityMainBinding.inflate(layoutInflater)
setContentView(bindings.root)
with(bindings) {
userInput.doAfterTextChanged { text ->
userInput.handler.removeCallbacksAndMessages(counter)
userInput.handler.postDelayed(500L, ++counter) { userResult.text = text }
}
}
}
}

One note about the counter variable. For removing a particular message we need to identify it and to do that we can use what is called a token. When posting for delay, we also provide an id in the form of a counter so that we can request its deletion later on.

Debounce extension

Since we are in Kotlin land and to avoid having the above code duplicated with various global counters for identification we can create an extension function that will pack everything together and help us in having a reusable component and more readable code:

fun EditText.debounce(delay: Long, action: (Editable?) -> Unit) {
doAfterTextChanged { text ->
var counter = getTag(id) as? Int ?: 0
handler.removeCallbacksAndMessages(counter)
handler.postDelayed(delay, ++counter) { action(text) }
setTag(id, counter)
}
}

So our code ends up looking like this:

class MainActivity : AppCompatActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
val bindings = ActivityMainBinding.inflate(layoutInflater)
setContentView(bindings.root)
with(bindings) {
userInput.debounce(500L) { text -> userResult.text = text }
}
}
}

which is very similar to the original code but provides the debounce functionality!

Lets build a coroutine

Ever since Kotlin introduced coroutines there has been a plethora of posts that showcased their usage in networking or multi threading scenarios. Inevitably many developers when asked what a coroutine is their first answer was “a lightweight thread” or “a way to write clean asynchronous code”. Unfortunately this is not the definition of a coroutine but rather a couple of things that a coroutine can help us with.

Routine (aka Subroutine)

So what is a coroutine? To answer that we must first understand what a routine is.

A routine is nothing more than the common function that we all use every day. Its main characteristic is that its execution must come to a completion before returning to the caller. It does not hold any state and calling it multiple times is like calling it for the first time.

An example:

// a routine:
fun saveUserTasks(userId: Int) {
val user = loadUser(userId)
println("user loaded")
val tasks = loadTasks(user)
println("tasks loaded")
saveTasks(tasks)
}
// when called multiple times:
fun main() {
println("Call #1:")
saveUserTasks(7)
println("Call #2:")
saveUserTasks(7)
println("Call #3:")
saveUserTasks(7)
println("done!")
}
// its like calling it for the first time:
/*
Call #1:
loading a user…
user loaded
loading tasks for provided user…
tasks loaded
saving provided tasks…
Call #2:
loading a user…
user loaded
loading tasks for provided user…
tasks loaded
saving provided tasks…
Call #3:
loading a user…
user loaded
loading tasks for provided user…
tasks loaded
saving provided tasks…
done!
*/
Coroutine

On the other hand a coroutine (a concept that is way older than Kotlin) is a function that can hold its current state allowing us to pause and resume its execution at certain suspension points. This can be of great help when we need to write concurrent code, meaning, when we need to run two tasks at the same time by executing small parts of those tasks one at a time.

For example, if we have task A broken in two parts (A1, A2) and task B broken in two parts as well (B1, B2), we can write code that executes first A1, then B1, then A2 and finally B2.

Building a coroutine

Our goal is to convert the above routine into a coroutine and to do so we need to have a blueprint:

fun saveUserTasks(userId: Int) {
val user = loadUser(userId)
println("user loaded")
// save loaded user
// pause execution
// resume execution
// restore saved user
val tasks = loadTasks(user)
println("tasks loaded")
// save loaded tasks
// pause execution
// resume execution
// restore saved tasks
saveTasks(tasks)
}

So, step #1 is to separate the states into blocks of code and to do that we are going to use the when statement:

fun saveUserTasks(userId: Int, state: Int) {
when (state) {
0 -> {
val user = loadUser(userId)
println("user loaded")
// save loaded user
// pause execution
}
1 -> {
// resume execution
// restore saved user
val tasks = loadTasks(user) // ERROR: unknown user
println("tasks loaded")
// save loaded tasks
// pause execution
}
2 -> {
// resume execution
// restore saved tasks
saveTasks(tasks) // ERROR: unknown tasks
}
}
}

the problem here is that the code does not compile since the states do not communicate and are missing important information.

To fix it we are moving to step #2 where the state parameter will be used as a vessel to pass data from one state to the other:

class State(
var label: Int = 0,
var result: Any? = null
)
fun saveUserTasks(userId: Int, state: State) {
when (state.label) {
0 -> {
val user = loadUser(userId)
println("user loaded")
state.result = user
// pause execution
}
1 -> {
// resume execution
val user = state.result as User
val tasks = loadTasks(user)
println("tasks loaded")
state.result = tasks
// pause execution
}
2 -> {
// resume execution
val tasks = state.result as List<Task>
saveTasks(tasks)
}
}
}

the code now has distinct states that share data but it cannot resume correctly since there is no way to move from one state to the other.

Step #3 addresses that by updating the state’s label allowing the function to resume from where it was paused:

fun saveUserTasks(userId: Int, state: State) {
when (state.label) {
0 -> {
val user = loadUser(userId)
println("user loaded")
state.result = user
state.label = 1
return
}
1 -> {
// resume execution
val user = state.result as User
val tasks = loadTasks(user)
println("tasks loaded")
state.result = tasks
state.label = 2
return
}
2 -> {
// resume execution
val tasks = state.result as List<Task>
saveTasks(tasks)
}
}
}

and that’s it. saveUserTasks is now a coroutine where every call executes a small part of the function allowing us to pause and resume the task:

fun main() {
val state = State()
println("Call #1:")
saveUserTasks(7, state)
println("Call #2:")
saveUserTasks(7, state)
println("Call #3:")
saveUserTasks(7, state)
println("done!")
}
// results in:
/*
Call #1:
loading a user…
user loaded
Call #2:
loading tasks for provided user…
tasks loaded
Call #3:
saving provided tasks…
done!
*/

Concurrency

We did manage to convert a routine to a coroutine but the example did not show the power of using coroutines which is concurrency. Lets change that.

To make things a little bit easier we are going to package a few common functionalities together

abstract class Coroutine {
var isFinished: Boolean = false
private set
protected val state: State by lazy { State() }
protected fun resumeWith(result: Any) {
state.label++
state.result = result
}
protected fun <T> restore(): T {
return state.result as T
}
protected fun finish() {
state.label++
isFinished = true
}
protected class State(
var label: Int = 0,
var result: Any? = null
)
}

which allows us to create these

class SaveUserTasks : Coroutine() {
operator fun invoke(userId: Int) {
saveUserTasks(userId, state)
}
private fun saveUserTasks(userId: Int, state: State) {
when (state.label) {
0 -> {
val user = loadUser(userId)
println("user loaded")
resumeWith(user)
return
}
1 -> {
val user = restore<User>()
val tasks = loadTasks(user)
println("tasks loaded")
resumeWith(tasks)
return
}
2 -> {
val tasks = restore<List<Task>>()
saveTasks(tasks)
finish()
}
}
}
}
class ApplyDownloadedSettings : Coroutine() {
operator fun invoke() {
applyDownloadedSettings(state)
}
private fun applyDownloadedSettings(state: State) {
when (state.label) {
0 -> {
val settings = downloadSettings()
println("settings downloaded")
resumeWith(settings)
return
}
1 -> {
val settings = restore<Settings>()
applySettings(settings)
println("setting applied")
finish()
}
}
}
}

This way we can call the two functions as such:

fun main() {
val saveUserTasks = SaveUserTasks()
val applyDownloadedSettings = ApplyDownloadedSettings()
while (!saveUserTasks.isFinished || !applyDownloadedSettings.isFinished) {
saveUserTasks(7)
applyDownloadedSettings()
}
println("done!")
}
/*
loading a user…
user loaded
downloading settings…
settings downloaded
loading tasks for provided user…
tasks loaded
applying settings…
setting applied
saving provided tasks…
done!
/*

As you can see the two functions are being executed concurrently. First we load the user, then we download the settings, then we load the user’s task and so on and so forth!

Further reading

My goal with this post was to give you a better understanding on what a coroutine is and I did it by using the concept of a finite state machine. The same concept that Kotlin’s implementation of coroutines uses.

For digging in the actual implementation of coroutines I suggest you take a look at a couple of great posts that helped me a lot in grasping the concept:

The memento design pattern in Kotlin

I started playing with the memento pattern for a use case I was researching when I realized that the Kotlin implementation had a, potentially, show stopper in comparison with the Java one:

I could not use a private property from within the same file

Why was that a show stopper? We’ll see, but first, what is the memento pattern?

Memento pattern

This pattern is a good way to implement a functionality that helps in restoring previous states. One good example is the undo in our text editors. You can write, edit, delete and then, by hitting undo, take each action back.

There are three main ingredients for this pattern:

  1. the originator that holds the current state and creates snapshots of itself,
  2. the memento that, in essence, is the snapshot with perhaps some additional metadata and
  3. the caretaker that orchestrates the backup/restore of the state

So in our example the originator is the editor which knows what the text is, the carets position etc, the memento a copy of those values and the caretaker can be the interface between the user and the editor.

Java implementation

Lets try to have an overly simplified version of the above example in Java:

public final class Editor {
private final List<String> text;
private int caretPosition;
public Editor() {
this.text = new ArrayList<>();
this.caretPosition = 0;
}
public void write(final String sentence) {
text.add(sentence);
caretPosition = calculateCaretPositionInEndOf(text);
}
public void edit(final int index, final String newSentence) {
text.remove(index);
text.add(index, newSentence);
final List<String> subText = text.subList(0, index + 1);
caretPosition = calculateCaretPositionInEndOf(subText);
}
public void delete(final int index) {
final List<String> subText = new ArrayList<>(text.subList(0, index));
text.remove(index);
caretPosition = calculateCaretPositionInEndOf(subText);
}
public void render(final Screen screen) {
final String allText = String.join("", text);
screen.render(allText);
screen.renderCaretAt(caretPosition);
}
public Memento backup() {
return new Memento(text, caretPosition);
}
public void restore(final Memento memento) {
text.clear();
text.addAll(memento.text);
caretPosition = memento.caretPosition;
}
private int calculateCaretPositionInEndOf(final List<String> lines) {
return lines.stream().mapToInt(String::length).sum() + 1;
}
public static final class Memento {
private final List<String> text;
private final int caretPosition;
public Memento(List<String> text, int caretPosition) {
this.text = new ArrayList<>(text);
this.caretPosition = caretPosition;
}
}
}

Here the editor, besides manipulating text, is able to produce snapshots of its state in a way that only itself can access the state’s values. The Memento class might be public, in order to allow the caretaker to handle instances of it, but its fields are private and only the originator can read them.
A great way to copy something while having the smallest possible API surface and maximum privacy.

As a matter of fact, here is the caretaker and its usage:

class UI(
private val screen: Screen
) {
private val editor = Editor()
private val backups = mutableListOf<Memento>()
fun write(text: String) {
backups.add(0, editor.backup())
editor.write(text)
editor.render(screen)
}
fun edit(index: Int, text: String) {
backups.add(0, editor.backup())
editor.edit(index, text)
editor.render(screen)
}
fun delete(index: Int) {
backups.add(0, editor.backup())
editor.delete(index)
editor.render(screen)
}
fun undo() {
val memento = backups.removeAt(0)
editor.restore(memento)
editor.render(screen)
}
}
fun main() {
val screen = StdoutScreen()
val ui = UI(screen)
with(ui) {
write("Hello, there! ")
write("How are you? ")
write("I hope you feel good 🙂")
edit(1, "Kotlin! ")
delete(1)
undo()
undo()
undo()
undo()
undo()
}
}
/* which produces this:
Hello, there! |
Hello, there! How are you? |
Hello, there! How are you? I hope you feel good :)|
Hello, there! Kotlin! |I hope you feel good 🙂
Hello, there! |I hope you feel good 🙂
Hello, there! Kotlin! |I hope you feel good 🙂
Hello, there! How are you? I hope you feel good :)|
Hello, there! How are you? |
Hello, there! |
|
/*

As you can see the UI uses the editor to write, edit, delete but before that it saves a backup with the editor’s state in order to restore it every time the user hits undo!

Kotlin implementation

So lets move originator and memento to Kotlin. Ctrl+Alt+Shift+K and boom.. we have a problem:

Kotlin, in contrast with Java, does not allow accessing private properties when in the same file.

What do we do? Well we can always make the properties public:

class Memento(text: List<String>, caretPosition: Int) {
val text: List<String>
val caretPosition: Int
init {
this.text = ArrayList(text)
this.caretPosition = caretPosition
}
}

but this way we, indirectly, expose the editors state:

Another way to implement the pattern is to have Memento as an interface with no state for the public API and have a private implementation of it for internal usage:

class Editor {
//
fun backup(): Memento {
return ActualMemento(text, caretPosition)
}
fun restore(memento: Memento) {
if (memento !is ActualMemento) return
text.clear()
text.addAll(memento.text)
caretPosition = memento.caretPosition
}
//
interface Memento
private class ActualMemento(text: List<String>, caretPosition: Int) : Memento {
val text: List<String>
val caretPosition: Int
init {
this.text = ArrayList(text)
this.caretPosition = caretPosition
}
}
}

this way we do not expose any state but we do open a bit our API. We now have an interface that can be implemented and given to the restore() function.

Inner classes

Fortunately Kotlin has inner classes. An inner class can access the outer class’s members but, most importantly, can be extended only from within the outer class. This means that this:

class Editor {
//
fun backup(): Memento {
return ActualMemento(text, caretPosition)
}
fun restore(memento: Memento) {
memento as ActualMemento
text.clear()
text.addAll(memento.text)
caretPosition = memento.caretPosition
}
//
open inner class Memento
private inner class ActualMemento(text: List<String>, caretPosition: Int) : Memento() {
val text: List<String>
val caretPosition: Int
init {
this.text = ArrayList(text)
this.caretPosition = caretPosition
}
}
}

checks all our boxes. We keep the originator’s state private and our overall API small!

I prefer not to use the keyword “it”

And the reason is simple:

I want to be as explicit as possible and allow the reader of my code to have an uninterrupted flow.

Think about it. Every time you encounter the it keyword you do, a quick, conversion between what you see and what it represents. Personally I do it even in very small lambdas, imagine if you are two or three lines deep in a lambda and you see an it:

val animals = listOf("Lion", "Penguin", "Giraffe", "Whale", "Shark")
val usernames = animals.map {
val randomNumber = Random.nextInt(0, 10)
val randomCharacter = listOf("!", "@", "$", "%", "#")[Random.nextInt(0, 5)]
"$it$randomCharacter$randomNumber"
}

It might not look much in this simple example but read it now with an explicit value:

val animals = listOf("Lion", "Penguin", "Giraffe", "Whale", "Shark")
val usernames = animals.map { animalAsBase ->
val randomNumber = Random.nextInt(0, 10)
val randomCharacter = listOf("!", "@", "$", "%", "#")[Random.nextInt(0, 5)]
"$animalAsBase$randomCharacter$randomNumber"
}

You don’t have to do a mental translation and it also provides some details regarding the format of username.

This last part can make the code even more readable since it allows us to describe the values we use:

values.map { rawValue -> Name.of(rawValue) }

this hints that (a) values list does not contain usable data and (b) the of function will perform some kind of cleaning

Two reasons why you should add a return type in your functions in Kotlin

Kotlin’s compiler is clever enough to figure out on its own what is the return type of a function but this does not mean that we should over use it and here is why:

Help the compiler to help us

By adding a return type in a function we instruct the compiler to expect and force that type (by a compiler error). On the other hand if we allow the compiler to infer the type, if something changes in the function’s body and the return type is not the one intended by the author, the compiler will follow along thinking that we know what we are doing!

Help the reader [to help us]

We write something once but it gets read multiple times. So it is our responsibility to make it as readable, explicit and quick in the eye as we can. In every case that we omit a return type the reader of our code has to do the calculations and extract the type on her own which, depending on the complexity, will take time and effort. You might say that a few seconds is not a big deal but in comparison with the zero seconds of having a type it is a lot.

Also not all reading takes place in an IDE that provides hints and colorful help. Our PR reviewers will probably read out code directly from GitHub or GitLab. By making them change context to figure something out we break their flow and concentration.

So, when should we use it

Never! In my humble opinion the only valid place is in small (one line), private methods that either construct something, so the use of the constructor along side the = sign trick the mind:

private fun createName(value: String) = Name(value)

or the return type is clearly obvious:

private fun isCompleted(task: Task) = task.status in listOf(COMPLETED, CANCELLED)

A use case of using chain of responsibility pattern to scale strategy

Lets say we have a simple application that executes certain actions dictated by an external service.

More particular the external service sends a response that looks like this:

class Response(
val action: String,
val value: String
)

the supported actions are:

interface Action {
val name: String
fun execute(response: Response)
}
class Print : Action {
override val name: String = "print"
override fun execute(response: Response) {
println("printing ${response.value}")
}
}
class Log : Action {
override val name: String = "log"
override fun execute(response: Response) {
println("logging ${response.value}")
}
}
class WriteToFile : Action {
override val name: String = "write_to_file"
override fun execute(response: Response) {
println("writing to file ${response.value}")
}
}

and there is an executor to help as translate the response to an actual action execution:

class ActionExecutor {
private val allActions = mutableMapOf<String, Action>()
fun addAction(action: Action) {
allActions[action.name] = action
}
fun executeByResponse(response: Response) {
val action = allActions[response.action]
action?.execute(response)
}
}

This is an implementation of the Strategy Pattern where every strategy is a certain action allowing us to add as many actions as we want as long as there is a one-to-one relation with what the response sends:

fun main() {
val executor = createActionExecutor()
executor.executeByResponse(Response("print", "leonidas"))
executor.executeByResponse(Response("log", "kotlin"))
executor.executeByResponse(Response("write_to_file", "leonidas loves kotlin"))
}
private fun createActionExecutor(): ActionExecutor {
return ActionExecutor().apply {
addAction(Print())
addAction(Log())
addAction(WriteToFile())
}
}

The problem

One day the external service decides to add a print error action but it does not do it by having a new action value. Instead it decides to have an is error flag which must be taken under consideration when the action value is print!

So the response is now this:

class Response(
val action: String,
val value: String,
val isError: Boolean = false
)

leading us into having an if in the print action’s code

class Print : Action {
override val name: String = "print"
override fun execute(response: Response) {
if (response.isError) {
System.err.println("printing (in error stream) ${response.value}")
return
}
println("printing ${response.value}")
}
}

which defeats the purpose of the strategy pattern and violates the SRP. Each strategy should do one thing and one thing only. By having an if in the strategy we allow it to implement two actions thus having two reasons to change.

Adding a chain

What we need is a way to allow the representation of a single action value from multiple strategies where each one implements a unique action depending on the values of the response.

This is where the Chain of Responsibility Pattern comes in helping as into having multiple actions tied together, passing the response to each other until one of them can execute it.

There are two ways to implement the pattern depending on the size and state of your project.

Using inheritance

If you have a small project with just a few actions and you don’t mind touching many files you can use inheritance and have each action containing the next in the chain:

abstract class BaseAction(
private val nextAction: Action?
) : Action {
override fun execute(response: Response) {
nextAction?.execute(response)
}
}
class Print : Action {
override val name: String = "print"
override fun execute(response: Response) {
println("printing ${response.value}")
}
}
class PrintInErrorStream(
nextAction: Action?
) : BaseAction(nextAction) {
override val name: String = "print"
override fun execute(response: Response) {
if (response.isError) {
System.err.println("printing (in error stream) ${response.value}")
return
}
super.execute(response)
}
}

which can be used as such:

fun main() {
val executor = createActionExecutor()
executor.executeByResponse(Response("print", "leonidas"))
executor.executeByResponse(Response("log", "kotlin"))
executor.executeByResponse(Response("write_to_file", "leonidas loves kotlin"))
executor.executeByResponse(Response("print", "$&#$@#", isError = true))
}
private fun createActionExecutor(): ActionExecutor {
return ActionExecutor().apply {
addAction(PrintInErrorStream(Print())) // first try to print in error and the in simple
addAction(Log())
addAction(WriteToFile())
}
}
Using composition

If we do not wish to change any of the existing actions then composition is the only way.

What we need is a way to wrap an existing action in an object that will (a) hold the next action in the chain and (b) decide which action will be executed, the wrapped or the next one:

class ChainAction(
private val action: Action,
private val canExecute: (Response) -> Boolean
) : Action {
private var nextAction: Action? = null
override val name: String = action.name
override fun execute(response: Response) {
if (canExecute(response)) {
action.execute(response)
return
}
nextAction?.execute(response)
}
fun or(action: ChainAction): ChainAction {
nextAction = action
return this
}
}
fun Action.asChain(canExecute: (Response) -> Boolean): ChainAction =
ChainAction(this, canExecute)
view raw chain_action.kt hosted with ❤ by GitHub

Using ChainAction results in this:

fun main() {
val executor = createActionExecutor()
executor.executeByResponse(Response("print", "leonidas"))
executor.executeByResponse(Response("log", "kotlin"))
executor.executeByResponse(Response("write_to_file", "leonidas loves kotlin"))
executor.executeByResponse(Response("print", "$&#$@#", isError = true))
}
private fun createActionExecutor(): ActionExecutor {
val printInErrorStream = PrintInErrorStream().asChain { response -> response.isError }
val justPrint = Print().asChain { true }
return ActionExecutor().apply {
addAction(printInErrorStream.or(justPrint))
addAction(Log())
addAction(WriteToFile())
}
}

This way we can scale the strategy pattern both vertically, one strategy per action value, and horizontally, one strategy per action value sub cases.