Reducing your Cyclomatic Complexity in C#

April 3rd, 2019

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

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:

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).

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.