I’ve been meaning to do a follow up post on Maven for quite a while. I received several emails regarding my previous post from people asking how we’re using it. I must admit, it looked promising initially, but as we got into the specifics, it looked less workable for building commercial software. Here I hope to outline some of the reasons I suggest that Maven may not be for you.
Firstly, by reading blogs, wikis and the Maven website itself, you would get the impression that Maven is well suited to building web applications. It is, as several are already in existence, and those developers seem to like using it. For the most part, these are open source projects, following best practices, typically producing jars, wars or zip build outputs.
This makes Maven suitable for web applications such as a stock trading applications a typical bank would use. Coders code it, Maven builds it, then deploys it to a test environment where QA test it. If it is deemed of acceptable quality, it may be further deployed to a live environment. Maven suits this process well.
This is fine for internal web based applications which an information systems department may maintain, or for web based open source applications. When it comes to commercial software, the needs are a little different. For the majority of projects I’ve worked on, we eventually need to build and test software, before creating an installer, and bundling it on CD or for download. This leads us to the first issue I have with Maven …
1. One build output.
Within the Maven project file, you can specify the packaging used for your build output. The default is jar, with war, rar, ear, and a few others also acceptable.
The point here, it that you only get one output file from a Maven project. For open-source, or web application development, this is generally sufficient. In my experience though, this is far from ideal for commercial software.
The software I’ve been dealing with is mostly Java, with some native bits, and associated data and configuration files. Bundling all this into a single jar, or war is not appropriate for several reasons. Some technical, some legal (with regard to licensing of third party libraries), etc.
The net result, is if you persist in using Maven, you’ll need one project file per output file, with the associated overhead of ensuring that those multiple build systems don’t diverge over time.
2. Linear build process.
The second issue I have, is that Maven defines a linear build process. Again, this reduces it applicability to general purpose project building.
A good example if how this hurts, is cross platform Java development with native code. Java provides an API for talking to serial ports, though the implementation must be provided separately. It’s relatively easy in Ant, to branch your build depending on the platform your building, and include the Linux serial implementation when you build on Linux, and a different Windows serial implementation when building on Windows.
No such luck with Maven. You get a linear build process which you can optionally hook in at various points, but you don’t get branching or looping constructs for your build system. You’re left to resort to multiple project files again.
3. Configuration Overhead
One of the major selling points of Maven is it’s jar management abilities. I admit, if done properly, this would be a killer feature. I await the day it’s done well.
This works well, again for open source only projects. For the rest of us, we’ll need to create our own Maven repositories, for internal commercial libraries, as well as commercial third party libraries and toolkits.
This adds to the amount of work required from a project team before the first successful build is created. I’ve already posted about the pain I experienced in installing and configuring an internal Maven repository. Ideally this cost could be borne once, and shared amongst all project teams, but then you’re running into legal and licensing issues when you could potentially be sharing libraries across project teams without the necessary per-seat fees. Also, as I’ve noted before, Maven isn’t ideal for all projects, so adopting (or forcing) it to other teams is problematic. In the majority of cases, you’ll be left alone to manage your own project infrastructure, adding to your workload.
4. Build failures.
Rather than check in libraries to your project, Maven allows you to specify what libraries you need in your project file. Maven then looks for these jars in your local Maven directory, a maven proxy (if configured) or finally in the central Maven repository. This is a useful feature, as all the dependencies are managed for you with this approach.
The downside, is the need to have a local maven proxy for your own commercial, or third party libraries. Another downside, is the need to be constantly connected to the internet to check the central repository while building. For example, if your project file specifies your project needs the latest version of JUnit, then Maven will check that it has it each time you build. If for some reason your internet connection is down, slow, or the central repository is busy (which is likely as Maven’s popularity grows), you get a build failure.
Call me old fashioned, but to me build failures are serious. They generally denote that something has gone wrong. You’ve forgot to check in a file, or a unit test has failed, etc. You need to fix it.
With intermittent build failures due to network connectivity, a developers faith that a failed build is actually something that needs fixing becomes eroded, and failed builds tend to be ignored for longer, as developers assume it another bogus failure that’ll fix itself eventually.
The net result here is either time spent diagnosing bogus failures, or developers getting lazy about build failures.
Related to Maven’s library management, is the requirement of repeatability. To me a build should be constantly repeatable. That is, if I check out revision 2345 of a project and build it today, I get the same build outputs as if I build the same revision next week, month, or year.
This is not necessarily the case with Maven’s library management. Unless your are fastidious in specifying the version of libraries you need, Maven will download updated libraries behind your back. So building revision 2345 today gets you a build. Building the same revision next week gets you a different output, because the libraries you depend on were updated on the central repository.
If you can’t reproduce consistent builds, what’s the point in having source control infrastructure? Source Control Management is already difficult enough, without playing fast and loose like this. What happens in 3 years when that big customer requests some changes to the software you sold them?
Call me paranoid, but I’d rather take the hit and manage my own libraries. Sure checking them into Subversion or CVS uses disk space, but disk space is cheap compared to not being able to repeat a build when that big customer comes calling.
6. Internal Processes
How your company builds software also has a baring on this discussion. Our software development process specifies that the Configuration Manager must build all release candidates. This step is introduced so that a person independent from the project team can validate that the software, tools and methods needed to build an application are in place, and that a specific build version could be reproduced in the future if necessary.
We generally meet this requirement by checking in all libraries needed into source control, and writing a build instructions document which outlines what tools and configuration is needed to set up a build environment, as well as how to produce a build from that environment.
As already noted, Maven is unsuited to this metaphor for various reasons:
- You are depending on resources outside of your control when depending on libraries from Maven’s central repository. Can you guarantee that in X years time, the repository will still be there, with the versions of libraries you need? (No you can’t, so repeatability of builds is compromised).
- Can you guarantee that your project’s maven proxy will be available in X years time? Generally, project resources get redeployed when a project finishes. Your CM manager will have lots of work to do to recreate the Maven proxy when a build is needed.
7. Declarative XML.
The Maven project file describes itself in a declarative XML notation. XML is, as noted in a previous post, a data markup language. It is not a domain specific language written for the purposes of building software. Ant fails this test too.
Ant is somewhat procedural, even if it does use a funny reverse execution mechanism. Generally I’ve found it relatively easy to debug when the build system fails. Maven on the other hand uses some sort of voodoo-magic. When Maven builds fail, be prepared to spend several days pouring over verbose output logs trying to find out why it didn’t execute the hibernate schema generator when you thought it should.
If you’re considering using Maven, then I would suggest you’re better off researching some of the newer build tools such as Gant, Rake, or Buildr. These have learned from Ant and Maven mistakes, and are built on easy to learn scripting languages.
Using Maven is like ridgewalking. If you can stick to the beaten track, all will be well. Wonder off, even a little, and you’ll find yourself falling off some pretty steep cliffs. Maven works, but only for a very specific type of project. If that’s you, then by all means knock yourself out. While it serves it’s niche well, I personally wouldn’t consider it a general purpose build environment.