1. Dec 30th, 2006

    Ruby: A Better Build for Java

    When I look back at 2006, one of the biggest mistakes I made was switching a project to Maven 2.0. It was tempting, On paper, Maven 2.0 looks like it does all the right things.

    Maven will handle the order of dependency when building modules, and when importing external artifacts. It has pre-canned plugins for all the common tasks, and if you follow the default project structure, you don’t need to configure anything. You can plug extensions for code generation, resource manipulation and packaging. It all looks good.

    But when the rubber meets the road, it starts falling apart. It’s XML-based, so the language is dead simple, or dumb, depending on your point of view. There’s too many things you just can’t do with dumbed down languages, not to mention the propensity for verbosity. A build file that can be summarized in a few sentences takes over a few pages.

    It’s declarative, which means you can’t do anything procedural. You can mix Ant, only to find out the Maven/Ant integration is far from perfect and limits what Ant can do. Even the declarative dependency mechanism gets in the way on the few occasion when you need to override it, and sometimes the only solution is to not use an artifact, just because you can’t fix things easily.

    At some point, you spend so much time fighting Maven for control, you have no time left for writing code.

    A good build system is neither Ant nor Maven. It needs to be procedural so you can perform any task that you need, even — especially — if you only need it for that one project. It’s nice to have pre-canned tasks, but you can’t be limited to the few that are designed for the very generic case. Building tasks and plugins in Java complicates the build process, especially when you’re procedural code is effectively one line of code.

    A good build system needs to be declarative, but it’s not about the dependencies. Declarative is about writing the least amount of build code, and not having to write the same thing twice. Out of that comes dependency management, but you also want abstractions to process a set of files in one go, use patterns to collect resources, or to pick the right SQL DDL based on your test database.

    I can think of more examples, but it all comes down to having a generic language that’s easy to script.

    Martin Fowler captures the point when he says:

    “The thing with build scripts is that you need both declarative and procedural qualities. The heart of a build file is defining tasks and the dependencies between them. This is the declarative part, and is where tools like ant and make excel. The trouble is that as builds get more complex these structures aren’t enough. You begin to need conditional logic; in particular you need the ability to define your own abstractions.”

    When I work on said Java project, I always envy the build system I use in my Ruby projects. That one is short and sweet, uses a lot of canned tasks, but also creates its own custom tasks. Keeps repetition to a minimum, anything I need more than once is wrapped into a variable or a function. It captures more information in less lines without obfuscation. And there’s no fear that breaking one line will bring the entire system down.

    I’m looking forware to JRake and Raven maturing, so we can start doing the right thing in Java land.

    1. Feb 14th, 2007

      Lee

      I totally agree. In fact I wrote about my experiences on my blog. For me it boiled down to two fundamental things:

      1. I want to have one repository (for example svn) and not two (svn and maven).

      2. The rigidity of the build cycle. It just doesn’t work on projects where you have several databases, webservices, teams, and continuous integration going on. A lot of time wasted trying to get Maven to stuff.

    2. Apr 18th, 2007

      Labnotes » Introducing Buildr, or how we cured our Maven blues

      [...] no secret I have a love/hate relationship with Maven 2.0. I hate it. And I love using it as an example of how [...]

    Your comment, here ⇓