Using the JDepend Fixture for FitNesseThe JDepend fixture is named Module Dependencies. It provides a FitNesse fixture interface for JDepend.
Good Java designers partition their application into components. These components may all be placed in a single .jar file, or they be separated into many different .jar files. We want to avoid dependency cycles between these components so that the system is buildable, and that the components are independently deployable.
Keeping component dependencies under control is hard, because it's so easy to violate them. Any programmer can put an import or reference into a module that inadvertently builds a cycle, or creates an unwanted dependency. What we need is a tool that can be run at every build to check that there are no cycles, and no unwanted dependencies. JDepend (you can get it at http://www.clarkware.com/software/JDepend.html) is a tool that analyzes component dependencies by scanning .class and .jar files. It generates reports about the dependencies in your application. It also provides an api that you can use to write JUnit tests to ensure that your application has only the desired dependencies.
Writing JUnit tests for this can be awkward. So I wrote a FitNesse fixture that allows you to represent the dependencies of your system as a table. The fixture invokes JDepend and makes sure that only the dependencies you signify in the table are actually present in your application. The following table describes a system with two components, where component a depends upon component b.
If this were executed as a FitNesse fixture, and if module a really did depend on module b, then the cell with the x would be colored green. Any other dependency would cause the corresponding cell to be colored red. For example, if a did not depend upon b; and if b depended upon a instead, then the cell with the x would be left uncolored, but the cell denoting the dependency from b to a would be colored red.
To say this another way: The names of the components appear accross the top, and down the left side, of the table. The left side denotes the source of a dependency (the depending component), the the top row denotes the target of the dependency (the depended upon component). You put an X in any cell that represents a dependency that you would like to allow. You leave the cells for any unwanted dependencies blank. If any allowed dependency exists, that cell will be green. If any allowed dependency does not exist, that cell will be uncolored. If any disallowed dependency exists, then that cell will be colored red.
What is a module.A module is a synonym for a component. For our purposes a module is a package that contains many other packages. For example, the package payroll might contain payroll.tasks, payroll.commands, payroll.exceptions, payroll.reports, etc. The Module Dependencies fixture counts dependencies from the contained packages as dependencies belonging to the component. So, for example, if there are two components named payroll and gui, and if gui.dialogs depends upon payroll.employee, then the Module Dependency fixture will infer that the gui component depends upon the payroll component.
Cycles.If the Module Dependencies fixture detects a cycle between components, it will color all the dependencies within the cycle red, and mark them with the word 'cycle'. They'll stick out like a sore thumb, and you can track them down. Running JDepend to generate the dependency report will be helpful in tracking down the individual dependencies.
Table StructureIf your modules don't have a cycle, then they are arranged as a tree. If you order the modules in the table such that the independent modules are at the top and left, while the most depended modules are at the bottom and right, then you will see that all the dependencies occupy the section of the table that is above the diagonal, as shown below:
The cells marked with dashes denote the diagonal. You don't have to put the dashes in if you don't want. The fixture will automatically color these cells grey for your convenience.
This table topology is handy. If you can arrange all the dependencies such that none are below the diagonal, then you can be certain that there are no cycles between the modules dependencies.
Details for use:To use the fixture, download it and put it in a handy directory. On (or above) the fitnesse pages where you want to use it, put !path statements that point to the directory that contains the fixture .class files. Also put a !path statement that points to the JDepend jar file.
Make sure you are using JDepend 2.8+
It is handy to put the following import table at the top of the page
Denote the location of the class and jar files for the system you want to analyze using the Module Dependency Paths table as shown below:
|Module Dependency Paths|
You can have as many lines in this table as you like. The JDepend fixture will search them all.
Create the Module Dependencies Table by listing the packages that contain your modules accross the top and down the left of the table. Put Xs (or actually anyting non-blank) in the cells that denote desired or allowed dependencies. Leave the rest blank.
Sometimes your module names will be long, with many prefixed packages. For example you might have modules with names like com.company.payroll.a, com.company.payroll.b, com.company.payroll.c.one, and com.company.payroll.c.two. To avoid repeating all the prefixes in the table, you can add a prefix argument in the cell after the fixture name as follows:
The '.' in the front of the modules above indicate that the prefix should be used. Without the '.' then the fully qualified name of the package should be used.
Conclusion.Have fun with this fixture. I hope you find it useful for managing the dependencies between your modules. Remember that the prime motivation for using Object Oriented Design is to manage module dependencies.
23 December 2004, Robert C. Martin.
26 December 2004, Stefan Roock
Cool! Some additional lightweight tools for managing dependencies are described at <http://www.stefanroock.de/weblog/blogger.html>.
27 December 2004, IljaPreuss[?].
I guess the "!" in the latter examples should be "x", too?
- No, any non-blank entry denotes an expected dependency. I started using !, but then changed the convention to X.
The link to download this fixture could be made more prominent for those of us that ignore the first couple of sentences when reading an article ;) Could you make the words 'download it' into a link? How about an entry on the left-hand menu?
When I click on the "Here" link, I get a "The requested resource: files/downloads/ModuleDependencyFixture.[?]zip was not found." message. Any ideas?
Add Child Page to JdependFixture