Maven – inheritance
One of Maven features not appreciated enough (from my experience) is inheritance. Many people are used to the fact that each module had a “build.xml” once. Those Ant files were usually big and they were 80% (or more) copy-pasted since Ant’s support for inheritance was terrible (<import> was supposed to do the job but I never saw anyone using it for actual inheritance – I myself only used it for loading <macrodef> libraries). So it was Ok to have those big Ant files, one per-module. Almost nobody knew for sure what they were doing and almost nobody was capable (or willing) to maintain them – well, that what happens when you copy-paste your build logic and Ant tasks all over the place. But I don’t blame anyone – there was almost no choice with Ant ! (sometimes I hate it as much as I like it: after all, crafting a cool <macrodef> may be a real fun .. but since I’m in a Groovy camp now – I guess those <macrodef> times are also gone for me)
Anyhow, we’re with Maven today and it supports inheritance. This time it’s for real. Any plugin configured in <parent>’s POM will be invoked automatically (unless <inherited> is false). This can be pretty powerful! The only problem left is people not looking for a ways to make their POMs smaller by inheriting <parent> behavior (plugins). I saw developers still copy-pasting plugin configurations from POM to POM, just out of habit doing the same with Ant, I suppose. Not surprisingly, they end up with exactly the same situation they had before – a biiig POM, one per-module.
We can do better! How about this one:
<?xml version="1.0" encoding="UTF-8"?> <project xmlns = "http://maven.apache.org/POM/4.0.0" xmlns:xsi = "http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation = "http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd"> <modelVersion>4.0.0</modelVersion> <groupId>com.company</groupId> <artifactId>VisualStudioModule</artifactId> <packaging>jar</packaging> <name>[com.company:VisualStudioModule]-[SVN/Path]</name>
<parent> <groupId>com.company.visualstudio</groupId> <artifactId>main.2005</artifactId> <version>1.0-SNAPSHOT</version> </parent> </project>
This module is a VisualStudio project and parent POM (com.company.visualstudio:main.2005) invokes Ant which, in turn, invokes “devenv.exe” of VisualStudio 2005. There’s a com.company.visualstudio:main.2008 <parent> as well, doing the same for Visual Studio 2008.
The point is – all I had to do in module’s POM is specify a correct <parent>. No copy-paste and POM itself can’t be any smaller. Having lot’s of similar modules – one would really appreciate carrying around those “smart parents” (as I call them) knowing what to do, once they’re referenced.
We also use this technique for packaging similar archives (there are many modules, each one producing a ZIP with a predefined structure) – we have a parent POM knowing exactly how to pack an archive and all other POMs just reference it, adding a little bit of their own configurations (by further configuring parent’s plugins but I usually prefer defining simple variables that impact the way parent plugins are running – usually, they’re passed as arguments). That’s template pattern in action where parent knows 90% or even 100% of what needs to be done so children have very few work left to do.
This kind of inheritance is a very powerful thing I see in Maven so I suggest to use it more.
I guess nobody wants to end up with tons of huge and almost-similar POMs, spread all over the source tree … Those ancient days are long gone already!