Gradle's build-by-convention approach

There has been an exchange on Twitter with Tim Fox from VMWare who is also the lead of the Vert.x project. Tim was unhappy with his Gradle experience. His main pain (please correct me Tim if I’m wrong) was that the conventions of the Gradle Java plugin don’t fit his project. In that context Tim questioned the build-by-convention approach for build systems. With this posting I would like to share my opinion on that.

First of all, the Gradle Java plugin is a small opinionated framework about how a Java project looks like. As with all frameworks, you don’t have fun with them if your view of the world is different. And our position here is crystal clear. If your view of the world is different, don’t use the Java plugin. For example there is a big company that is using Gradle, where they use different projects for their production code and their unit test code. They have their reasons for doing this. So their view of a Java project differs significantly from the Gradle Java plugin, which expects production and test code to be in one project. You could argue that they could still use the Java plugin for their projects and just having empty test directories or empty main directories. But this is already too much tweaking for my liking. Imagine a new developer coming to a team, changing the production code, running the tests (they succeed as their are none) and committing without running the test project he was not aware of. The model of the Java plugin is just wrong for them and confusing. So what to do?

Gradle has three layers. A low level task layer conceptually similar to the Ant execution model. A second layer with domain specific language elements (e.g. a Java SourceSet) and a third layer that tells a specific opinionated story and provides a small framework. In the case of Java the second layer is contributed by the Java base plugin. This plugin is not adding any tasks, configurations, source sets, default behavior, etc … It is just providing the language elements for building Java projects and certain on-demand conventions. For example if you declare a source set, the compiled code will end up in a certain destination. If you add a jar task, the jar will end up by default in build/libs. If you don’t add a jar task there is no jar task. So this plugin is not telling a story, just providing a proper language for a story. The Java plugin then extends the Java base plugin to tell its story. In the case of the company mentioned above, they wrote their own Java plugin on top of the base plugin telling their story and their conventions. As this is a large company, they have many teams that all have this structure and are happily applying this plugin so that they don’t need to copy and paste a story or come up with their own one.

Gradle, as Maven, provides out of the box build-by-convention standards for certain domains (e.g. the Java plugin). This is a nice feature, but I think in my opinion it is not as important as other people may think it is. What Gradle puts additionally on the table, is a toolkit, which an enterprise can use to model their own standards and build-by-convention processes. They want to do this for example because they have conflicting perspectives with for example the Java plugin. But mostly because in their automation domain they might be happy with the Java plugin but have a lot of additional custom requirements where no build system provides any standards for. For modelling this they may either use the second layer of the Gradle domain model to tell their story. Or, if no such second layer exists (e.g. for Microsoft Office document transformations), they can use the lowest layer of Gradle to create such a layer/toolkit for this domain and create opinionated frameworks on top of that, thus giving their teams a convenient build by convention story where it fits and a powerful toolkit for the non-conventional use cases. This approach is what we do again and again for standardising the build infrastructure of our clients and they are very excited by this possibility. In my opinion the fact that Gradle is a very capable tool for implementing custom standards is by far more important for the enterprise than the out-of-the-box standardisation it also provides.

If you have an, from a build perspective, unconventional single open source project like Vert.x you don’t need to care about build by convention. You definitely don’t want to fight with an opinionated framework that doesn’t understand your needs. Nonetheless, you are in the Java domain, so you have sources to compile, tests to run, etc … Therefore I think it is very likely that the Java base plugin provides nice value. On top of this just tell your own story in your build script. (@Tim: We are more than happy to help you with that.). But for an efficient build infrastructure in the enterprise, build-by-convention is very important for making your developers efficient when dealing with the builds.