Reducing your Cyclomatic Complexity in C#

Do you have a sawtooth if..then..else from hell? Today, I explain how to lower your cyclomatic complexity in your application.

Written by Jonathan "JD" Danylko • Last Updated: • Develop •
Albert Einstein Chalkboard with E=MC2

We've all been there before.

You come up with an idea for an RPG and you start writing code feverishly on a late night. After drinking a couple Red Bulls (or Bourbons), you crash on your bed from the adrenaline rush and exhaustion.

In the morning, you return to your code to experience the following:

public class GildedRose
{
    IList<Item> Items;

    public GildedRose(IList<Item> Items)     {         this.Items = Items;     }

    public void UpdateQuality()     {         for (var i = 0; i < Items.Count; i++)         {             if (Items[i].Name != "Aged Brie" && Items[i].Name != "Backstage passes to a TAFKAL80ETC concert")             {                 if (Items[i].Quality > 0)                 {                     if (Items[i].Name != "Sulfuras, Hand of Ragnaros")                     {                         Items[i].Quality = Items[i].Quality - 1;                     }                 }             }             else             {                 if (Items[i].Quality < 50)                 {                     Items[i].Quality = Items[i].Quality + 1;
                    if (Items[i].Name == "Backstage passes to a TAFKAL80ETC concert")                     {                         if (Items[i].SellIn < 11)                         {                             if (Items[i].Quality < 50)                             {                                 Items[i].Quality = Items[i].Quality + 1;                             }                         }
                        if (Items[i].SellIn < 6)                         {                             if (Items[i].Quality < 50)                             {                                 Items[i].Quality = Items[i].Quality + 1;                             }                         }                     }                 }             }
            if (Items[i].Name != "Sulfuras, Hand of Ragnaros")             {                 Items[i].SellIn = Items[i].SellIn - 1;             }
            if (Items[i].SellIn < 0)             {                 if (Items[i].Name != "Aged Brie")                 {                     if (Items[i].Name != "Backstage passes to a TAFKAL80ETC concert")                     {                         if (Items[i].Quality > 0)                         {                             if (Items[i].Name != "Sulfuras, Hand of Ragnaros")                             {                                 Items[i].Quality = Items[i].Quality - 1;                             }                         }                     }                     else                     {                         Items[i].Quality = Items[i].Quality - Items[i].Quality;                     }                 }                 else                 {                     if (Items[i].Quality < 50)                     {                         Items[i].Quality = Items[i].Quality + 1;                     }                 }             }         }     } }

(For those who've been around, this code may look familiar, but don't give away any secrets quite yet. Shhhh...)

After looking it over, you realize your one-too-many Bourbons caused you to write this code.

What's even worse, your IDE is yelling at you because you have a cyclomatic complexity of 19 for the UpdateQuantity method.

Wow! OMG...a 19? What am I going to do? I don't know the first thing about...

...wait, what is cyclomatic complexity?

What IS Cyclomatic Complexity?

Cyclomatic Complexity is a software metric used to indicate the complexity of a program. It's a way to gauge the linearly independent paths within a section of code or method.

If you feel like you just had a glass of Bourbon and didn't understand what that meant, it's ok.

It basically means the following:

  • if you DON'T have a large number of conditionals or decision points (like IF statements) in your method, your cyclomatic complexity is 1. Simple; no calls to other methods; it's a linear process and you exit the method.
  • If you have one IF statement in your method, your cyclomatic complexity would be 2. One point for the true condition and one point for the false condition.
  • If you had a nested IF statement (one IF and another IF in the true section), you would have a cyclomatic complexity of 3.

The lower the cyclomatic complexity, the easier the program is to understand (of course, there are exceptions to the rule).

So, you can see why the cyclomatic complexity of the UpdateQuantity() would be crazy to debug.

(No, seriously...it's a CC of 19).

Screenshot of Gilded Rose Kata's UpdateQuantity method

Fixing Cyclomatic Complexity

While 19 is definitely a high number, blindly staring and blinking at it won't fix the issue (trust me, I've tried that approach and it doesn't work).

So what can we do to fix it?

Smaller Methods

As Martin Fowler said in his Refactoring, 2nd Edition, it's better to have smaller methods as opposed to larger methods where it's harder to track down the responsibility of each segment of code.

Take the code and start splitting out certain sections where the logical grouping of code makes more sense and methods are better named.

Your future self will thank you.

Fewer Conditionals

The less conditionals and decisions you have in your code, the lower your cyclomatic complexity. 

Plain and simple.

Object-Oriented Approach

Early in my career, one of my friends said to me,

If you were to create a truly object-oriented application, it would have no if..then statements in the code.

The idea behind this approach is to create classes encapsulating the logic inside the classes.

I mentioned this briefly in my Programming Myths About Coding.

Using tools

As you can guess, there are a number of tools to assist with cyclomatic complexity while writing code.

The one I used in the image above was an extension for Resharper (yes, an extension for an extension) called Cyclomatic Complexity.

Continue to Learn

You always want to continue learning how to reduce cyclomatic complexity.

And that means writing more code.

If you write more code, you'll start identifying certain patterns to refactor into more maintainable code. Once you solve this particular if..then sawtooth piece of code, you'll know how to solve it later.

Always Improve Your Programming Skills.

Conclusion

Ok, Ok, I'll tell you about this GildedRose class.

The code above is a Code Kata meant to teach you about refactoring code into something a little more maintainable. You can find a lot of different katas I've collected over the years in a post entitled Improve Your Programming Skills (yes, the link from above).

These links give you programming scenarios and give you a chance to practice your coding skills.

Cyclomatic complexity with high numbers is always hard to follow. Anything higher than a 15 will melt your brain.

Don't be a brain-melter!

How do you manage cyclomatic complexity? Which tool do you use? Why even worry about it...if it was hard to write, it should be hard to read! Post your comments below and let's discuss.

Did you like this content? Show your support by buying me a coffee.

Buy me a coffee  Buy me a coffee
Picture of Jonathan "JD" Danylko

Jonathan Danylko is a web architect and entrepreneur who's been programming for over 25 years. He's developed websites for small, medium, and Fortune 500 companies since 1996.

He currently works at Insight Enterprises as an Principal Software Engineer Architect.

When asked what he likes to do in his spare time, he replies, "I like to write and I like to code. I also like to write about code."

comments powered by Disqus