Working with Dependencies to Eliminate Unwanted Cycles
The Dependency Structure Matrix (DSM) is a very powerful and fancy tool to explore your project dependencies. In this article, based on chapter 7 of Sonar in Action, guides you step by step on how to get the best from it. Sonar in action is being written by Patroklos P. Papapetrou and G. Ann Campbell
Dependency Structure Matrix (DSM) is a flexible, colorful and easy-to-use feature that lets you browse dependencies on every level of your projects. You can access it by clicking on any metric on dashboard package widget.
This article will show you at first how to navigate the DSM. Then, we'll show you how to "read" the DSM in order to spot dependencies between software components. We hope that at the end of the article working with dependencies and eliminating cycles will be a piece of cake for you.
Navigating the Dependency Structure Matrix (DSM)
An alternate way to navigate DSM is to choose Design in the left menu. You get a matrix with project modules. If you're viewing a single module project, then the DSM, instead of modules, displays by default project packages. Module packages are also available by double-clicking on any module shown in DSM.
Figure 1 illustrates the difference between the two versions of the DSM view by showing two screenshots taken from Sonar's public instance. The upper version reports on the module dependencies for the XStream project whereas the other one shows a package dependency matrix for a selected module, which, in our case, is XStream Core.
Figure 1 Dependency Structure Matrix views for modules and packages dependencies
As you'll notice, there are no column headers to save some space and simplify the interface, so keep in mind that each column has the same header as its corresponding row. To clarify this, let's take a closer look at XStream modules DSM, shown in figure 2.
Figure 2 Column headers would make DSM look ugly
We've manually added the column headers to help you visualize the information in the graph. Unfortunately, unless you turn your head to the right angle, it's hard to read the content of these headers in figure 2. Now, imagine for a moment, how much more difficult it would be in a very complex program within the Sonar interface. We've seen DSMs that scrolled down multiple "pages." Imagine how much "noise" these labels, repeated as headers, would create to the package matrix you've seen in figure 1.
When you look at the DSM for the first time, it's normal to find it difficult to read the dependencies between components without any column headers. We're pretty sure, however, that most people get used to it pretty quickly.
Before we move on and play a little more with the DSM, it's a good idea to explain what the colors tell you. For now, focus on the colored cells with numbers (see figure 3).
Figure 3 Colored cells in DSM report on dependencies and cycles between components.
First, some of the color cues that apply to the rest of the Sonar interface work here as well: red is bad and gray is neutral. A black number in a gray cell simply reports a count of references between two components. But, a red background (these numbers are white for visual contrast) alerts you to a dependency cycle that could be removed. The numbers in cells that report on the dependencies between the components are colored black for innocuous dependencies or white for cycle dependencies.
One more detail you might find useful: when the DSM lists modules in the left column, then the numbers indicate package dependencies. When the left column shows packages, the DSM shows file dependencies.
Now that you've got a broad idea about the DSM, it's time to move on to how to read the component dependencies it shows. All these numbers shown in the matrix may make you feel lost, so we'll show you how you can get the information you want for your project design in a few clicks. You'll also learn how to identify package cycles that you might want to remove in order to keep the modularity and maintainability of your application in a good shape.
Most of the figures and examples that you'll see in next pages focus on package dependencies. Based on our experience, these dependencies are the most important when we talk about software design and potential package cycles should be carefully examined and removed.
Finding dependencies between components
To examine a package's dependencies, just click on it in the left column. The package's row and its corresponding column are highlighted in blue. The numbers in the package row are the package's incoming dependencies—the other packages that this one includes. Similarly, the numbers in the highlighted column are the package's outgoing dependencies—the packages that this one is included by.
NOTE To remember what rows and columns in the DSM tell you about component dependencies, keep in mind the acronym RICO, which stands for row incoming, column outgoing.
For instance, let's take a look at figure 4. It's a screenshot taken from Sonar's public instance and shows the DSM for the Server module from Sonar itself. As you see, the package org.sonar.server.charts is currently selected (clicked) and its description is highlighted in blue. All cells for the corresponding row and column are also highlighted and colored light blue.
As an illustration, let's do some simple math with the DSM. Assume that you need to find the total incoming and outgoing dependencies of the selected package. All you have to do is sum up the numbers shown in the highlighted row and column and you're done. For the record, org.sonar.server.charts has only one incoming file dependency (the sum of numbers shown in highlighted row) and a total of six outgoing file dependencies (the sum of numbers shown in the highlighted column).
Figure 4 Viewing dependencies of selected component in DSM
You may have already noticed that some rows (other than the selected one) have a color sign (green or gold) at the end of the package description. These colors are your guide to find out which package is dependent on which one. They let you read the dependencies as a sentence. The little legend on the top of the DSM explains the meaning of each color. Green uses (depends on) blue, and blue depends on gold.
So, let's read the dependencies of the highlighted package in figure 4 just like you're reading this book: the org.sonar.server.platform package (green sign) has one (1) file dependency on org.sonar.server.charts (blue highlighted package), which has five (5) file dependencies on org.sonar.server.charts.deprecated package(gold sign).
If you still feel confused with all these numbers and colors then keep reading. We'll clarify them very soon. As we already mentioned, each number represents the total file dependencies (incoming or outgoing) from one package to another. The fact that there are no column headers in the DSM makes it even more difficult to find the dependencies between two specific components but here comes the beauty of DSM.
So far, you've seen that you can click on any row label in the DSM. Now it's time to try clicking on a cell. When you do, you'll notice a couple of changes in the DSM, as shown in figure 5.
Figure 5 Clicking on a DSM cell. Dependencies between selected components are highlighted and differently colored for both directions. Clicked cell also turned purple.
Figure 5 shows how the DSM looks after clicking on the 5 (the fourth cell) in the last row. First, you notice that there are more highlighted rows and columns showing the incoming and outgoing dependencies of the selected components. Now two of the package descriptions are highlighted and turned blue—instead of just one. In addition to highlighting the package name of the cell row you clicked, it also highlights in blue the package that belongs to the clicked column. When you click any single cell in the DSM, you're picking one half of an interaction—where package A meets package B in the grid. To show the full relationship, Sonar lights up the whole rectangle for you, also showing where package B meets package A. So, for instance, in figure 5, we clicked on the fourth cell (column) in the row, so the corresponding package—the fourth row—is also highlighted.
If you're following along on a live instance of Sonar, you've also noticed that the highlight colors have changed. Cells aren't light blue anymore. They're either green or gold to indicate the direction of the dependency, similar to what we showed you in the previous screenshot. And the same rules apply: green depends on blue and blue depends on gold.
You'll also have noticed (if you're following along in a browser) that the two "corner" cells where green and gold meet—bottom-left and top-right—are colored purple. The numbers in each corner reflect the dependencies in one direction of the relationship. So, in figure 5, the empty purple square toward the upper right is where org.sonar.server.charts meets org.sonar.server.charts.deprecated. The corresponding purple square with a 5 at the bottom left shows the other half of that relationship, where org.sonar.server.charts.deprecated meets org.sonar.server.charts. Now that we've explained all the information shown in the DSM, we are ready to move on the next level, which is where you start to hunt down package cycles to improve the design of your application.
You may already be suspicious about the design of the project we've been showing you because there are packages depend on packages that depend in turn on the first packages. (Dizzy yet?) You're right to be suspicious. These are what we call undesired dependencies. You've already seen that some cells in the DSM are red, and you can get a quick take on how bad your design is with a glance at the number of red cells, and an even better understanding by looking at the size of the numbers in them. Yes, big is bad in this case. In this section we'll dive to what the DSM has to tell us about these cycles. First, remember, that even though the column headers aren't shown in the DSM, we know what they are—they're the same as the row labels. So if the first column in figure 5 were labeled, it would say org.sonar.server.ui—to match the first row. The second column would say org.sonar.server.platform—to match the second row. And, so on. The diagonal line of dashes across the grid shows where each package matches up horizontally and vertically. These cells will never have a number in them because it would represent the number of dependencies among classes within the same package—it would be meaningless!
If you visually split DSM in two triangles by drawing a line across all the dashes, then all dependencies that circle back to form cycles are shown in the upper-right triangle. Figure 6 shows the DSM divided into the triangles we described.
Figure 6 Unwanted cycles are displayed in the upper-right triangle
But why do the numbers showing unwanted dependencies all end up in the upper-right triangle? Is it this way all the time? Well, yes. This is the norm because Sonar lists software components (figure 6 shows packages, but it could be modules) so dependencies to cut are always shown in the upper-right triangle.
Low-coupled components are listed at the top of the DSM and components with high coupling are listed at the end. When a cycle is found between two components, then the one with the largest number of incoming dependencies from the associated components is placed lower in the list than the other one.
So far, you've learned that big numbers in red cells is a message that you have many cycles in your application that could be removed. But this is not enough. Knowing that you have a total of N cycles in your project or module is just the beginning. You need to look at components as pairs and get more information in a file-level.
When you're looking a package level DSM, double-clicking on a cell gives you a list of file dependencies. When the cell you clicked is a red one, then this lists represents the file dependencies that could be removed to eliminate the package cycle (see figure 7).
Figure 7 Double-clicking on a numbered cell, you see a list of outgoing file dependencies between the selected packages. Clicking a file name pops up a window with the source code viewer we discussed many times in previous chapters.
The list is split in two sections. At the top of each section, Sonar shows the name of the connected package. Each row represents a file coupling and it can be easily read. Clicking a file name pops up a window with the now-familiar file detail view.
You've seen that double-clicking on a cell displays the list of individual couplings. Well, DSM supports Sonar's most favorite feature. Double-click on any row and you will drill down to the next level. Figure 8 is a screenshot showing file dependencies of a specific file.
Figure 8 Double-clicking on a row drilldowns the DSM to the next navigation level.
Figure 8 doesn't show you any file-level dependency cycles, but they are possible, and they would show up here in a case where two files directly depend on each other. All the other stuff we've covered about colors and highlighting still applies in a file level as well. There is, however, a slight difference in double-click behavior. Double-clicking on a row here will pop up a new window showing the source code viewer instead of drilling down—because there's no "down" left to drill into—and double-clicking on a numbered cell will just show the names of the connected files instead of showing a list of associated files.
Measuring design and architecture quality can be a difficult concept to get your head around. But by exploring all those Sonar's features you can feel relaxed. Let Sonar take care of these metrics. All you have to do is to get some reports and take action, if needed.
In this article, you learned that the Dependency Structure Matrix (DSM) is a valuable tool to recognize cycles in your projects and dependencies between software components.
Here are some other Manning titles you might be interested in:
The Art of Unit Testing, Second Edition
Unit Testing in Java