Detect and Break “Spaghetti” Code With These 5 Useful Metrics
Have you ever been baffled by illegible and convoluted code? In this article, we want to give you some handy tips on how to deal with and maintain ‘Spaghetti,’ or overly complex and illegible code.
Join the DZone community and get the full member experience.Join For Free
What Is “Spaghetti” Code?
Spaghetti code refers to code that is difficult to read and maintain. This code has the following characteristics:
- an important nesting or dispersion of the logic (trade).
- a complex control structure.
- complex logic checks.
- a potentially abundant presence of comments.
- code that does several things at once (Single Responsibility Principle Violation).
Fortunately, it can be easy to identify this type of code with a good tool.
5 Useful Metrics to Detect "Spaghetti" Code
Here are the 5 useful metrics we recommend detecting “Spaghetti" code
1. Code Coverage Rate
Code coverage is an excellent way to identify “Spaghetti” code. Convoluted code will probably fare poorly on this metric, since it requires tremendous effort to execute on the part of the developer.
Reporting Code Coverage Using Maven and JaCoCo Plugin
The measurement of code coverage is a metric to inform the developer about the completeness of these tests.
There are four levels for assessing whether code is well-tested:
- coverage by lines of code.
- coverage of execution paths.
- coverage of predicates.
- data coverage.
The effort to cover the four levels is cumulative: to cover all the paths, you cover all the lines.
No matter what your tool uses as an indicator of code coverage, spaghetti code is statistically poorly covered, because the difficulty to cover it increases with complexity.
Takeaway: Look for poorly covered code.
2. Code Complexity
Cyclomatic Complexity, NPath—there are many metrics. What's important is to understand what they measure and, specifically, how to improve results.
Code complexity with Embold
Cyclomatic Complexity (abbreviated CC) evaluates the potential number of paths to compute. It is often simplified by 1 + the number of control flow branches. Each path is a test case. Some classes like in the previous figure require more than 300 test cases to assess the functionalities. And if statement counts for 2, a loop for 2, a switch for n cases.
The NPath complexity evaluates the complexity taking into account both paths (like sCC) and the combinatorics linked to the path imbrication. The more a code is nested, the higher its complexity (exponential).
The more complex the code is, the greater the effort to test it. Testability and maintainability go hand in hand.
Takeaway: Look for the most complex code in your application.
3 . Coupling Between Objects (CBO)
Coupling is the notion of dependence between two objects (or classes) that creates a strong relationship. If one class is modified, there is a strong chance of creating a regression in the other.
Complex code becomes conspicuous either by using many resources of the application or by being critical and used by everyone.
The CBO metric evaluates the level of dependency between this class and the rest of the application.
A strongly coupled, potentially complex class is most likely spaghetti code that is difficult to isolate and extract from the application.
A huge (in terms of lines) and highly dependent class in your application is often referred to as a God Class:
4. Number of LOC in the Method
Large classes, large methods require large effort to understand.
On the basis of this observation, it is important to quickly identify methods that are too voluminous and require time to understand. The ones which probably violate the SRP principle are potentially problematic.
Component Risk in Embold
Takeaway: Look for the largest ones and go down the hierarchy.
5. Response for Class (RFC)
Convoluted code as opposed to pure function has many side effects. The code manipulates many objects and causes state changes in several classes and systems around it.
Potential side effects can be evaluated via the RFC metric.
The RFC metric counts the number of potentially executed methods within a code to determine its complexity. Code that invokes many other methods (ideally other classes) is fragile and potentially difficult to understand or test.
Dependency Analysis in Embold
We recommend the open source project OpenKM as a source of understanding while learning metrics. It contains plenty of Java code from different ages and quality.
To learn how to deal with "Spaghetti" code, pick a tool with the described metrics and dependency analysis capabilities.
Let us know if this was useful in the comments!
Opinions expressed by DZone contributors are their own.