Understanding the Challenge
Let’s take a multi-module app to understand the problem. Manually declaring versions along with dependencies across multi modules is our first approach. That would look something like below
At first module build.gradle
file we declare dependencies:
|
|
In the second module build.gradle
fiile we declare same dependencies:
|
|
As we are defining dependency versions at each build.gradle
file this has created problems like conflicting versions if not upgraded correctly. It’s very hard to manage the version upgrades of dependencies and config data. Whenever there is a change in dependency if we have more modules there was a lot of manual process of going to each and every module and checking whether the dependency is exiting or not if found updating and then moving to next.
What is a DSL and Kotlin DSL?
What is a DSL?
DSL is an acronym for Domain Specific Language
that can be used in the context of a particular domain. It’s a contrast to General-Purpose Language (GPL) like Java which is widely applicable or used for multiple domains. It helps us to write declarative code to reduce the boilerplate stuff. The code written with DSL would be much easier to read.
The common usage of DSL language is HTML
in Web development, Gradle
in build tools, SQL
in data management, XML
for the Markup language, etc. Though we might have experience in above mentioned one or more languages but we might not know that we are using DSL.
Kotlin DSL?
Kotlin DSL is built on top of the core language Kotlin. So the syntax would no different from the parent language which gives us the benefit of using Kotlin for development.
Introducing buildSrc
buildSrc
is a directory at the project root level which contains build info. We can use this directory to enable kotlin-dsl
and write logic related to custom configuration and share them across the project. It was one of the most used approaches in recent days because of its testability
The directory
buildSrc
is treated as an included build. Upon discovery of the directory, Gradle automatically compiles and tests this code and puts it in the classpath of your build script. For multi-project builds there can be only onebuildSrc
directory, which has to sit in the root project directory.buildSrc
should be preferred over script plugins as it is easier to maintain, refactor and test the code. — Gradle Docs
Setting Up buildSrc
-
Create a directory named
buildSrc
in the root of your Micronaut project. -
Inside
buildSrc
, create a directory structure mirroring the package of your build logic. For example, if your build logic is for dependency management, you might create a package likecom.melon.dependency
. -
Create a
build.gradle.kts
file and add the following code to it:
|
|
- Create a
settings.gradle.kts
file and add the following code to it:
|
|
- The structure will be as shown below:
- Create
Libraries
andVersions
objects insidebuildSrc/src/main/kotlin/com/melon/dependency/
- Update all libraries inside the
Libraries
object:
|
|
- Update all versions inside the
Versions
object:
|
|
- Update the
build.gradle
file inside theapp/api/
directory of the project:
|
|
Conclusion
buildSrc + Kotlin DSL
is the best option for dependency management. As it’s a class-level declaration it can be easily tested. The auto-suggestion support and code navigation would help in saving time. Maintain separate classes for each purpose. This approach could be easy for better reusability and easy maintenance.