When I started to program in C# I remember I had to enable an option in Visual Studio that analyses C# code and suggests changes in the code to improve readability and make the code less complex, one of those options was called Cyclomatic Complexity.
Is this article I suggest three tips to help you reduce that “thing” in your C# code.
Before you start coding, and to enable the option in Visual Studio to analyze Cyclomatic Complexity, let’s first talk about some important facts in Real World Programming.
Most programmers do not analyze source code searching for improvements and optimizations. Everybody knows that but no one cares.
There are tools out there to analyze your source code, most of them are paid, and all of them suggest a lot of code changes to improve and reduce Cyclomatic Complexity, but what exactly is that by the way?
Cyclomatic Complexity is a metric created by Thomas J. McCabe in 1976 to measure source code to check how complex it is.
That metric goes from 1 to N, it means that there are no limits. Low values are better, so for greater values be careful, your code can be complex and difficult to maintain.
The White Box Testing Blog suggests acceptable metrics for Cyclomatic Complexity,
- 1-10 - simple, not much risk
- 11-20 - complex, low risk
- 21-50 - too complex, medium risk, attention
- More than 50 - too complex, can't test , high risk
The calculate rule for that metric is kind of complex, and if you want more details on how CC is calculated, please check Wikipedia. I will just focus on how to reduce the values of CC in your code.
Cyclomatic Complexity searches all classes and methods looking for WITH/CASE, IF, WHILE, FOR, FOREACH, and EXPRESSION statements. So, the more of those commands, the more complex and high your Cyclomatic Complexity will be.
Back to the real world, open one of your projects in Visual Studio and go to the Analyze menu, then click Calculate Code Metrics and For Solution. Visual Studio will start to analyze your source code and will show a screen like this:
I have used source code from my article “The Magic of Model Binder in MVC and Web API” as an example to test and reduce our Cyclomatic Complexity values.
Visual Studio shows all Cyclomatic Complexity values summarized by namespaces, then you need to open each node until it reaches a method, then compare the CC value to the Cyclomatic Complexity Table above.
Now you know how to run the Code Metric Analysis in Visual Studio, let’s see somes tips to reduce Cyclomatic Complexity:
Tip #1 – SWITCH/CASE
Avoid use of switch/case statements in your code. Use Factory or Strategy design patterns instead.
Original code
Complexity of 8 (1 for each CASE and 1 for method itself).
- public void MethodDay(DayOfWeek day)
- {
-
- switch (day)
- {
- case DayOfWeek.Monday:
- Console.WriteLine("Today is Monday!");
- break;
- case DayOfWeek.Tuesday:
- Console.WriteLine("Today is Tuesday!");
- break;
- case DayOfWeek.Wednesday:
- Console.WriteLine("Today is Wednesday!");
- break;
- case DayOfWeek.Thursday:
- Console.WriteLine("Today is Thursday!");
- break;
- case DayOfWeek.Friday:
- Console.WriteLine("Today is Friday!");
- break;
- case DayOfWeek.Saturday:
- Console.WriteLine("Today is Saturday!");
- break;
- case DayOfWeek.Sunday:
- Console.WriteLine("Today is Sunday!");
- break;
- }
- }
Refactoring using Factory design pattern and complexity changed to 1.
- public void MethodDayReduce(DayOfWeek day)
- {
- var factory = Activator.CreateInstance(Type.GetType($"{day.ToString()}DayFactory")) as IDayFactory;
- factory.Write();
- }
-
- public interface IDayFactory
- {
- void Write();
- }
-
- public class MondayDayFactory : IDayFactory
- {
- public void Write()
- {
- Console.WriteLine("Today is Monday!");
- }
- }
Tip #2 – IF Expressions
Reduce IF expressions in your code. Use the Single Responsibility principle for extracting a piece of code to other methods and make the method for just one responsibility. That change will reduce Cyclomatic Responsibility and improve maintainability for your code.
Original code
Complexity of 4 (1 for each expression and 1 for method itself).
- public void Method(bool condition1, bool condition2)
- {
- if (condition1 || condition2 && (!condition1))
- {
- Console.WriteLine("Hello World!");
- }
- }
Refactoring to complexity of 2,
- public void MethodReduce(bool condition1, bool condition2)
- {
- var negative = (!condition1);
- condition2 = condition2 && negative;
- condition2 = condition2 || condition1;
- if (condition2)
- {
- Console.WriteLine("Hello World!");
- }
- }
Tip #3 – BE COOL
Don't kill yourself because of Cyclomatic Complexity.
It’s better to keep your code simple and follow single responsibility principles than refactoring all your code making it hard to understand.
“Any fool can write code that a computer can understand. Good programmers write code that humans can understand.” Martin Fowler.
Adopt an acceptable metric of CC for your business and your daily life. This article is a guide for you, not a rule.
And about performance?
Can Cyclomatic Complexity affect the performance of an application? The answer is Yes and No. It will affect performance if the complexity value is more than 50 and still depends on the kind of commands you are using. You will need to run a performance benchmark in your code to check that.
I would say to you: Relax!
So, do you I need to reduce Cyclomatic Complexity?
Of course! Who likes to read a source code with a lot of chaining IF and SWITCH/CASE statements? Applying Cyclomatic Complexity reduces the use of those commands, helps maintainability and still you use design patterns! Isn’t that cool?
After reading this article, you should have no issues writing better code, right?
Thank you and good luck!