Before 2004 the defacto standard build tool for Java applications was ANT. It was a step up from the make-based way of building Java software; it featured standard tasks, like compile and jar, that you needed in most projects. It was a first attempt to make building java applications more declarative.
But as time moved on, and projects become ever more complex, so did the ANT scripts. You ended up with scripts calling scripts, calling scripts, calling scripts, … And soon building an application was just as complex as the average nuclear fission paper. Not even mentioning trying to assemble the right versions of all the dependencies into the libs folder.
Many people were running into this problem, so in 2004 Sonatype invented Maven. In essence, it does two things:
- Enforce a strict structure of the build file
- Explicitly define dependencies
I’m not going into the second part of, because that will take many blog posts, but I want to talk a bit about that strict structure. The structure is based on three things:
- Predefine build steps (e.g. clean, compile, jar, deploy)
- Plugins that place functionality in those steps.
- A predefined directory structure.
Enforcing such a structure has one very very big advantage; projects and their build files always look the same. No matter if it is a complex project like spark or camel, or a simple HelloWorld project, it’s always dependencies, plugins, optionally modules and profiles. That are the building blocks you need to work with. And this rigidness is what has kept projects manageable ever since.
But Maven has one obvious issue; it uses XML to define the build. And there is nothing really wrong with that, except that it is a bit verbose. Is that an issue? To some apparently, but not too many, otherwise polyglot Maven would have caught on much more.
Never the less the verbosity and inflexibility (as a result of the strict structure) resulted in 2007 in the creation of Gradle. Its primary purpose was using a DSL to define the build, replacing the XML. And the idea of Gradle is very inspiring, and initially I was a fan. But with the introduction of the DSL they also loosened the strictness; make coding in the build file easy again, and you can split up build files as you please. And that is where things are going wrong.
The adoption rate of Gradle is not too high, most projects still use Maven, but especially newer projects have a tendency to use the latest and greatest (I’m looking at you Android). I have adopted Gradle for JFXtras, to force myself to learn and form an educated opinion. Personally, wanting to stay strict, I feel my build file looks quite ok. But I was not able to write that completely by myself, Gradle’s learning curve is steep (and I’m very appreciative of all the help I get!).
But if I take a closer look, there are things that bother me. For example the fact that there is another build file, that is imported without reason from the project structure. Or this block in the main file:
// wait for every subproject to be configured before reconfiguring root project evaluationDependsOnChildren()
What? Wait! I need to tell my build tool it needs to wait for itself?
If I take a look at the build file of the big sister project, ControlsFX, then I see that it has a different build file setup. The tasks in the build file are recognizable, but the toplevel talks about subprojects, but if you go deeper, you get a ‘normal’ build file.
Tasks are the same, the structure is different. Hmmm. Where have I seen that before?
If structure is not enforced, users will start (ab)using that freedom, because some custom code usually is less work than writing a plugin; “I’ll fix that later”. Back in the days I used very structured build files for ANT, which were dubbed MAVANT (yes, yes, I know, Maven and ANT combined, brilliant), but in the end it still grew askew. No convention can prevent that, unless you actively monitor all commits.
So if you feel so strongly about the verbosity, use polyglot Maven. I like the YAML version, Kotlin is very readable as well, and Groovy allows easy coding if you really can’t resist. But please, pretty please, a strict structure is good. Use Maven.