There are various factors that can contribute to the complexity of a type or a method pertaining to a type in your application's code. Cyclomatic complexity is a popular metric that is used to measure your program's complexity. In other words, it's a software metric that provides a quantitative measure of the complexity of a program.
In essence, Cyclomatic complexity is a measure of the linearly independent paths that are available through your program. Its value is actually dependent on the number of conditional branches or constructs in your code. So, cyclomatic complexity will be high for methods that have a large number of conditional constructs (i. e, switch/if/while/for/foreach statements).
The MSDN states: "Cyclomatic complexity measures the number of linearly independent paths through the method, which is determined by the number and complexity of conditional branches. A low cyclomatic complexity generally indicates a method that is easy to understand, test, and maintain."
Here's how cyclomatic complexity is calculated:
CC = E - N + 1
Where,
CC denotes cyclomatic complexity
E denotes the number of edges in the graph
N denotes the number of nodes in the graph
Note that a node represents the logical branch and an edge represents the connected line between the nodes. Incidentally, the lower the value of cyclomatic complexity of a method, the easier it is to test and maintain, hence the better. You can take advantage of cyclomatic complexity to calculate the complexity of methods, types and also modules in your application.
Since cyclomatic complexity indicates the linerly independent paths though the program, the more the value of cyclomatic complexity, the more the number of test cases you would need for your program -- the number of test cases you would need would typically be equivalent to the cyclomatic complexity in this case. If the value of cyclomatic complexity is less (a value less than or equal to 10 is considered awesome), the code is assumed to be well structured, highly testable and maintainable.
How do I check cyclomatic complexity?
The newer versions of Visual Studio provide support for calculating cyclomatic complexity using the Visual Studio IDE. You can calculate Code Metrics for the entire solution or for the projects you have selected. When you run it, the Code Metrics Results window will show you the code analysis results organized into Maintainability Index, Cyclomatic complexity, Depth of Inheritance, Class coupling and also the Lines of Code. In this post we will explore Cyclomatic Complexity and I will present a discussion on the other points in a later post here.
Now, refer to the code snippet given below.
private void DisplayMessage(string str)
{
Console.WriteLine(str);
}
When you calculate the cyclomatic complexity for the DisplayMessage method using Visual Studio, it shows the value as 1. Now, consider this method that contains a check to see if the parameter passed to the method as an argument is null or empty.
private void DisplayTextMessage(string str)
{
if(!string.IsNullOrEmpty(str))
Console.WriteLine(str);
}
If you run Code Metrics for the solution again, you would observe that the cyclomatic complexity for the DisplayTextMessage method is 2.
How do I reduce cyclomatic complexity in the code?
Though in some cases, it is difficult to adopt to a particular strategy to reduce the cyclomatic complexity in your code as the conditional constructs may be because it is inherent to your problem, you can adopt various strategies to achieve a lower cyclomatic complexity value. The two approaches that you should follow to mitigate high cyclomatic complexity is through unit tests and code refactoring. While unit tests will help you to minimize the risks, you should leverage code refactoring to make your code less complex, easier to test and maintain.
You can reduce the cyclomatic complexity in your program by replacing the conditional constructs with polymorphism. In using polymorphism, you can add a lot of flexibility to your code -- your code becomes more testable and you can add, edit or even remove conditions without much change in your code. In essence, the lesser the value of cyclomatic complexity, the more is your code easy to read, test and maintain. In some cases, I'd recommend that you take advantage of the behavioral design patterns like, the Strategy design pattern to reduce cyclomatic complexity in your code.