Page 2 of 3
This reminds me of the situation in the late 90s when Swing was added to the JDK (version 1.2 in 1998), Internet Explorer became the dominant browser that only supported Java 1.1 and suddenly users had to install a rather large browser plugin to run applets. I think it is safe to say that this killed Java in the browser and almost killed Java as a language before it had a strong comeback on the server side. A particular problem was the large size of the plugin (remember that the internet was slow back then and many people were still on dial up). But given the dependencies between the toolkits, even if you were using only AWT you had to download (the much larger) swing as well!
9637 if (Component.isInstanceOf(this,
9638 if (((javax.swing.JComponent) this).
Reference to javax.swing.JComponent in java.awt.Component (click here to explore the dependency graph)
A common point made here is that there might be another reason, not known to the outsider, for having this dependency here. Or, in other terms, that a behaviour-preserving refactoring that breaks this dependency is just not possible. But this is definitely not the case here: in the alternative Apache Harmony implementation of the JDK, this dependency is missing.
The following table shows the size of some programs in terms of their dependency graph (nodes are classes, edges are relationships), and the number of antipattern instances found.
|system||classes (nodes)||dependencies (edges)
Many programs also have a large number of both class and package tangles. In mathematical terms, tangles are strongly connected components - every artifact in a tangle (directly or indirectly) depends on every other artifact within the tangle. Software engineers often refer to tangles as “big balls of mud”. An extreme example is azureus-18.104.22.168.jar with a package tangle consisting of 373 packages and a class tangle consisting 2698 classes!
Packages inside the large (373) package cluster in azureus-22.214.171.124.jar (click here to explore the dependency graph)
Detecting Dependency-Related Problems
There are a number of tools that can extract, display and analyse the dependency graph. There are two approaches to detect critical dependencies: metrics and patterns.
Metrics associate artifacts and their relationships with numerical values expressing quality. The classical example is distance from the main sequence (D) - a metric for packages. It states that abstract packages should have relatively many incoming dependencies (high responsibility), while concrete (implementation) packages should have relatively few incoming dependencies but will depend on other packages (high instability and low responsibility). The classic tool to detect the D metric is JDepend. JDepend computes several package dependency metrics, and can be easily embedded into IDEs and build scripts. It also supports the detection of circular dependencies between packages.
Some of the general (anti-) patterns are described above. Some tools also allow the user to define project-specific patterns, often relating to application tiers and their dependencies. For instance, if the persistence layer must not depend on the presentation layer, dependencies between classes in the respective layers become antipatterns.
Systematic and scalable pattern analysis is not well-supported by any existing tool, and was reason we started to develop our own set of tools. This tool is based on the GUERY graph query library we have developed and open-sourced. The Massey Architecture Explorer is an HTML5-based front end using this library.
There are well-known scalable algorithms for detecting tangles (such as Tarjan’s algorithm) and many commercial tools support tangle detection. Free tools that support tangle detection include Google’s CodePro Analytix (formerly Instantiations) and the Massey Architecture Explorer.
Another good free tool that extracts and visualises the dependency graph using an UML-like notation is Programmer's Friend Class Dependency Analyzer (CDA). Commercial programs that can be used to analyse and visualise dependencies include Lattix, SonarGraph for Java and Structure 101.