Cyclometric Complexity and defects

When we say a program is complex, what exactly do we mean by complex? In future posts I'm going to keep returning to this issue, but today I'm going to deal with one type of complexity: cyclometric complexity.

The cyclometric complexity of a routine is the number of independent code-paths through the procedure. Examine the following Python routine:

	def f(x):
		if x==0:
			print "Zero"
		if x>0:
			print "Greater than Zero"
		if x<0:
			print "Less than zero"
	

Assuming that we pass in an integer to this routine, there are three distinct code paths. One for when x is zero, one for when x is greater than zero and one for when x is less than zero. The cyclometric complexity of this routine is therefore three. The larger the cyclometric complexity of a routine the more complex it is.

You can then add up the total cyclometric complexity over all the routines in a program to get a feel for the complexity of the entire program. For even the smallest of programs the cyclometric complexity is likely to be in well in to the thousands. In large projects, it will probably run in to tens of a millions.

This seems to tie in nicely of what our intuition tells us complexity should be. The more decision points your program has the more complex your piece of software is.

Does lowering cyclometric complexity reduce defects?

We know that complexity is the source of bugs. A natural question to ask is whether working to reduce the cyclometric complexity of a program also reduces the defect count in that program?

In Steve McConell's pivotal book, Code Complete, he has this to say about Cyclometric complexity and defects:

Control-flow complexity is important because it has been correlated with low reliability and frequent errors (McCabe 1976, Shen et al. 1985). William T. Ward reported a significant gain in software reliability resulting from using McCabe's complexity metric at Hewlett Packard (1986b). McCabe's metric was used on one 77,000-line program to identify problem areas. The program had a post-release defect rate of 0.31 defects per thousand lines of code. A 127,000 line program had a post-release defect rate of 0.02 defects per thousand lines of code. Ward reported that because of their lower complexity, both programs had substantially fewer defects than other programs at Hewlett-Packard. My own company, Construx Software has experienced similar results using complexity measures to identify problematic routines in the 2000s."

I think the verdict here is pretty resounding. Lowering the over-all cyclometric complexity of a program is going to reduce bugs considerably.

How do I go about lowering complexity?

The number of decision paths in your typical program is going to be huge. But reducing overall decision complexity can be achieved by aggressively adopting the following principles:

The primary message is that lowering complexity is about writing less code. The less code you write the less decision points there are. At every opportunity you should try to write less code.

How can I identify problematic routines?

There are a number of tools in a variety of languages that allow you to flag routines that have a high cylcometric complexity. The rule of thumb is to rewrite any routine where you have a cyclometric complexity of greater than ten.

You can use the following tools in your organisation to measure the cyclometric complexity of your routines:

2008-03-31 22:22:55 GMT | #Programming | Permalink
XML View Previous Posts