When we build an application, we handle the build logic as some sort of “script” that will execute and produce our application binary. But as projects grow, the build logic also expands, getting more sophisticated and generally requiring more attention.
Many of our projects use Gradle for building our apps. Gradle build logic is written in scripts that have historically used Groovy language. There is a good reason for that: Gradle is a JVM based tool and Groovy is a JVM language that allows you to write build scripts in such a declarative way that Gradle scripts look more like static configuration files.
However, all those Groovy features come with a cost. The fact that you can omit parentheses when calling a function or that you can call a function that doesn’t exist (thanks to meta object programming) gives you a superpower to write the build logic in a very concise way. This works well until someone else needs to understand your build logic. At that moment these superpower features might make the script hard to understand and cause long build debugging sessions. Groovy’s dynamic nature prevents the IDE from helping you and many issues are encountered only at runtime.
Kotlin alternative
Building the Gradle build tool around Groovy was a good decision at the start of the Gradle project but as the community has been adopting it, the demand for a more predictable and robust way of writing Gradle scripts has become apparent.
The Gradle team was aware of this need and started to work on an alternative: Gradle Kotlin DSL.
Gradle Kotlin DSL is not just about another programming language for writing configuration scripts. Its goal is unification of the Gradle API surface, setting healthy standards for writing Gradle scripts, and focus on IDE integration. The introduction of this feature is actually a game changer for many teams that were previously reluctant to use Gradle.
The first stable release was done as a part of Gradle 5.0 at the end of 2018. Since then, Gradle 5.x releases of 2019 focused on enhancing the usability and API surface and Gradle 6.x releases improved the IDE support and build config speed. The efforts culminated in 2020 with the release of Kotlin 1.4 in August 2020.
However, the really important changes that Gradle Kotlin DSL brings to the table are available from the very first release, so let’s go through them one by one.
Kotlin language
As stated earlier, Gradle Kotlin DSL is not just about the programming language. Nevertheless, Kotlin (compared to Groovy) is a big enticement for many teams.
The fact that you can write the build logic with the same language you use every day for writing your application code (despite Groovy not being that different in terms of syntax) is comforting.
You have all Kotlin features available and even junior programmers are more likely to work on build files when they are written in a language they know best.
Even senior developers like the fact that 100% of the code in a single repo is written in one language and they don’t have to deal with Groovy features like closures or runtime metaprogramming.
IDE support
With Gradle Kotlin DSL, the IDE can actually assist you when you are writing the script. You get auto-completion that actually works, you can use all sorts of refactorings, navigate to source code from anywhere in your script, or read the source code documentation.
To be fair, some of those features were introduced to the top-used IDEs for Gradle Groovy DSL too, but those were just a few chosen features baked directly in IDEs and they did not always work well.
With Kotlin, it's a different story. Gradle Kotlin scripts (
*.gradle.kts files) are processed on the fly when you write the code and the IDE helps in a very similar way as when you write your app's code. All the nice stuff we love just works.
Correctness
Thanks to Kotlin being a strongly typed language with great IDE support, most of the common errors can be spotted and fixed right in the IDE when writing the script, or at least during its compilation. This leads to less errors at runtime, a much shorter feedback cycle, and better developer productivity.
No more blind tries writing some Groovy code and running the Gradle over and over again, failing every time because of the wrong type/function call error. Now you know what plugin class you are dealing with, you can view its functions and if there is an error, syntax highlighting will help you immediately.
Gradle API polishing
Last but not least, the Gradle team polishes the Gradle Java API that Groovy or Kotlin DSL call underneath and makes it more robust and clean.
Gradle was built on top of “Groovy magic” features that allows you to use the same syntax for calling properties and functions, shortcuts for working with collections or the “methodMissing” concept.
But when thoughts about introducing a new language arose, it was obvious that this change wouldn't be possible without a solid and “independent” API. Don't take me wrong, Gradle is a JVM tool and always will be (in the near future at least), but the new Gradle Java API standardization is kind of neutral ground for these purposes and helps the Gradle ecosystem a lot.
Complexity
Some of the arguments most often voiced against Gradle Kotlin DSL are the complexity of the Gradle Kotlin scripts processing, sync with the IDE, and build configuration times. Granted, these arguments are absolutely valid.
With Gradle Groovy DSL, the IDE has quite an easy job. It highlights the Groovy syntax and when the developer hits the
Sync Project with Gradle Files button, it executes a complete project model re-build. The rest is done by Gradle during the build run.
With Gradle Kotlin DSL, the story is different. The IDE highlights the Kotlin syntax but also creates a model with all the information about available Gradle APIs. When another Gradle plugin is applied, the IDE model needs to be refreshed to include the newly added plugin APIs.
To avoid complete project model re-build when
Sync Project with Gradle Files is executed, there was a special
Load Configuration action dedicated to run just Gradle configuration and load all necessary changes. With Kotlin 1.4, Gradle 6.0 and IntelliJ IDEA 2020.1 (or Android Studio 4.1), this has been enhanced quite a bit. The
Load Configuration action has been supplemented with
Load Script Configurations which loads changes to the script configurations only, without updating the whole project (see the
Kotlin 1.4 release notes for details).
It’s up to everyone to decide whether this is something one can learn and utilize or that it is a show stopper.
Conclusion
Build scripts are usually smaller than the rest of the application code but that does not mean they are less important. And when we are working on something important we like to use proper and productive tools. Gradle Kotlin DSL is definitely one of them.
If you want to start with Gradle Kotlin DSL, we recommend
Gradle Kotlin DSL Primer.
Pavel Švéda
Twitter: @xsveda