Ant - Metatargets and a build script Antipattern
A few days ago I was reading an article on the Object Mentor website entitled How To Misuse Ant. One bit of the article in particular caught my attention because it runs completely counter to the way that I have created targets in the past. The bit was about using Metatargets instead of the depends keyword.
By making lots of small targets that do one thing well, you introduce the possibility of chaining them together to do different operations. These “metatargets” allow people to use the build in ways you never anticipated. What horror! Things must be done the way you define them back when you originally wrote the script. Why would anyone have the arrogance to do it another way?
If you have to decouple into small targets, make sure you chain them all together using the depends keyword. It’s almost as good as the OneBigTarget.
To me this makes a lot of sense. However, I see a danger with this thinking; what happens when people run those small, individual targets without first running targets that they do depend on? I can’t run a test target without first compiling the tests or compiling the code or initializing the build directories, etc.
To solve this do I make all the little targets private and the Metatargets public? This to me seems like the most logical explanation. But then my mind wanders over to how communicative this is. A Test target really does depend on certain targets being run successfully before it can run. Putting in a depends attribute communicates this to people. On the other hand, it tightly couples the Test target to its dependencies and possibly prevents the test target to be run later in the build process.
One build antipattern I have definitely identified so far is, what I call, dependency chaining. By this I mean where you create a target that depends on another target which depends on another target which depends on another target and so on. In order to understand the initial target you have to trace your way through 5 or 10 targets to fully understand what the target does.
Using the idea of Metatargets should solve this problem by more explicitly showing exactly what the target does. This makes it a lot easier for a new developer to understand the intent behind a target.