Friday, February 12, 2010

Event Horizon

When working in an agile environment, being able to control parts of the architecture like layers, conventions, etc, is usually desired, while letting the teams make most of the design decisions. Easier said than done. In this model the architect envisions the initial architecture and, communicates the architecture to the team. The architecture evolves over time according to the needs, while the architect shapes it, to keep things simple and “right”.

Keeping track of what’s going on in a large code base is virtually impossible. Even the most skilled developers might miss architecture violations, while performing code reviews for a big chunk of code.

In order to solve this I use a powerful tool called Structure-101 (I call it s101). The s101 client on its own is brilliant for analyzing the code base and defines / communicate the desired architecture. However having to manually check out the latest code, check for new violations, see what has changed and notify the developer, who created new violations, is tedious and time consuming. Luckily s101 comes with a command line utility called S101Headless, which can be integrated into your nightly build. The S101Headless utility allows you to test for new / existing structural violations / increased code complexity, and publish a new snapshot.

The strategy that I use with s101 is as follows. First I analyze the code base, define the architecture diagrams, and extract recommendations for refactoring. Later by integrating s101 into the nightly build, I control the evolution of the architecture. Legacy code bases usually contain many design tangles which are hard to get rid of, and, usually you won’t get the resources for refactoring… Still it is easy to seal the complexity and isolate it from the “happy code”. S101 allows you to break the build only on when new architectural violations show up.

The current version of S101Headless is somewhat awkward to use with Ant, even though it is much better than the previous version. The utility consumes an XML file containing the operations you want executed. But hey, the arguments are usually dynamic, especially in a build environment. The documentation suggests utilizing the echo task in order to write the XML file to disk. While this approach allows you to use the Ant variables, it is makes your XML file less readable. Here’s how I do it:

First you need a template file (s101headless-template.xml):
<?xml version="1.0" encoding="UTF-8"?>
<headless version="1.0">

        <operation type="check-architecture">
            <argument name="output-file" value="@REPORTS_DIR@/arch-violations.csv"/>
            <argument name="onlyNew" value="true"/>

        <operation type="publish">
            <argument name="rpkey" value="c0d3s1ut"/>

        <argument name="local-project" value="@S101_LOCAL_PROJECT@">
            <override attribute="classpath" value="@CLASSPATH_OVERRIDE@"/>
        <argument name="repository" value="@S101_REPOSITORY@"/>
        <argument name="project" value="@S101_PROJECT@-snapshots"/>

In the Ant build file I use copy with a filter chain to render the XML for the S101Headless utility:
<target name="prepareHeadlessFile" depends="setup_classpath">
                <copy file="s101headless-template.xml" tofile="s101headless.xml" overwrite="true">
                                <replacestring from="@CLASSPATH_OVERRIDE@" to="${my-jars-path}"/>
                                <replacestring from="@REPORTS_DIR@" to="${s101.reports.dir}"/>
                                <replacestring from="@S101_PROJECT@" to="${}"/>
                                <replacestring from="@S101_REPOSITORY@" to="${s101.repository}"/>
                                <replacestring from="@S101_LOCAL_PROJECT@" to="${s101.local.project}"/>

        <target name="s101" depends="prepareHeadlessFile">
                <mkdir dir="${s101.reports.dir}"/>
                <java classname="com.headway.assemblies.seaview.headless.S101Headless" fork="true" errorproperty="s101.failure" resultproperty="s101.result.code" maxmemory="512m" dir="${}">
                                <pathelement path="${}/structure101-java-b586.jar"/>
                                <pathelement path="${basedir}"/>
                        <arg value="${basedir}/s101headless.xml"/>
                <!-- fail if there were errors in the S101Headless execution -->
                <condition property="s101.violations.found">
                                <equals arg1="${s101.result.code}" arg2="0" />
                <fail if="s101.violations.found" message="${s101.failure}"/>
I leave the Ant classpath and properties setup as an exercise to the reader ;)

As a complementary to the nightly build analysis, s101 also offers an IDE plugin, which allows connects to the structure 101 repository, and can display real time errors / warnings when new violations are detected in the code. IMHO the Eclipse plugin is still in its infancy, and requires some improvements. In the near future (I hope), it will provide a real time, 24/7, protection against evil code :D

BTW, can anyone guess why I called this post “Event Horizon”?

No comments:

Post a Comment