views:

1259

answers:

15

I've been playing around with measuring the cyclomatic complexity of a big code base.

Cyclomatic complexity is the number of linearly independent paths through a program's source code and there are lots of free tools for your language of choice.

The results are interesting but not surprising. That is, the parts I know to be the hairiest were in fact the most complex (with a rating of > 50). But what I am finding useful is that a concrete "badness" number is assigned to each method as something I can point to when deciding where to start refactoring.

Do you use cyclomatic complexity? What's the most complex bit of code you found?

+5  A: 

We recently started to use it. We use NDepend to do some static code analysis, and it measures cyclomatic complexity. I agree, it's a decent way to identify methods for refactoring.

Sadly, we have seen #'s above 200 for some methods created by our developers offshore.

Nebakanezer
In an earlier life, I remember having seen more than 300.
Daniel Daranas
Tonight we dine in hell!
Aidan
A colleague of mine has encountered cases of over a 1000.
reinierpost
+1  A: 

I haven't used it in a while, but on a previous project it really helped identify potential trouble spots in someone elses code (wouldn't be mine of course!)

Upon finding the area's to check out, i quickly found numerious problems (also lots of GOTOS would you believe!) with logic and some really strange WTF code.

Cyclomatic complexity is great for showing areas which probably are doing to much and therefore breaking the single responsibilty prinicpal. These's ideally should be broken up into mulitple functions

Harry
+11  A: 

We refactor mercilessly, and use Cyclomatic complexity as one of the metrics that gets code on our 'hit list'. 1-6 we don't flag for complexity (although it could get questioned for other reasons), 7-9 is questionable, and any method over 10 is assumed to be bad unless proven otherwise.

The worst we've seen was 87 from a monstrous if-else-if chain in some legacy code we had to take over.

kenj0418
87? That's a very thorough implementation of the Arrow Anti-Pattern... Sincere condolences.
Michael Stum
A: 

I'm afraid that for the language of the project for which I would most like metrics like this, LPC, there are not, in fact, lots of free tools for producing it available. So no, not so useful to me.

chaos
Chaos shouts: watch out for LAG! I'm running metrics...
erickson
Heh. Somebody knows the story.
chaos
+4  A: 

Until there is a tool that can work well with C++ templates, and meta-programming techniques, it's not much help in my situation. Anyways just remember that

"not all things that count can be measured, and not all things that can be measured count" Einstein

So remember to pass any information of this type through human filtering too.

Robert Gould
+1  A: 

There's a Java metric called CRAP4J that empirically combines cyclomatic complexity and JUnit test coverage to come up with a single metric. He's been doing research to try and improve his empirical formula. I'm not sure how widespread it is.

duffymo
+2  A: 

It's useful to me in the same way that big-O is useful: I know what it is, and can use it to get a gut feeling for whether a method is good or bad, but I don't need to compute it for every function I've written.

I think simpler metrics, like LOC, are at least as good in most cases. If a function doesn't fit on one screen, it almost doesn't matter how simple it is. If a function takes 20 parameters and makes 40 local variables, it doesn't matter if its cyclomatic complexity is 1.

Ken
+1  A: 

I frequently measure the cyclomatic complexity of my code. I've found it helps me spot areas of code that are doing too much. Having a tool point out the hot-spots in my code is much less time consuming than having to read through thousands of lines of code trying to figure out which methods are not following the SRP.

However, I've found that when I do a cyclomatic complexity analysis on other people's code it usually leads to feelings of frustration, angst, and general anger when I find code with cyclomatic complexity in the 100's. What compels people to write methods that have several thousand lines of code in them?!

mezoid
I've seen some of those huge methods you're talking about, and it's usually about putting out fires. Once a fire is out, there's no reason to refactor (it works damnit!) and now that chunk of code is that much bigger, and has another fire in a few weeks/months.
wowest
+4  A: 

You'll know complexity when you see it. The main thing this kind of tool is useful for is flagging the parts of the code that were escaping your attention.

David Plumpton
It's also useful if you do *not* know the code.
reinierpost
+2  A: 

It's great for help identifying candidates for refactoring, but it's important to keep your judgment around. I'd support kenj0418's ranges for pruning guides.

wowest
A: 

+1 for kenj0418's hit list values.

The worst I've seen was a 275. There were a couple others over 200 that we were able to refactor down to much smaller CCs; they were still high but it got them pushed further back in line. We didn't have much luck with the 275 beast -- it was (probably still is) a web of if- and switch-statements that was just way too complex. It's only real value is as a step-through when they decide to rebuild the system.

The exceptions to high CC that I was comfortable with were factories; IMO, they are supposed to have a high CC but only if they are only doing simple object creation and returning.

Austin Salonen
A: 

After understanding what it means, I now have started to use it on a "trial" basis. So far I have found it to be useful, because usually high CC goes hand in hand with the Arrow Anti-Pattern, which makes code harder to read and understand. I do not have a fixed number yet, but NDepend is alerting for everything above 5, which looks like a good start to investigate methods.

Michael Stum
+2  A: 

Actually, cyclomatic complexity can be put to use beyond just method level thresholds. For starters, one big method with high complexity may be broken into several small methods with lower complexity. But has it really improved the codebase? Granted, you may get somewhat better readability by all those method names. But the total conditional logic hasn't changed. And the total conditional logic can often be reduced by replacing conditionals with polymorphism.

We need a metric that doesn't turn green by mere method decomposition. I call this CC100.

CC100 = 100 * (Total cyclomatic complexity of codebase) / (Total lines of code)

bagheera
But testability has improved: separate methods can (in principle) be tested separately, even if the logic doesn't change. Of course this doesn't hold if the methods also depend on a lot of global state, but that's a problem in its own right.
reinierpost
+1 for the hyperlink to an interesting slide show. I recently spent some thoughts on exactly this issue and am happy to find more material on it.
stakx
A: 

Yes, we use it and I have found it useful too. We have a big legacy code base to tame and we found alaraming high cyclomatic complexity. (387 in one method!). CC points you directly to areas that are worth to refactor. We use CCCC on C++ code.

chrmue
A: 

Cyclomatic Complexity is just one composant of what could be called Fabricated Complexity. A while back, I wrote an article to summarize several dimensions of code complexity: Fighting Fabricated Complexity

Tooling is needed to be efficient at handling code complexity. The tool NDepend for .NET code will let you analyze many dimensions of the code complexity including code metrics like: Cyclomatic Complexity, Nesting Depth, Lack Of Cohesion of Methods, Coverage by Tests...

including dependencies analysis and including a language (Code Query Language) dedicated to ask, what is complex in my code, and to write rule?

Patrick Smacchia - NDepend dev