ter SampleConfiguration - Architecture Rules - Wiki

SampleConfiguration

From Architecture Rules - Wiki
Jump to: navigation, search

The simplest and most effective way to setup your rules, is to create architecture-rules.xml in a directory such as /src/main/resources, or any other directory that will end up in the project’s classpath. Once the file is created, add your configuration and rules such as in this example below.

Contents

architecture-rules.xml

<architecture>
 
    <configuration>
 
        <sources no-packages="exception">
            <source not-found="ignore">
               core\target\classes
            </source>
            <source not-found="ignore">
               web\target\classes
            </source>
            <source not-found="exception">
                ws\target\classes
            </source>
        </sources>
 
        <cyclicalDependency test="true"></cyclicalDependency>
 
    </configuration>
 
    <rules>
 
        <rule id="web-layer-with-wildcards">
          <comment>web and dao mix like oil and water</comment>
          <packages>
            <package>com.company.app.web</package>
            <package>com.company.app.web..*</package>
          </packages>
          <violations>
            <violation>com.company.app.dao</violation>
            <violation>com.company.app.dao..*</violation>
          </violations>
        </rule>   
 
        <rule id="dao">
            <comment>
                integration layer is independent
            </comment>
            <packages>
                <package>com.company.app.core.dao</package>
                <package>com.company.app.core.dao.jdbc</package>
            </packages>
            <violations>
                <violation>com.co.app.core.services</violation>
                <violation>com.co.app.web</violation>
                <violation>com.co.app.web.spring</violation>
            </violations>
        </rule>
 
    </rules>
 
</architecture>


Sample Configuration Breakdown

Here is an explanation of the various XML nodes.

Sources

<sources  no-packages="exception">
    <source not-found="ignore">core\target\classes</source>
    <source not-found="ignore">web\target\classes</source>
    <source not-found="exception">ws\target\classes</source>
</sources>

Sources are the directories that JDepend will analyze. The Jdepend docs call these sources, but in reality you want to point to your complied classes.

<sources no-packages="ignore">

Valid no-packages values are ignore and exception.

  • ignore will continue on when the source directory does not exist
  • exception will throw a SourceNotFoundException when the directory does not exit
<source not-found="ignore">core/target/classes</source>

Sources can be a relative path or an absolute path. Valid not-found values are ignore and exception.

  • ignore will continue when no packages exist, but nothing will be tested. Not recommended.
  • exception will throw a NoPackagesFoundException: No packages found when no packages are found in any of the given sources.

Cyclic Dependency Test

<cyclicaldependency test="true"></cyclicaldependency>

Easy as true or false to indicate weather you want this test to run or not. When this test runs and fails, a CyclicRedundencyException is thrown.

Rules

Rules define a package, and then go on to list each package that would be considered a violation to depend on. An id is used to refer to the rule when something goes wrong, and a comment may be entered in order to document the rule for future developers (or even for yourself for that matter.)

  <rule id="dao">
    <comment>
        dao layer depends on no other layers
    </comment>
    <packages>
        <package>com.co.app.core.dao</package>
        <package>com.co.app.core.dao.jdbc</package>
    </packages>
    <violations>
        <violation>com.co.app.core.services</violation>
        <violation>com.co.app.web</violation>
        <violation>com.co.app.web.spring</violation>
    </violations>
  </rule>

Wildcards

You may also use wildcards to define your packages. Consider the following rule that dictates packages and sub-packages of the web “layer” may not access packages or sub-packages of the dao “layer”. Note that we must define the web package, and then the web sub-packages with two different package elements.

  <rule id="web-layer-with-wildcards">
    <comment>web and dao mix like oil and water</comment>
    <packages>
        <package>com.company.app.web</package>
        <package>com.company.app.web..*</package>
    </packages>
    <violations>
        <violation>com.company.app.dao</violation>
        <violation>com.company.app.dao..*</violation>
    </violations>
  </rule>

Here is a description of how wildcards tokens may be used, and where they can be used. Match One Package Match Many Packages Match to the depth of one package with the .* combination Match to the depth of one or more packages with the ..* combination

Internal Wildcard Terminating Wildcard Wildcard stated within a package. Wildcard stated at the end of a package. com.company.*.dao com.company.project.dao.*

When defining your Rules, ids can not be duplicated, but packages can. If you want to break up violations for the same package you can do that.

You can add more than one package to a rule. For example ..dao and ..dao.hibernate packages are probably going to be the same, so you can define them in a single rule. This is a change from the version 1 releases.

You can not add a violation that is identical to the package. This is because, in reality, if you have a class that uses a class in the same package, no imports are defined, and therefore this situation can not be tested. If you try this, you will get an IllegalRuleException

Sample Programmatic Configuration

You also have the option of programmatic configuration when running architecture-rules as a unit test - you don’t have this option when running via the ant-task. Assuming you followed the getting started tutorial, you now have a unit test that extends AbstractArchitectureRulesConfigurationTest. From here, you can simply call getConfiguration() which will return the Configuration entity that has been populated with the settings from architecture-rules.xml. With this Configuration reference, you may not create new Rule and SourceDirectory entities and add them to the configuration.

Example

/**
 * Get the configuration that already has the
 * architecture-rules.xml configuration loaded.
 */
final Configuration configuration = getConfiguration();
 
final Rule rule = new Rule("services");
rule.setComment("services may not depend on web layer.");
rule.addPackage("com.co.app.core.services");
rule.addViolation("com.co.app.web");
rule.addViolation("com.co.app.web.spring");
rule.addViolation("com.co.app.web.decorators");
 
configuration.addRule(rule);
 
/**
 * Changing a boolean like
 * configuration.setDoCyclicDependencyTest(false)
 * would override the value in the configuration file,
 * because the configuration file is loaded first.
 */
configuration.setDoCyclicDependencyTest(false);

In this example, the configuration is pre-populated with the configuration found in the XML file with the name returned by the method String getConfigurationFileName() in your unit test. If you do not implement this method, or if you return “” then the configuration will be empty.

Personal tools