Some thoughts about building
Over the last few days I had some thoughts about building your project. I am using Apache Maven for quite a while now. At my current employer we use Maven for all our components even our learn portal which is build entirely in Adobe Flex, using the Flexmojos.
The bottom line is that we have approximately 100 projects build with maven to build our entire platform. You don't need much imagination that we have a couple of challenges to meet.I started with Maven 1 which was a astonishing mixture of Apache Ant and Jelly. But I never really liked the idea of executable XML. In my opinion XML is not a good programming language at all but this would be a blog posting of its own
Back to to the builds. A couple of days ago a read some tweets from the the man behind tapestry to remind me about Apache Buildr. This lead to rethink some experiences I made with Maven2 in the last couple of month...
This lead to certain discoveries what I started to really dislike on Maven2:
- The XML - The
pom.xmlwhich defines the central project object model os getting really cluttered. When you have a small project there is almost no problem but if you have an enterprise scale project (almost evereything after an example project) thepom.xmlis getting huge and you don't find the things you need.Okay, there are "helpers" to maintain the
pom.xml, but e.g. if you use Eclipse with a POM file the XML editor starts to parse it. If the file is no very small - even a small open source project like jaev has an approx. 140 linespom.xml- it'll make Eclipse somewhat slow. If you use the m2eclipse plugin it will get even worse. The m2eclipse offers some very nice tools for POM handling and it got really good compared to the early versions. But I know a couple of guys who refuse to use it because of the negative impact on your development environment. - Reuse by inheritance - The only way (so far I know
) to reuse settings in Maven2 is POM inheritance. This works like prototypic inheritance (like in Javascript). You may define prototypic plugin settings in the parent POM and all POMs which inherit from this parent POM will use this settings as a default.
So far so good, but in most object oriented programming languages inheritance to reuse code is considered to be a bad design pattern. In Maven2 you may stumble across the same bad issues as e.g. in Java when you use the POM inheritance. As a matter of fact you may only inherit from one parent POM, so your inheritance tree will get cluttered with settings and overrides.
- Insufficient version and dependency management - The dependency management is one of Maven2 strongpoints, no doubt about it. But if you really start to use it you'll get to it's limits very fast.
I guess Maven2 did some awesome pioneer work to version handling. Due to the fact that every artifact has a version number. Unfortunately the version numbers in Maven do not have an ordinal structure and admits special indicators like
SNAPSHOT,alphaorLATESTwhich are adding a whole new level of complexity. So maven can't tell if a version is greater than another version, e.g. is1.4-SNAPSHOTgreater than1.4?. This is very problematic when use version ranges and transitive dependencies. When you'll get a dependency from different sources (e.g. the commmons-lang library) there is always some magic involved which version you'll get. This leads to next next issue: - The build does not break early enough. - Maven2 tries to be very clever in some situations like the dependency resolution. If a problem occurs maybe a log message will be provided but the build will continue even if you have contradictory dependency declarations. So the only "hint" you'll get, if the dependency tree is faulty, are compile errors if you're lucky. If you have runtime dependencies you'll get some funny effects in your application
- No separation of concerns. - The POM includes all concerns of a build like:
- Dependency management
- Compiling
- Tesing
- Packaging
- Reporting
- Deployment
You'll have different sections in the
pom.xmllike<build/>,<dependencies/>,<profiles/>or<reporting/>which group the declarations a little bit. But if you take a closer look at the<build/>section you'll soon realize that it works quite different that e.g. the<dependencies/>section. In the<build/>you are more on a programming level to specify the compile and packaging issues of your build. The<dependencies/>is only declarative. - Only one file - To make the lack of separation more painful you are not able to break the different concerns into separate files. There are some Maven plugins which use other files like the assembly plugin, but this an exception. It would be really nice if out could include files into your
pom.xml. This really could have positive effects on the inheritance issue too.
Okay to straighten this a little bit. I guess the Apache Maven did some of the most innovative work on the build sector in the last few years. And I don't consider to switch to make or Apache Ant. It makes many things a lot easier and most of my critique may be corrected in further versions
I already had a peek into the Maven3 source code and I'll guess the Maven/Sonartype guys will level some of this issues. I 'am very curious about Maven3 and I hope it will ease some of my pain related to the Version 2 of Maven.
So, it was great to get some thoughts clear about what is important when you build a project and what are the different facets when you use a build tool. I had a first look on Apache Buildr maybe I get enough stuff together to create a blog entry about it ...