Changes to the Sonargraph Dashboard

The Sonargraph dashboard was designed to give the user a quick overview about several important aspects of software quality. The most important aspects in our opinion are “Architecture” and “Structure”, which are displayed at the top of the dashboard. After some internal discussions we decided that we could improve the metrics in the “Structure” box. Those changes will be rolled out with Sonargraph version 15.2.0, which is expected to be released this week.

The metric “Entangled code (%)” up to now included component cycles (for most languages components are a synonym for source files) and package/namespace cycles. The later are quite language specific. Each language had to decide which second form of entanglement had to flow into the metric. For Java that would be packages, for TypeScript it would be directory cycles. Considering that usually a good part of package/namespace cycles are just caused by code placed in the wrong package/namespace we decided that it would be better to only use cyclic dependencies based on “real” cycles. A component cycle is a real cycle. A package cycle not based on a “real” cycle can be resolved by just moving components between packages/namespaces.

We recently (June 2025) also added the capability to detect cycles between top level logical elements (e.g. types, routines…). In Java these cycles are usually the same ones detected by the component cycle analyzer. In a language like C# where there is no mandatory relationship between namespaces and directory structure and classes and source files, it is much more likely to find cycles between top level elements that are not detected by the component cycle analyzer, since this one only looks for cyclic dependencies between source files. The detection of those cycles is optional and has to be activated by the user in the system settings. But they are also to be considered “real” cycles. If they are a duplicate of an existing component cycle, this is shown in the cycle groups view. So if the user activated the detection of top level type cycles, the cycle groups detected by this analyzer will contribute to the metric “Entangled code (%)” if the cycle group is not a duplicate of a component cycle.

For most projects this modified definition will lead to significantly lower values. We think the lower value projects a more precise picture, because only code involved in “real” cycles is counted. This also affects the two values below: “Critically entangled code” and “Entangled code”. Here we now count the lines of code of all source files involved in “real” cycles. The “Critical” part refers to cycle groups, that have more than a certain number of elements that can be configured by the user. The default value here is 6, meaning that every cycle group with 6 elements or more is considered critical. The second number is the total number of lines of code for all source files engaged in “real” cycles.

This screenshot shows the changed values for the same project:

As you can see the value for “Entangled code (%)” dropped quite dramatically, from almost 79% to a bit more than 16%. But we consider this number to be a better indicator of the situation. Now you know that about 16% of this code base is involved in “real” cycles. All other cycles on the package/namespace or directory level can be solved by just re-arranging code.

We also changed the definition of “Relative Entanglement (%)”. This metric is based on the metric “Relative Cyclicity”. Relative cyclicity is calculated by first adding up the cyclicity of all cycles groups in a given scope (system or module – in Sonargraph terms a system can contain many modules, at least one). The cyclicity of a cycle group is the square number of the number of elements in the group. For example the cyclicity of a cycle group with 4 elements is 16.

This leads us to the formula for relative cyclicity:

Lets try that formula with a hypothetical example. Lets assume we have a system with 50 source files, all of which are involved in one big cycle group of 50 elements. In that case “sumOfCyclicity” would be 2.500 (50 * 50). The square root gives a value of 50, which will then be divided through the total number of elements in that system, in our case 50. So relative cyclicity would be 100%, the worst possible value.

Now lets assume a similar system with 50 source files, but instead of one big cycle of 50 elements we have 25 cycles of 2 elements. In that case the “sumOfCyclicity” would be 100 (25 * 4). In that case the formula would evaluate to 20%.

Now we can see the usefulness of that metric. Even though all source files in both examples are involved in cyclic dependencies, the second value is much better caused by the fact that you could cut the second system into 25 individual parts, while the first system cannot be sub-divided since everything is in one big cycle.

Before we just used the average of the relative cyclicity for components and the relative cyclicity for packages/namespaces (or directories for languages without namespaces). This was a bit problematic. For example, a C++ project that would not use namespaces would get better values than a C++ project that used namespaces and had cycles between them. The project not using namespaces could still have problematic cycles between source directories and that would not show up in the metric. Also, in Java we were using the relative cyclicity of package cycles on the system level. We had a Java project with about 100 modules. The relation between the modules was cycle free, as is the case for most projects. However, it had distributed packages, i.e. the same package was used in more than one module. This means that those distributed packages were merged first before creating a system wide package dependency graph. That lead to an incredible big “virtual” cycle group with almost 600 packages spanning most of the system. You can imagine, that this caused quite a bad value for the entanglement metric. In reality the biggest cycle group within the scope of modules had 79 members. Therefore we went back to the white board and designed an improved version of the metric.

With the old definition of relative entanglement our example system had a value of almost 33%. Now it is below 15%. That again is a better reflection of the real state of this system. There is no cycle group with more than 80 elements and propagation cost has a reasonable value. It still is far from perfect and you can see the seedlings for a real big ball of mud in there.

The new definition works as follows: first we calculate the relative cyclicity for components and top level elements (if the analyzer is activated) and take the average value of the values. Then we calculate the weighted average of relative cyclicity for packages/namespaces on the module level (if available in the language and there are at least two packages/namespaces) and the weighted average of relative cyclicity for source directories (if available in the language and there are at least two source directories) and then take the average of those two values. The first value is considering real cycles, while the second one can also be based on cycles, that can be solved by just re-arranging code. Then we average the two value giving a weight of 60% to the real cycles and 40% to all other cycles.

The advantage of the modified definition is that it considers all potential kinds of cyclic dependencies. Growing cycles will make the value worse, while untangling cyclic dependencies will improve the value. This makes this metric an ideal indicator for measuring how far your system has evolved into a big ball of mud. In other words we recommend to use this metric for project governance for all of your projects. Try to keep relative entanglement below 5%. The higher the value the more problems you will have in the future.

Now lets look at a real big ball of mud (Apache Cassandra):

As you can see both bars are almost completely red. While the new values are slightly lower than the old versions of the structure metrics they are a good reflection of the state of the Cassandra code base. the biggest component cycle (a real cycle) contains 2,013 elements of a total of 2,616 components (Java files). That means 80% of all components form a single very large cycle. I think it is fair to assume, that if the developers had monitored this metric during the development process it would have led to a better outcome.

If you want to activate the cycle analysis for top-level elements you have to go to the system configuration dialog (System/Configure).

Here you can also define the threshold, from which on cycles are considered to be critical.

If you have questions or feedback, either contact us or leave a comment below.

Leave a Reply

Your email address will not be published. Required fields are marked *