Showing posts with label maven. Show all posts
Showing posts with label maven. Show all posts

Monday, April 6, 2009

Improving Maven

I'm still at loggerheads with Maven. There are some specific problems that bother me and that I think could be improved while preserving its basic Maven-ness. Many of the problems center around issues when simultaneously developing more than one component at a time, i.e., when depending on SNAPSHOT versions. In fact a SNAPSHOT dependency is a fairly good indicator of misery; but some small improvements in Maven could reduce that pain point by a lot.

1. Maven knows that source produces artifacts, but it doesn't know that artifacts come from source. When Maven checks dependencies, it looks in local and remote repositories, but it doesn't know enough to build (or re-build) an artifact from source.

If Maven artifacts (at least locally deployed ones) had a backpointer to the location of the source project that produced them, then it would be possible to check dependencies against source. For instance, if project B depends on A, and I touch project A's code and then rebuild B, project A should also get rebuilt and installed. Similarly, if artifact A came from local source, then it almost certainly should NOT get replaced by an "updated" artifact from a remote repository, even if the remote artifact is newer; rather, local source code should always get honored. Extra points for a "mvn svn:update" command or the like, that would transitively sync the version control system to the latest code in all upstream projects.

2. SNAPSHOTs need to be versioned. When you're collaboratively working on two projects, and an API between them changes, the downstream build is broken until the upstream project gets refreshed. But right now that happens in a nondeterministic, asynchronous way: to Maven, all SNAPSHOTs are identical until, around midnight or so, it decides to refresh. Basing refreshes on an update interval is like filling up your car's gas tank every Friday: it's either too soon or too late. This needs to be deterministic. What I really want from SNAPSHOT is the idea of a fine-grained version number, that I will throw away upon release. It could be as simple as letting me say 1.3.0-SNAPSHOT-002, instead of just 1.3.0-SNAPSHOT.

3. Maven assumes that the internet is fast and reliable. It is neither, as anyone who works from coffeeshops and airports knows all too well. When Maven fails to get a network connection, or the network dies midway or times out, it needs to be able to roll back to a known and working state. Among other things, this means that updates need to be atomic across projects, or at least they need to be nondestructive. It also means that basic help should not rely on a network connection. Maven should not attempt to update plug-ins or projects during a 'clean' or 'help' operation.

I've got other problems with Maven - for instance, I think XML is nasty to work with, and I think that "convention over configuration" translates to "doesn't play well with others." Those things are harder to address while still keeping it Maven. But if the above three improvements were made, I think no one who loved Maven would be harmed, and a lot of other folks would be helped.

Friday, December 5, 2008

Maven Continues to Suck

Maven is supposed to be a tool to support collaborative software development.

Maven is based on the concept of software modules, each of which is versioned, and which have interdependencies. Let's say version 1.0.2 of MyThing depends on version 2.4.1 of YourThing, for instance. Now, what if I want to make some changes to both YourThing and MyThing? Well, there's a special version called "SNAPSHOT" - as in 2.4.1-SNAPSHOT - that means "the latest and greatest up-to-the-minute version of YourThing version 2.4.1". Setting aside the discussion of how the concept of a "version of a version" is inherently flawed, this introduces a big problem: it does not distinguish between changes I make and changes somebody else makes.

Case in point. Another developer at my company, and I, both are working on modifications to a module that our other stuff depends on. My modifications won't ever be shared with the rest of the world, they're just for my temporary purposes, but nonetheless I need them. The other developer, however, made some changes and committed them to version control. When I went to do a build of MyThing, Maven checked dependencies and noticed that there was a new SNAPSHOT of YourThing.

In a sane world, a collaborative software tool would notice the conflict, and perhaps notify me: "a newer version of YourThing is available, but it conflicts with your local changes - do you want to upgrade and lose your changes, or keep the stale but familiar stuff you've got?" The default, of course, would be to keep what I've got; after all, if I made some local changes, it was presumably for a reason.

Not Maven, though. Because I said SNAPSHOT (so that I could make changes locally), Maven silently and transparently discards my local version and updates me to somebody else's changes, at a random time of its deciding (typically, in the first build I do after midnight, of any project that happens to depend on YourThing).

Fortunately, the other developer's changes contained a serious bug. I say fortunately, because otherwise I might not have noticed that my changes had been silently discarded, and I might have spent a lot of time trying to figure out why my code, that used to work, no longer did.

What kind of collaborative software development tool is it that can't gracefully handle the simple case of two people working on a shared module?

Maven is not really a collaborative software development tool, it seems. Maven is a tool for letting one person develop a single module of code, with external dependencies on an otherwise-static world. That does not describe any software project I have ever worked on.

I keep hoping to see the light, and discover that I'm wrong about Maven. But it keeps on sucking.

Monday, October 27, 2008

Maven Sucks

Tools like Maven make me want to quit the software industry before I die of frustration. I've wasted basically the last two days screwing around with problems related to Maven. In a nutshell, Maven does not provide a consistent or reliable build environment.

Modern software is not written from scratch; it's assembled from myriad components from other vendors, in much the same way that car manufacturers buy their parts (seats, brakes, wiper motors, radios) from other companies. And just like a car seat is itself made of springs and fabric and metal bits that come from yet other manufacturers, each software component may itself be assembled from other components.

Maven is a tool to help manage all the little pieces that fit together into a software product - to manage the fact that my product consists of components X, Y, and Z, which in turn require the presence of P, Q, R, and S, which in turn require A, B, and C; to fetch those components from wherever they come from if they're not already on my computer; and to make sure that the versions of these different components are all compatible.

But it sucks. Maven wants to update things without me asking, so that if I run a test twice in a row I don't necessarily get the same results. Maven wants to download things without me asking, so a task that took 15 seconds the last time might take a few minutes, or fail utterly (if I lose my network connection), leaving me in an unknown and inconsistent state where I can't build at all. And most frustratingly, Maven is itself highly modular, meaning that it's not all downloaded until it's needed, meaning that in the event of network trouble it can again fail utterly. Networks are not yet reliable enough for that to be okay.

Further, Maven seems to do a crappy job of understanding and resolving or reporting version conflicts. I'm extending some test code, that's supposed to exercise version 3.2.5 of product HappyWidget. The test code therefore tells Maven that it needs HappyWidget version 3.2.5. But the test code also needs OtherThing version 2.7.1; which needs FussyBit 2.0.1; which needs HappyWidget 3.1.2. Whoops! This is a version conflict. It would have been easy to fix, except that Maven didn't tell me there was a problem, it just silently deployed HappyWidget 3.1.2. So all along this test was actually testing HappyWidget 3.1.2. What's really scary is that when I uninstalled and then reinstalled everything, without explicitly making any changes in my dependencies, the behavior changed - now it's deploying 3.2.5, which is nice for my test but not so nice for the corresponding code that is supposed to test HappyWidget 3.1.2.

The first requirement of a build tool is that it should behave predictably. Maven fails.

It's late and I'm not going to spend more time saying all the hateful things that Maven has done to me in the last two days. I will blog in the future about what I think the solution to this should be.