Build File Pattern: Keep Paths in Properties

Problem: You have paths that are partially or completely identical in multiple locations in your build file.

Solution: Factor out duplication into one or more properties.

Example.

<csc target="library"  output="src\build\bin">
    <!-- removed for clarity -->
</csc>

<copy todir="bin">
    <fileset basdir="src\build\bin">
        <includes name="*.dll" />
    </fileset>
</copy>

<copy todir="bin">
    <fileset basdir="src\build\support">
        <includes name="*deploy.xsl" />
    </fileset>
</copy>

Has three duplications. Factor them out to properties:

<property name="${bin.dir}" value="bin" />
<property name="${build.dir}" value="src\build" />
<property name="${build.bin.dir}" value="${build.dir}\bin" />

<csc target="library"  output="${build.bin.dir}">
    <!-- removed for clarity -->
</csc>

<copy todir="${bin.dir}">
    <fileset basdir="${build.bin.dir}">
        <includes name="*.dll" />
    </fileset>
</copy>

<copy todir="${bin.dir}">
    <fileset basdir="${build.dir}\support">
        <includes name="*deploy.xsl" />
    </fileset>
</copy>

I have become less tolerant of even simple paths if they are duplicated (e.g. ${bin.dir} is longer than the path itself). But, by factoring it out, I can ensure that if I want bin to be one level up from the location of the build file, I can just change the value of the property from "bin" to "..\bin" in one place, and know that all of copy statements will work.

Also, factoring out even sub duplication (e.g. build.dir) means that if you suddenly don't want the compiler output going to src\build (maybe src\build\bin) you don't have to worry about changing both the compiler task and the copy task.

This is just an application of Don't Repeat Yourself, but I see it a lot, maybe because its easy to write build scripts, and even easier to let them get shabby. Or maybe because at first glance, the factored one is harder to read (particularly if there is a long distance in the file between the property definition and its use). Good names for properties, consistent property naming, and a little bit of practice should make this go away.