A major contributor to large code bases becoming brittle is the dependencies between pieces of code. If class A uses class B, then A depends on B and a change in B may cause A to malfunction. That's not too bad if there are only 2 classes, but becomes impossible to track manually as code bulks up. The difficulty is that complexity, as measured by the number of dependencies between units of code, does not merely increase linearly with the quantity of code. In fact, the function is quadratic and the curve is parabolic.
This is why architecture-minded folks try to impose certain code architectures: to tame -- though never quite slay -- the dreaded complexity dragon. When architectural layers are enforced, code in certain layers cannot directly use -- and depend on -- code in certain layers, and generally dependencies only go in one direction. These boundaries break up the n^2 function. Or they may try to eliminate cyclic dependencies: cycles couple code units together, preventing them from being tested or used in isolation. Or they may use various code metrics to discover potential trouble spots.
This may sound admirable, but for any code base big enough for such architectural enforcement to be worthwhile, I can't imagine doing this exploration by hand. I'd need a tool. Fortunately, there seems to be quite a number of tools out there. The folks responsible for XDepend (now called JArchitect) were kind enough to give me a copy to review. I don't pretend to be any kind of authority on this topic, nor even come close to mastering this tool. But I think this tool is cool enough for me to share a few of its features.
Like other tools, XDepend is capable of generating those "boxes and arrows" illustrations that graphically express the dependencies between code units. But even they acknowledge that such diagrams do not scale: crank up the complexity, and your dependency diagram turns into a cobweb. A dependency matrix diagram like this, on the other hand, scales quite nicely. Expanding/collapsing the tree lets you adjust the granularity from the package level down to the method level. The blue boxes count the number of dependencies in one direction, green in the other, and black counts bidirectional dependencies (i.e., cycles). Mouse-overs display more information for each cell. There is a button that tells XDepend to try to arrange the packages according to their layers. If the code is strictly layered, you would see green boxes on one side of the diagonal, blue on the other and no black boxes. A quick glance at the diagram above tells me that this is not the case with this code.
It took some time for me to begin to understand how this matrix works. But now I appreciate the elegance and information density of this construct. It lets me visualize the dependency pattern of an entire application at a glance, while letting me drill down to the level of detail I want.
Treemap metrics diagram
XDepend boasts of over 80 different code metrics, but it's not easy to get the big picture from a pile of numbers. What is cool about the metrics diagram is that it lets me visualize an entire code base's code units as measured by a particular metric. The relative size of each box corresponds to the selected measure's number for that unit of code. In this case, larger boxes show greater complexity. You can select package, class or method granularity. Hovering your mouse over each box will pop up more information for each box.
This particular diagram measures byte code cyclomatic complexity. Yes, that means you don't need to have source code handy for XDepend to analyze your code: just throw a few jars at it and away you go.
This sounded like something that only experts versed in deep XDepend magic would use. A query language for code: yikes. But it's easier than it looks, thanks to the auto-completion feature in the query editor that lets you pick from a menu of clauses as you build the query. XDepend also comes with a ton of precanned queries that you can modify.
// <Name>Methods too complex (BCCyclomaticComplexity)</Name> WARN IF Count > 0 IN SELECT TOP 10 METHODS WHERE BCCyclomaticComplexity > 40 ORDER BY BCCyclomaticComplexity DESC // METHODS WHERE BCCyclomaticComplexity > 20 are hard to understand and maintain. // METHODS WHERE BCCyclomaticComplexity > 40 are extremely complex and should be split // in smaller methods (except if they are automatically generated by a tool).
XDepend is a polished tool with a ton of other features that I did not even hint about here. It has lots of online documentation and videos to help get started. Nevertheless, it's not an easy tool to learn. Part of this is due to the sheer number of features and the unfamiliarity of the concepts to me. But another factor is that XDepend comes from NDepend, a .NET tool, and much of the documentation and video is actually for the latter. So the docs and videos often use terminology that is foreign to the Java world (like "assemblies"). That said, I think XDepend is a tool well worth exploring, and I will continue to explore its capabilities. Its ability to meaningfully visualize an entire code base makes XDepend a powerful tool with which to gain control over your code.
Update 4/12/2013: XDepend is now called JArchitect, and I have updated the link accordingly. Also, the query language is now called CQLinq. I imagine there's lots of improvements, but the improvements are not reflected in this this blog post, which reflects my review of a much older version.