Gradle fans have been discussing a recent article on Gradle and the halting problem. The premise is that a program (such as an IDE) can not reason about a Gradle build without first executing the build script. And since the build script is written in a Turing-complete language (Groovy), it may never complete execution and you won’t even be able to discover a build’s dependencies.
I don’t want to focus on the halting problem argument as Schalk Cronjé has already voiced my own viewpoint pretty much. Instead, I want to tackle the perception that Gradle is all about the script. Another example of this is Tim Boudreau’s post on the benefits of Maven in which he says that he worries about Gradle’s scriptability and the potential for lots of custom, hard to understand builds.
The most important thing to understand about Gradle is that the build script is simply a mechanism to access the Gradle API. You can’t simply paste a Gradle build file into a Groovy console and execute it as the script will throw an error. The real value of Gradle is in the API and the model that the script provides access to. The core model is one of projects, tasks, dependencies and a few more things. Plugins can extend that model to incorporate such concepts as source sets and compilation depending on the type of project you have.
Gradle’s API and internal model are the key to modelling your own build processes. And I argue that’s the most important aspect of a build tool: that it adapts to and supports your requirements rather than forcing you to adapt your processes.
Given the above, it seems clear to me that Gradle could use a custom, non Turing-complete language for defining builds. The downside is the amount of effort required to implement such a thing, when a language like Groovy already provides the necessary behaviour. Surely that time is better spent on getting the model right. In addition, the fact you can readily define task implementations within the build script makes Gradle accessible. That doesn’t mean it’s always the right thing to end up with, but that’s what refactoring is for.
The question of untrusted builds is an important one as more and more projects start using Gradle, particularly open source ones. I do think it behoves Gradle to consider restricting the system access permissions of build scripts by default and perhaps adding a time out on the script execution. Both of these features would help protect users from malicious scripts.
I would like to finish up by tackling Tim’s concern directly. It is indeed possible with Gradle to end up with a spaghetti build as many of us experienced with Ant. The key question is how likely this is to happen. To answer that, we need to understand why builds evolve towards a complete mess in the first place.
I’ve had a fair bit of experience with builds and software development in general and I find that builds and code tend to get dicey when there is uncertainty or something is just plain hard. There are other factors to be sure, but who’s going to write their own custom Java compilation tasks when you can simply apply the Java plugin and have all the hard work done for you? Such conventions tackle much of the uncertainty in build and encapsulate expert knowledge. But what I really love about Gradle is that (on the whole) it makes it easy to do the right thing with customisations. If you’ve ever added your own source set, you’ll know what I’m talking about.
To summarise, I think focusing on the build script misses the real value that Gradle brings to building software. And yes, there are potential problems with using a language such as Groovy for the build script, but these can be overcome and don’t impact those developing their own builds. I know these arguments won’t sway those who believe that build definitions should only contain configuration settings, but hopefully others that are on the fence will have a better understanding of what Gradle is about.