Architecture Rules eats his own Dog Food
Reprinted from Architecture Rules eats his own dog food with permission from Mykola Nikishov
While adding support for YAML configuration files I introduced a cyclic dependency (shame on me) in our code base. If this means nothing to you there are some reasons why introducing cycles considered as a bad practice.
How to catch problems like this one?
Your project’s build system must be ready for this. Integrate tools like Architecture Rules or any other alternative tool into your Maven, Ant or whatever build system of your choice.
Build your projects and run tests against them continuously, with Hudson, CruiseControl or TeamCity
Sounds obviously for you? For sure.
As the problem popped up as soon as it was introduced, fixing it was a trivial task. I absolutely agree with a statement that every piece of code becomes “legacy” few hours after it’s written. Distributed development teams make such things even worse. `Individuals and interactions over processes and tools’ don’t work.
How did I discovered this? First of all, this post is about eating your own dog food, right? One of the purposes of Architecture Rules is to report on cyclic dependencies among your project’s packages and classes. And my build system was ready to catch this with just running mvn test.
How this looks like? As a plain old unit test’s failure:
Results :
Tests in error:
testArchitecture(org.architecturerules.SimpleArchitectureTest)
Tests run: 99, Failures: 0, Errors: 1, Skipped: 0
In my case more details are in the target/surefire-reports
org.architecturerules.SimpleArchitectureTest.txt:
------------------------------------------------------------------------------- Test set: org.architecturerules.SimpleArchitectureTest ------------------------------------------------------------------------------- Tests run: 1, Failures: 0, Errors: 1, Skipped: 0, Time elapsed: 0.54 sec <<< FAILURE! testArchitecture(org.architecturerules.SimpleArchitectureTest) Time elapsed: 0.532 sec <<< ERROR! org.architecturerules.exceptions.CyclicRedundancyException: 2 cyclic dependencies found: -- org.architecturerules.configuration.xml depends on | | | |-- org.architecturerules.configuration | |-- @ org.architecturerules.configuration.xml.DigesterConfigurationFactory | \ while | |-- org.architecturerules.configuration.DefaultConfigurationFactory | \ depends on org.architecturerules.configuration.xml | -- org.architecturerules.configuration depends on | | | |-- org.architecturerules.configuration.xml | |-- @ org.architecturerules.configuration.DefaultConfigurationFactory | \ while | |-- org.architecturerules.configuration.xml.DigesterConfigurationFactory | \ depends on org.architecturerules.configuration | at org.architecturerules.services.CyclicRedundancyServiceImpl.buildCyclicRedundancyException(CyclicRedundancyServiceImpl.java:162) at org.architecturerules.services.CyclicRedundancyServiceImpl.performCyclicRedundancyCheck(CyclicRedundancyServiceImpl.java:117) at org.architecturerules.AbstractArchitectureRulesConfigurationTest.doTests(AbstractArchitectureRulesConfigurationTest.java:143) at org.architecturerules.SimpleArchitectureTest.testArchitecture(SimpleArchitectureTest.java:51)
Thanks to our Maven 2 plugin your build will fail too as soon as you introduce cycles in a dependency graph. Even if your project uses Apache Ant (sorry, it’s not my favorite tool) as a build system, you can download and use our Ant task to get the same result.
How-to setup Ant task? Sorry, it’s still not available and I have any clue. In a response to this post Mike provided this great how-to install and configure guide. Thank you, Mike!
XML Report Prototype
One of the 3.0 Roadmap items is an XML report. Eventually we will use this XML output for a Maven 2 report and hopefully it will be used to write a Sonar Plugin and a Hudson Plugin. We’ve prototyped one possible format for this output. This output should be enough to generate a rich architecture report for maven 2 and eventually provide DSM analysis and reports.
Have a look, then I will identify each section of it and mention why its been designed the way it was.
The XML
<architecture>
<rules>
<rule id="dao_layer_rule">
<comment>dao layer may not access service or web layers</comment>
<packages>
<package>com.company.project.dao</package>
<package>com.company.project.dao..*</package>
<packages>
<violations>
<package>com.company.project.service</package>
<package>com.company.project.service..*</package>
<package>com.company.project.web</package>
<package>com.company.project.web..*</package>
</violations>
</rule>
</rules>
<analysis>
<packages>
<package package="com.company.project.dao.hibernate.person">
<matches>
<rule>dao_layer_rule</rule>
</matches>
<dependencies>
<package>com.company.project.dao</package>
<package>com.company.project.dao.hibernate</package>
<package>com.company.project.service</package>
</dependencies>
<violations>
<violation violates="dao_layer_rule">com.company.project.service</violation>
</violations>
<cycles>
<cycle>com.company.project.service</cycle>
</cycles>
<classes>
<class class="HibernatePersonDAOImpl">
<dependencies>
<package package="com.company.project.dao">
<classes>
<class>PersonDAO</class>
</classes>
</package>
<package package="com.company.project.dao.hibernate.person">
<classes>
<class>AbstractHibernateDAO</class>
</classes>
</package>
<package package="com.company.project.service">
<classes>
<class>PersonService</class>
</classes>
</package>
</dependencies>
<violations>
<package package="com.company.project.service">
<classes>
<class>PersonService</class>
</classes>
</package>
</violations>
<cycles>
<package package="com.company.project.service">
<classes>
<class>PersonService</class>
</classes>
</package>
</cycles>
</class>
</classes>
</package>
</packages>
</analysis>
</architecture>
Explanation
There are two major parts to the report. The first is the rules elements. The second is the analysis elements.
The rules elements simply regurgitate the user’s rules as the user defined them. Architecture Rules is hopefully going to provide so much useful information someday that users would potentially not even define any rules and just use Architecture Rules to detect cyclic dependencies, get reports on their architecture including class and package dependencies, and someday Design Structure Matrix analysis. But for now I believe most of our users utilize rules, since that is what this project is currently designed to do.
The second element is the analysis element. This is were we will put everything that we discover about every package and class in the analyzed code base. Lets look at each element under the analysis element individually.
<analysis> Elements
For each package in the project that we analyze, we will output:
Rules
Each rule that was matched. This indicates which rules were matched based on the exact package names and wildcarded package names that you have defined in your architecture-rules.xml
Dependencies
Lists every package that the package under investigation depends on, including packages that are defined as a violation and packages that are involved in a cyclical dependency.
Violations
Lists packages that are defined as violations.
Cycles
The packages that are involved in a cyclical dependency with the package under investigation.
Classes
Now that we have listed dependencies at the package level, we are going to have an in depth look at each class within that package. So the package level analysis is a sort of summary of the information found at the class level.
For each and every class in the package under investigation we’ll output the class’s dependencies, the violations (as determined by the matched rules and that rule’s violations as described in architecture-rules.xml) and each class that is involved in a cyclical dependency with the class under investigation.
We would appreciate any feedback that you might have on this output. It might take a while to read and really digest all of the information that this report contains within it, but the sooner we get this prototype reviewed the sooner we can implement it, and the better the review is, the better the chances that we get it right the first time.
Look for a subset of this report in the 3.0 release. We won’t be able to output this entire report until we replace JDepend with a new analysis tool, or write our own.
Hudson
The Sonar team has an instance of Hudson running. Hudson is a fantastic open source continuous integration server.
Here are some links:
Architecture Rules on Hudson
http://ci.sonar.codehaus.org/job/Architecture rules/
Build Status RSS
http://ci.sonar.codehaus.org/job/Architecture rules/rssAll
Modules
http://ci.sonar.codehaus.org/job/Architecture rules/modules

