Agile Developer’s Toolbox: JDepend4Eclipse
What does dependency analysis mean to you? To me it mostly translates to the fact that Common Services (CS) packages should not depend on any of their clients. Does that happen in practice? More than enough to make the case for dependency analysis.
Just like the other tools in this series JDepend can be used in Eclipse or as part of a Continuous Integration cycle. I like to see what’s going on in terms of dependencies and other architectural metrics all the time, so I use both. JDepend calculates:
-
Total number of classes and interfaces - number of concrete and abstract classes (and interfaces) in the package is an indicator of the extensibility of the package. How many?
-
Afferent couplings (Ca) - number of other packages that depend upon classes within the package is an indicator of the package’s responsibility. Who depends on me?
-
Efferent couplings (Ce) - number of other packages that the classes in the package depend upon is an indicator of the package’s independence. Who do I depend on?
-
Abstractness (A) - the ratio of the number of abstract classes (and interfaces) in the analyzed package to the total number of classes in the analyzed package. The range for this metric is 0 to 1, with A=0 indicating a completely concrete package and A=1 indicating a completely abstract package. How abstract I am? If I change today, how many of my dependents have to change with me?
-
Instability (I) - the ratio of efferent coupling (Ce) to total coupling (Ce + Ca) such that I = Ce / (Ce + Ca). This metric is an indicator of the package’s resilience to change. The range for this metric is 0 to 1, with I=0 indicating a completely stable package and I=1 indicating a completely instable package. How stable am I? Do I change often?
-
Distance to Main Sequence (D) - the perpendicular distance of a package from the idealized line A + I = 1. This metric is an indicator of the package’s balance between abstractness and stability. A package squarely on the main sequence is optimally balanced with respect to its abstractness and stability. Ideal packages are either completely abstract and stable (x=0, y=1) or completely concrete and instable (x=1, y=0). The range for this metric is 0 to 1, with D=0 indicating a package that is coincident with the main sequence and D=1 indicating a package that is as far from the main sequence as possible.
-
Package dependency cycles - dependency cycles are reported along with the hierarchical paths of packages participating in package dependency cycles. If I depend on you and you depend on me, we have to work hard to adapt to each other’s changes, don’t we?
The JDepend4Eclipse plugin is an implementation of the JDepend tool. It follows the same principles and provides visual analysis inside Eclipse. One thing to note is that the plugin works on compiled java bytecode, so its important for your project to build. Related to this is the fact that if you’re following the same package/folder structure for your unit tests as your source code it might be a good idea to compile them into a separate output folder, separate all unit tests into another Eclipse project or just change the unit test package names (by appending the name test for example ), like I show below.
Quick Tutorial
-
Download and start Eclipse 3.2
-
Navigate to Help | Software Updates | Find and Install
-
Select Search for new features to install
-
Add a new remote site JDepend4Eclipse and point it to http://andrei.gmxhome.de/eclipse/
-
Finish the wizard and restart Eclipse
-
Download the sample solarsystem project from http://www.testearly.com/resources/agile/solarsystem.zip. Open the project in Eclipse. Note that this sample requires Java SDK 6.0.
-
Build the project
-
In the Package Explorer, right-click the source folder src/main/java and select Run JDepend analysis
-
In the newly opened JDepend perspective click on com.solarsystem.jupiter. Notice how the dependencies, packages with cycles, efferent and afferent dependencies and the metrics views get populated
-
Notice in the Dependencies view that the com.solarsystem.jupiter package has 3 Concrete Classes (CC), 1 Abstract Class (AC), 4 Afferent Dependencies (Ca) and 7 Efferent Dependencies.(Ce) Also the Abstractness (A) is 0.25 while the Instability (I) is 0.63. Finally, the Distance (D) to the main sequence is 0.11 which is denoted by a green dot in the Metrics view. Also in this view, notice that the package is marked as having a cycle. This is because the unit test PlanetUtilTest resides in the same package. JDepend works on compiled java code and therefore it picks up everything in the target/classes folder, including any unit tests. There is plenty of theory behind the various metrics gathered by JDepend and they are beyond the scope of this quick tutorial. It suffices to say that for any given package the shorter the Distance (D) to the main sequence, the better. In the above case the com.solarsystem.jupiter is used by four other packages, thus Ca=4. The package depends on 7 other packages, including junit.framework, therefore the Ce=7.
-

-
Generally speaking cycles between packages indicate complex interdependencies and should be avoided. In this step, let’s eliminate the cycles in the project.
-
In the Package Explorer locate src/test/java anc right-click on PlanetUtilTest
-
Select Refactor | Move…
-
Create a new package com.solarsystem.test.jupiter and click OK
-

-
Return back to src/main/java. Right-click and select Run JDepend analysis. All cycles are gone. While we eliminated the cycles, notice also that the distance jumped to 33 from 11 and is now denoted by a black dot.
-
In Java Browsing perspective select File | New | Interface. Enter a name, IBogus, select the package com.solarsystem.jupiter and click OK. This is just an empty interface.
package com.solarsystem.jupiter; public interface IBogus { } - Build the project
- In Package Explorer, right-click the source folder src/main/java and select Run JDepend analysis
- Notice the Distance is now 16 and the dot turned green. But what did the IBogus interface add to the package? Nothing. It just fooled the tool. This is where special care must be taken. Sometimes emty or unused abstract classes can negatively impact the static analysis and make one belive that the package is in a better state than it actually is. My recommendation is to use other tools that detect unused classes and imports and get the whole system cleaned-up before each dependency analysis.
- Enjoy.
