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:
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.
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:
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:
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:
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:
classMainActivity : AppCompatActivity() {
overridefunonCreate(savedInstanceState:Bundle?) {
super.onCreate(savedInstanceState)
val bindings =ActivityMainBinding.inflate(layoutInflater)
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:
on every key stroke we first cancel any previous call request
then we setup some kind of timer for our delay and the code that needs to be called
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:
classMainActivity : AppCompatActivity() {
privatevar timer =Timer()
overridefunonCreate(savedInstanceState:Bundle?) {
super.onCreate(savedInstanceState)
val bindings =ActivityMainBinding.inflate(layoutInflater)
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:
classMainActivity : AppCompatActivity() {
privatevar counter =0
overridefunonCreate(savedInstanceState:Bundle?) {
super.onCreate(savedInstanceState)
val bindings =ActivityMainBinding.inflate(layoutInflater)
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) {
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.
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:
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:
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:
the originator that holds the current state and creates snapshots of itself,
the memento that, in essence, is the snapshot with perhaps some additional metadata and
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:
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:
classUI(
privatevalscreen:Screen
) {
privateval editor =Editor()
privateval backups = mutableListOf<Memento>()
funwrite(text:String) {
backups.add(0, editor.backup())
editor.write(text)
editor.render(screen)
}
funedit(index:Int, text:String) {
backups.add(0, editor.backup())
editor.edit(index, text)
editor.render(screen)
}
fundelete(index:Int) {
backups.add(0, editor.backup())
editor.delete(index)
editor.render(screen)
}
funundo() {
val memento = backups.removeAt(0)
editor.restore(memento)
editor.render(screen)
}
}
funmain() {
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 :)|
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:
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:
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:
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)]
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:
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:
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!
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:
abstractclassBaseAction(
privatevalnextAction:Action?
) : Action {
overridefunexecute(response:Response) {
nextAction?.execute(response)
}
}
classPrint : Action {
overrideval name:String="print"
overridefunexecute(response:Response) {
println("printing ${response.value}…")
}
}
classPrintInErrorStream(
nextAction:Action?
) : BaseAction(nextAction) {
overrideval name:String="print"
overridefunexecute(response:Response) {
if (response.isError) {
System.err.println("printing (in error stream) ${response.value}…")
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:
classChainAction(
privatevalaction:Action,
privatevalcanExecute: (Response) ->Boolean
) : Action {
privatevar nextAction:Action?=null
overrideval name:String= action.name
overridefunexecute(response:Response) {
if (canExecute(response)) {
action.execute(response)
return
}
nextAction?.execute(response)
}
funor(action:ChainAction): ChainAction {
nextAction = action
returnthis
}
}
fun Action.asChain(canExecute: (Response) ->Boolean): ChainAction =
I decided to take a look at GitHub Actions so for the past week I’ve been watching and reading everything about it. I even wrote a post, an Introduction to GitHub Actions. What I found really interesting is the fact that you can write an action using the language you feel more comfortable with. And so I did!
There are three ways to create an action but only the one using Docker allows us to use the language we want.
In all three ways the main two ingredients are:
the action’s code
the action’s metadata, a file called action.yml which is placed in the root folder of your project and defines how the action will run and what inputs/outputs it has.
In our case there is also a third ingredient, a Dockerfile or a docker image which is used by the action’s runner to create a container and execute the action’s code inside it. All you have to do is to make sure that the action’s executable parts are being copied in the container and that are called upon its start.
The runner makes sure that the working space is being mounted to the container (in the state that it was just before the action is started) along with all the environment variables and the inputs the action needs. You can read more in the documentation.
Ktlint PR comments
Action’s code
The action has three distinct parts.
The first part is responsible for using GitHub’s REST API to collect all of the PR’s changes and then keep those that are in Kotlin files and were added or modified. For that I used kscript and I was able to leverage all the libraries that I was accustomed to, like Retrofit and Moshi. When I was happy with the resulted script I used its --package option to create a standalone binary and copy it in the action’s Docker image.
The second part is a combination of bash commands that execute the ktlint binary by passing to it the results of the first part. Ktlint is being called with the --reporter=json parameter in order to create a JSON report.
The third and final part is again a kscript script that uses the report created before and GitHub’s REST API to make a PR line comment for every ktlint error that is part of the PR’s diff. Again a standalone binary was created and put in the image.
Note:
I like kscript since I can write things fast, easy and with all the libraries that I know but I also like writing test first and that proved to be quite difficult. So what I ended up doing was to act as if I was in a Kotlin project. I created my tests (using all my favorites like junit5, hamkrest and MockWebServer) and from that I created .kt files with the proper functionality. And for having a script I created a .kts file where I defined the external dependencies and included the .kt files:
From the start what I wanted for this action was to be as autonomous as possible leaving very little responsibilities to the consumer and allowing her to just plug it in and watch it play.
For that the only input the action needs is a token, for allowing the kscript scripts to communicate with the API, which will most likely be the default secrets.GITHUB_TOKEN making the action’s usage as simple as adding the following lines in your workflow:
A lot of things must happen in order to have the action ready to run. Sdkman, Kotlin and kscript must be installed, the code needs to be retrieved from the repository and both kscript scripts have to be packaged. On top of that ktlint must be downloaded and placed in the proper path.
For all that, and to shave a few seconds from the action, I decided to have an image that has everything ready. So I created a workflow that gets triggered every time there is a push in the main branch, builds and packs everything in an image and pushes the result to Docker Hub.
So now the action simply uses that image to run a container without any other ceremonies.
Note:
Before using Docker Hub I tried to use GitHub Packages but it turns out that public is not that public* since it requires an authentication to retrieve a package.
Summary
That’s it! An action for having ktlint’s report as comments in your PR. A result of trial and error since I wrote it while learning about actions but I hope that someone might find it useful. If you do let me know!
I’ve used scratch files in IntelliJ IDEA and Android Studio but I think that can be found in all of Jetbrain’s products.
What are they?
Scratch files are files that don’t get tracked by the version control system, can be created at any given time and, most importantly, get bind to the IDE and not the project that is currently open.
How do I create them?
The simplest way is to hit ctrl+alt+shift+insert. If you can’t remember it press shift twice and start writing scratch, you will be presented with the action of creating a new one.
The next step is to choose what kind of file you want to create and this is where it gets interesting since you can choose from a plethora of file types. From plain text, to markdown, Kotlin, JSON, XML, ruby and many many more!
How do I use them?
By choosing the file’s type you choose how the IDE will behave when you are working on it, so if you create a scratch.json and paste some json in it you can format it accordingly. Or if you create a scratch.md you can start writing in markdown and have a preview of your work.
But the most powerful aspect of those files is when you create code related ones. If, for example, you create a scratch.kts file and start writing some Kotlin in it, you will see your code being run on the fly presenting to you its result:
TDDish
You can even work test first if you need to figure out a quick algorithm and have your test run in every change you make!
I usually start with an assertThat function and a failing test and go from there:
Today I came across a piece of code that looked like this:
fun printAll(vararg names: String?) {
names.forEach { name -> println(name) }
}
and noticed that the IDE did not complain about using names without checking if it is null names?.forEach { ... }!
After decompiling Kotlin’s bytecode I saw that no matter what type I use (String? or String) the java code was the same:
public static final void printAll(@NotNull String... languages) {
//...
}
Does the Kotlin compiler ignore the nullable type completely? Turns out that yes!
And the reason is quite clear and straightforward but it hadn’t registered in my mind until now:
Note that vararg parameters are, as a rule, never nullable, because in Java there is no good way to distinguish between passing null as the entire vararg array versus passing null as a single element of a non-null vararg array.