Kotlin DSL — know your limits
Kotlin DSL —defining mandatory parameters
Or why I wrote another Android library

Since Kotlin was introduced, multiple libraries have opt-in for DSL implementation of their API.
Kotlin DSL is a great tool, it makes your API more readable and easier to use, and if you haven’t gotten around to play with it, I strongly encourage you to give it a try.
But this article is not meant to explain how to implement an API based on Kotlin DSL, there are some great articles about it out there.
Nor am I going talk about how awesome Kotlin DSL is (and it is).
Instead, I’ll focus on the problems I faced when I tried to apply it to my own use cases.
First
https://medium.com/media/850a7346dec798d01d2c96efa93a19a1/href
A nice example for DSL can be found in an Android library called Anko, which allows laying out UI components programmatically (might look familiar to Flutter/Jetpack devs):
verticalLayout {
editText {
hint = "Name"
textSize = 24f
}
button("Say Hello") {
onClick { toast(“Hello!”) }
}
}
Looks pretty easy to understand, right?
So, where’s the catch?
Let’s take a closer look:
button("Say Hello") {
onClick { toast("Hello!") }
}
As you can see, the button text is supplied as a parameter since it’s mandatory for the creation of a button, as opposed to the onClickListener which is optional and therefore defined inside the lambda block.
For a single parameter, this still seems quite readable, but what if there were multiple mandatory parameters?
After giving DSL a try, what I soon found out is that I had the same problem as with plain old Builders — receiving mandatory parameters.
What’s the solution then?
The obvious solution is to verify all mandatory parameters are set as part of the final object build, but that’s a runtime solution and a sign of bad API in my books.
Another solution I would use in builders was to define mandatory parameters in the constructor.
The same trick works for DSL, but I found it contradicts one of the purposes of DSL — being readable.
The final option I tried is using Kotlin Contracts, which I quickly ruled out for two reasons:
1. I didn’t feel it was mature enough.
2. They only apply for top-level functions, not exactly what I was looking for.
https://medium.com/media/b524e2fd23b6d1b3287bb1bc5bdd2f55/href
My goal was clear — a compile-time verification of mandatory parameters.
I wanted a simple solution to this common problem.
Introducing DSLint
Eventually, I decided to be my own best friend and implement a solution to this problem using a custom Android linter library (sorry non-Android devs).
So here’s how it works, let’s say I was to implement a Person builder using DSL and wanted to make sure the person’s name was set.
All I need to do is annotate the class and the name property and let my custom linter do the magic:
@DSLint
class Person {
@set:DSLMandatory
var name: String
}

Clean and simple.
I made it open source, so you can either use it in your project or clone the repo and create your custom solution based on it.
You can grab a look here:
To sum up
As I previously said, DSL is a great tool and I encourage you to try it but also be aware of its limits.
I hope you enjoyed reading and I look forward to hearing about the challenges you faced when trying out DSL and how you approached them.
Click the 👏 to say “thanks!” and help others find this article.
To be up-to-date with great news on Kt. Academy, subscribe to the newsletter, observe Twitter and follow us on medium.
If you need a Kotlin workshop, check how we can help you: kt.academy.
Kotlin DSL — know your limits was originally published in Kt. Academy on Medium, where people are continuing the conversation by highlighting and responding to this story.