When I see code that violates the DRY principle or contains a load of String literals, I tend to immediately jump into refactoring mode. Yet, as Paul recently point out to me, when we (as developers) construct and maintain build files, all those code perfectionist ideals seem to disappear.
For example, I was recently working with an Ant build file that had a maven-esque mechanism for managing dependencies. The build script downloaded each required binary dependency at build time via Ant’s get task like so:
<get dest="${cvg-libs}/commons-lang-1.0.1.jar"
usetimestamp="true" ignoreerrors="true"
src=
"http://www.ibiblio.org/maven/commons-lang/jars/commons-lang-1.0.1.jar"/>
This particular project has over 20 dependencies; therefore, there were over 20 get targets like the one above. This build script was in danger of becoming a maintenance nightmare if someone decided to upgrade a few different libraries!
Note how commons-lang-1.0.1.jar is repeated twice, meaning that someone would have to update the version twice during an upgrade. Also note the base URL- ibiblio was the main download source for 80% of the binaries.
These get tasks can be refactored to utilize the DRY principle by mimicking the Replace Magic Number with Symbolic Constant technique. By breaking out and up the String values, the build file can become more manageable and therefore, more maintainable.
For example, the above Ant code can be refactored into
<property name="commons-lang.jar" value="commons-lang-1.0.1.jar"/>
<property name="commons-lang.dir" value="/commons-lang/jars/"/>
<property name="base.ibiblio.url" value="http://www.ibiblio.org/maven/"/>
<get dest="${cvg-libs}/${commons-lang.jar}"
usetimestamp="true"
ignoreerrors="true"
src="${base.ibiblio.url}${commons-lang.dir}${commons-lang.jar}"/>
Now, when a library’s version requires updating, one only has to edit one String; moreover, if the file’s location changes, or the team decides to host all binaries locally, one property requires changing, not 20 plus.
The next time you happen to be in a refactoring mood, have a look at your build file. Just remember to verify it works before and after you improve it.

March 30th, 2006 at 12:41 pm
Andrew,
Good point. Of course using a build.properties file for such properties is a natural extension of this idea. However, for bigger projects — rather for bigger build files
— one can identify /types/ of changes. I like to call these “axes of change”, and I prefer to use a build_.properties file per such axis.
To illustrate this point, say you have properties dealing with libraries like you discussed, these properties would form one axis of change or maintainability hence would go in a “build_lib.properties”. Another axis of change would be the deploy locations for your final distributables which may or may not include other properties like APP_SERVER_HOME etc. which would go in a “build_dir.properties”
This works out well, since as you can imagine, typically it is desired to make changes along just /one/ of the axes at a given time.
September 20th, 2006 at 10:28 am
I agree that often build scripts would need some refactoring, and I think that what stops some of us is that we get use to have great support for refactoring in the IDE for source code, but there is no refactoring tool for ant build script. While having an extract property would really be nice, for example. Or even an extract macro, or target.
OTH, for the example you give, you should have a look at Ivy. In this particular case the configuration should be pretty easy to do, and you would have a good set of features for free: better independence between the build and dependency management, true independence between dependency declaration and their actual location, …
January 18th, 2007 at 10:27 pm
[…] While not perfect, it certainly is more in line with what I’d do if I were coding this logic in C#, for example. A build file (or files) is one of the most important assets a project has– without an effective build, no matter how many tests you write or how perfect the code is, customers will have a hard time receiving working, reliable applications. So the next time you find yourself wincing at your build script, take the time to refactor it, man! […]
January 17th, 2010 at 8:01 am
[…] Andrew Glover writes about it […]