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.