Interactive Build Tool Comparison Part Two
Maven vs. Gradle vs. Ant
Which is the best build tool? In part two of our interactive build tool comparison, we find out where the three of the major build systems – Ant, Maven and Gradle – have an edge over the competition. And don't forget to send us your questions, because in part four we'll be putting your questions to our three experts. Questions can be sent via email, or posted in the comments section at the bottom of the article.
JAXenter: In your opinion, what are your build tool's strengths, compared to other build systems
Hans Dockter (Gradle): Gradle offers many features that make every-day build processes easier. These include a generic function to skip certain Aspects of a build, without the aid of a Build-Master. In Ant, the developer has to use Skip Properties to miss out build Aspects; in Maven he needs to adjust the plugins – if this is possible.
Gradle also offers our beloved Camel Task Execution for abbreviating task names when running in the console. This results in a very dynamic output, which includes a counter for the executed tests. There is a 'stand alone' GUI, which can be accessed with gradle-gui. There is a wrapper for building projects with Gradle, without even installing Gradle. This wrapper also means zero-administration of client-centric Gradle-installations in the enterprise. I could go on!
The original motto of Gradle was: "Make the impossible possible, make the possible easy and make the easy elegant.” This motto summarises the contrasting characteristics of Gradle, and Ant and Maven:
Ant is a pure, imperative build system, which means Ant has the flexibility to make the impossible possible. However, often Ant doesn't make development easy and elegant, which frequently results in builds that are difficult to maintain and extend. Ant lacks the declarative element and the conventions. Ant does not model the problem space. The Ant-model consists of Task, Target, Project, Resources and Properties. It does not understand source directories, project dependencies, etc. ... This, the user has to model himself - and with the limited language elements that Ant provides. Gradle offers a rich, extensible model to model software projects - without losing the flexibility of Ant. This flexibility can be accessed when you need it; otherwise, it rests in the background of the declarative build description.
We consider Ant not primarily as a competitive build system, but as ageing friend and helper. This is especially true when it comes to the treasure of existing Ant tasks. These are First Class Citizens in Gradle. You can also easily wrap them in a Gradle-plugin, and get Convention over Configuration. You can load an Ant-build in Gradle-runtime and integrate it with Gradle. You can define dependencies of Gradle tasks to Ant targets and vice versa. You can also extend Ant targets in Gradle. This way you can very gently migrate - in whole or in part – from Ant to Gradle.
Even if a number of requirements can be easily realised with Maven, far too often it's very difficult to solve relatively easy problems with Maven. Project Automation is an important and critical component of successful software development but frequently we keep encountering things that are not automated, because it is too difficult to integrate with the build systems in use. This particularly applies to the requirements which cannot be anticipated by the build system. The implementation of such requirements often require workarounds, which result in high maintenance costs. I would also like to quote Erich Gamma:
“Frameworkitis is the disease where a framework wants to do too much for you, or to do it in a way that you don't want, but can't change. It's fun to get all this functionality for free, but it hurts when the free functionality gets in the way. But, you are tied into that framework. To get the desired behaviour you start to fight against the framework. And at this point you often start to lose, because it's difficult to bend the framework in a direction that it didn't anticipate. Toolkits do not attempt to take control for you, and therefore they do not suffer from frameworkitis.” Erich Gamma
This quotation corresponds to our intensive experience with Maven, and we do not anticipate anything fundamentally changing with Maven 3. This is not an issue with XML. Gradle follows the path recommended by Erich Gamma and offers small, optional frameworks based on toolkits.
Gradle extends the declarative approach of Maven, making it suitable for the full range of company-specific requirements (see above.)
Gradle offers very powerful support for multi-project builds. Project dependencies are First Class Citizens, in contrast to Maven, where dependencies are modelled in the same way as normal external dependencies. This allows for many optimisations (eg, partial builds,) and makes this information available to the users. Gradle doesn't use inheritance to define the common features of sub-projects. Instead, there is 'configuration injection' where a user can inject shared configurations into any group of subprojects. The Maven Mix In functionality for poms (which is postponed until Maven 3.1) is heading in the same direction, but is not as powerful.
There is one final aspect that often leads to considerable debate. Many Maven users like the very restrictive, unchangeable Presettings of Maven. In their opinion, they result in builds that are easy to understand, and easy to maintain. We believe that the opposite is often the case. What happens when you have to squeeze complex requirements into a simplified model? First, it is laborious. Often, it is so complex that it cannot be done. The result: the build rests as it is. Congratulations ;) But, what happens when you squeeze? Then, it often begins to become 'offensive' (in the words of Kent Beck.) You have to tear apart what belongs together (Shotgun Surgery,) or you get unnecessary indirections (such as Lazy Project.) The worst thing is that the developer is forced to violate a fundamental principle of domain-driven design: you have to make explicit the implicit. Such a build may at first glance look simple, but in reality it is often a maintainability monster.
We believe that it is important to have a clearly structured process for the build within an organisation. Gradle supports this more than any other build tool that we know of. But, the organisation must be able to create these processes themselves. Gradle offers a set of standard processes, but these are not privileged, and they are extensible. You can also design your own processes or use a mix.
Matthew McCullough (Maven) : Maven's unique strengths lie first and foremost in its opinionated conventions, proven to be industry-desired through an eight-year track record. Build scripts are, in most cases, not where developers should be expressing most of their creativity. Technical prowess should be demonstrated through the coding of the software product itself. Maven facilitates spending less developer time with the build script than other build tools because the build for multiple systems can derive the majority of their configuration from a parent script through true object-oriented inheritance.
I've seen far too many scripts in my day that, because there were few if any bounds placed on the build script by the build tool, were a cacophony of small elements rather than a symphony of plugins, run in a predictable lifecycle sequence. My No Fluff Just Stuff colleague, David Bock, recently extolled via Neal Ford at RailsConf 2010, that "constraints can be liberating" and I believe that Maven strongly embraces that sentiment.
Additionally, Maven aims through project object model inheritance (as discussed above) and through archetypes (powerful interactive project templates) to reduce the occurrence of construction of build scripts through the error prone practice of copy-and-paste coding. There are over 100 archetypes in the central repository today, all accessible through a natural dialogue with Maven. Each archetype prompts for the Java package and project name and instantiates a quality project, ready to be checked in to version control and accept new source code from developers. This mitigates the embarrassment of copy-and-pasting a new project's build script and accidentally forgetting to rename all the occurrences of "Blue Customer" for the new "Red Customer" project until it shows up on a projector screen during the first internal demo.
Lastly, Maven is the creator and keeper of the canonical dependency repository format. Ant Ivy, Gant, Gradle, and even the upcoming Grails dependency management systems all follow and leverage the repository layout and centralization of artifacts that Maven provides. It is an acknowledgement that there is eight years of value stored at http://repo1.apache.org/maven2 that will likely live on in both Maven as well as other build tools for many years to come.
Jan Matèrne (Ant) : Flexibility and openness. Personally, I prefer reading a piece of code and immediately understanding what is being done. I like to go through the code step by step and understand it from start to finish. With systems that do everything internally, out of sight of the developer, everything seems to be done by “magic.” But when something does go wrong, you don't know how to solve it.
Also, with Ant it is possible to customise a build according to a project's particular circumstances and needs, with only minor changes.
Agree? Disagree? Don't forget to send us your comments and questions, and stay tuned for part three!
Read more at part one.