What is Cyclomatic Complexity?
The cyclomatic complexity of a section of code is the quantitative measurement of the number of linearly independent paths that are in it. This software metric is used for the purpose of indicating the complexity of a program.
The metric was developed by Thomas McCabe to determine the stability and level of confidence in a program. Essentially, programs that have a lower cyclomatic complexity tend to be easier to understand and less risky to modify.
The cyclomatic complexity can be computed by making use of the Control Flow Graph of the program. The nodes in the graph represent the smallest group of commands of a program, and a directed edge in it connects the two nodes i.e. if second command might immediately follow the first command.
As an example, if the source code does not contain a control flow statement then its cyclomatic complexity is 1 and the source code contains a single path in it. In a similar manner, in case the source code contains one if condition then cyclomatic complexity will be 2 since there will be two paths, one will be for true and the other will be for false.
Why is cyclomatic complexity important?
Basically, cyclomatic complexity is important because it can help you understand how complex your code is. Looking at the numbers given per method in the source code, you can figure out whether your code is particularly complex or not. This metric even affects other software metrics such as the code maintainability index.
How do you measure the complexity of code?
Some of the metrics that can be used to measure the complexity of code include:
- Lines of code or verbosity
- Number of dependencies
- Test coverage
- Ease of testing
- Ease of reading
- Usage of common patterns or language features
- Good variable naming
- Amount of duplication
It isn’t easy to measure the complexity of code and different developers will assign different levels of importance to each of these metrics and factors.
What is the formula of cyclomatic complexity?
Mathematically, for a structured program, the directed graph inside control flow is the edge that joins two basic blocks of the program as control might pass from the first to the second.
So, this is what the formula for cyclomatic complexity (M) would look like:
M = E – N + 2P
E = the no. of edges in the control flow graph
N = the no. of nodes in the control flow graph
P = the no. of connected components
Here are the steps that you should follow when you are calculating cyclomatic complexity and test cases design:
- Construct a graph with nodes and edges from code.
- Identify the independent paths.
- Calculate the cyclomatic complexity
- Design the test cases
How can you reduce the cyclomatic complexity?
Here are some of ways through which you can reduce cyclomatic complexity:
Validating and removing unwanted ‘if’ statements
More conditional statements lead to more code complexities. You could validate and check which ‘if’ statements can be removed in order to reduce your code complexity.
Refactoring bigger methods into smaller methods can be very helpful in reducing code complexity. You can use the single responsibility principle to break bigger classes into smaller one, thereby reducing the dependency on a single class performing multiple functions.
Getting rid of redundant or unnecessary ‘else’ conditions
In case the if.Else block is performing some logic or returning something based on some condition, it would be better to just have a single ‘if’ statement. The ‘else’ in this statement would be redundant.
Quite often, complexity is introduced into otherwise simple code because of the presence of conditional statements. But if those conditional statements are rewritten with simple LINQ conditions, you would be able to reduce the count.
Is cyclomatic complexity a good metric?
The cyclomatic complexity does have it’s own uses and advantages, but it also has some disadvantages. Let’s understand all of these.
The uses of cyclomatic complexity
Here are some of the purposes for which cyclomatic complexity is utilized:
- Figuring out the independent path executions thus proven to be very helpful for developers and testers.
- Ensuring that every path has been tested at least once.
- Focusing more on uncovered paths.
- Improving your code coverage.
- Evaluating the risks associated with the program.
- Reducing risks if the metric is used earlier in the program.
The advantages of cyclomatic complexity
- It is possible to use cyclomatic complexity as a quality metric. It shows you the relative complexity of several different designs.
- The cyclomatic complexity can be calculated and computed much faster than Halstead’s metrics.
- You can use the cyclomatic complexity to measure the minimum effort and best areas of concentration for testing.
- The cyclomatic complexity can even guide your testing process.
- It is rather easy to apply this metric.
As we said earlier, this metric also has its disadvantages. Let’s see what those are:
The disadvantages of cyclomatic complexity
- The cyclomatic complexity is not a measure of the data complexity. It is simply a measure of the program’s control complexity.
- In this metric, nested conditional structures tend to be tougher to understand than non-nested structures.
- In case there are simple comparisons and decision structures, this metric might end up giving you an inaccurate, and thus misleading, figure.
In answer to the question about how good of a metric cyclomatic complexity is, let’s just say that it isn’t exactly a perfect way to measure how complex or good a piece of code is, but it still is an important metric that you should understand and keep in mind.