Why maven drives me absolutely batty

Although my maven bitching has been mostly snarky, I have come to truly believe it is the wrong tool for a growing enterprise and, like centralized version control, will lead to a situation where tools dictate process (and design).

But, what is maven actually good at?

  • Maven is great for getting started — you don’t have author an ant file (or copy one from an existing project)
  • Maven is great for enforcing a standard project structure — if you always use maven, your projects always look the same

This is about where it ends for me; everything else maven does – manage dependencies, automated process, etc., is done much better and much more quickly by other technology. It’s pretty amazing that someone can make a tool worse than ant, but maven is surely it

Dependency management is not a build step

Maven is the equivalent of doing a sudo gem update everytime you call rake, or doing a sudo yum update before running make. That’s just insane. While automated dependency management is a key feature of a sophisticated development process, this is a separate process from developing my application.

Maven’s configuration is incredibly verbose

It requires 36 lines of human-readable XML to have my webapp run during integration tests. Thirty Six! It requires six lines just to state a dependency. Examining a maven file and tying to figure out where you are in its insane hierarchy is quite difficult. It’s been pretty well-established outside the Java community that XML is horrible configuration file format; formats like YAML have a higher signal to noise ration, and using (gasp) actual scripting language code can be even more compact (and readable and maintainable).

The jars you use are at the mercy of Maven

If you want to use a third-party library, and maven doesn’t provide it (or doesn’t provide the version you need), you have to set up your own maven repo. You then have to include that repo in your pom file, or in every single developer’s local maven settings. If you secure your repo? More XML configuration (and, until the most recent version, you had to have your password in cleartext…in a version 2 application). The fallout here is that you will tend to stick with the versions available publicly, and we see how well that worked out for Debian.

Modifying default behavior is very difficult

Since maven is essentially a very, very high-level abstraction, you are the mercy of the plugin developers as to what you can do. For example, it is not possible to run your integration tests through Cobertura. The plugin developers didn’t provide this and there’s no way to do it without some major hacking of your test code organization and pom file. This is bending your process to fit a tool’s shortcoming. This is limitation designed into maven. This is fundamentally different that “opinionated software” like Rails; Rails doesn’t punish you so harshly for wanting to tweak things; maven makes it very difficult (or impossible). There was no thought given in Maven’s design to using non-default behavior.

Extending Maven requires learning a plugin API

While you can throw in random Ant code into maven, the only way to create re-usable functionality is to learn a complex plugin API. Granted, this isn’t complex like J2EE is complex, but for scripting a build, it’s rather ludicrous.

Maven is hard to understand

I would be willing to bet that every one of my gripes is addressed through some crazy incantation. But that’s not good enough. The combined experience of the 7 developers at my company is about 70 years and not one of us can explain maven’s phases, identify the available targets, or successfully add new functionality for a pom without at least an hour on the net and maven’s documentation.

A great example is the release plugin. All five developers here that have used it go through the same cycle of having no idea what it’s doing, having it fail with a baffling error message, starting over and finally figuring out the one environment tweak that makes it work. At the end of this journey each one (myself included) has realized all this is a HUGE wrapper around scp and a few svn commands. Running two commands to do a source code tag and artifact copy shouldn’t be this difficult.

Maven’s command line output is a straight-up lie

[INFO] ------------------------------------------------------------------------
[ERROR] BUILD FAILURE
[INFO] ------------------------------------------------------------------------
[INFO] Compilation failure

“Compilation failure”, but it’s own definition is a failure and therefore an error (not an informational message). Further, most build failures do not exit with nonzero. This makes maven completely unscriptable.

Maven doesn’t solve the problems of make

Ant’s whole reason for being is “tabs are evil”, and that tells you something. While maven’s description of itself is a complete fabrication, it at least has its heart in the right place. However, it STILL fails to solve make’s shortcomings wrt to java:

  • Maven doesn’t recompile the java classes that are truly out-of-date
  • Maven recompiles java classes that are not out-of-date
  • Maven doesn’t allow for sophisiticated behavior through scripting
  • Maven replaces arcane magic symbols with arcane magic nested XML (e.g. pom files aren’t more readable than a Makefile)

Maven is slow

My test/debug cycle is around a minute. It should be 5 seconds (and it shouldn’t require an IDE).

Conclusion

Apache’s Ivy + Ant is probably a better environment than maven for getting things done; a bit of up-front work is required, but it’s not an ongoing cost, and maintenance is much simpler and more straightforward. Tools like Buildr and Raven seem promising, but it might be like discussing the best braking system for a horse-drawn carriage; utterly futile and irrelevant.

Tags: ,

5 Responses to “Why maven drives me absolutely batty”

  1. [...] more about the person that wrote the post than about Maven itself. Here’s where I think the most recent post goes [...]

  2. nick says:

    Excellent post, Dave.

    You could also add:

    *Maven does not handle concurrent builds.*
    If your CI server is configured to run builds in parallel, you will see spurious results due to multiple mvn processes writing to the same ~/.m2/repository .

    *Maven will install buggy artifacts*
    If you have a multi-module build, maven will install artifacts to the local repository before the entire build has finished. This is a major problem if module A is used and tested by module B, where module B gets built and tested after module A has been installed to the repository.

  3. yellek says:

    Given that you have reccommended Ant and Ivy I was wondering if you had tried Gant or Gradle? If not have you used Groovy scripting in Ant tasks? I’d be interested in your comparisons.

  4. rogerdpack says:

    oh wow I totally hear you.
    After coming to java from ruby, I’m totally in agreeance.

    my gripes [probably because of lack of experience, but here they are]:

    1) maven doesn’t cleanup right sometimes–if you do too much moving around of modules, you are toast [I think it leaves old garbage behind in the ~/.m2/repository directory structure--every so often I have to nuke it--running mvn clean ironically does not clean maven].

    2) it re-runs unit tests for modules that haven’t changed since the last build, nor have their dependencies changed since the last build. I’ve wasted probably hours re-running tests on code that hasn’t changed.

    3) doesn’t have an option “fork processes and run as many tests as you can at the same time to use all cores” [which at least I want].

    That being said, it’s not…too hard to setup. It only checks for updated artifacts once a day for me, which…I’m ok with. And it actually works for large scale projects without horrible complexity, which is saying quite a bit. It’s probably a great step up from ant :)

    Oh and the documentation is awful. And it can’t run junit with testNg tests at the same time. But–welcome to java!

    -r

  5. Dave says:

    Coming from Ruby to Java you must be pulling your hair out.