Tracking Cyclomatic Complexity
Cyclomatic complexity is a quantitative measure of how many independent paths exist in your source code. And it's something you should be tracking in your projects – because there are no correct software metrics, only ones that are sometimes useful.
if (condition1) {
if (condition2) {
for {
if (condition3) {
switch x {
case y:
if (condition4) {
What causes cyclomatic complexity? Control flow statements can create new code paths. Control flow statements can be choice statements: if/else
, switch/case
. They can also be loop statements: for/while
. Finally, they can reference other code through goto
or function calls. In a simple example, a program with no control flow statements has a cyclomatic complexity of 1 – there is only a single execution path. A program with a single if
statement has a cyclomatic complexity of 2 – the true
path and the false
path.
Higher cyclomatic complexity requires more test cases for coverage.
Too much cyclomatic complexity is considered harmful. That's along the same lines of what Dijkstra was getting at in his Go To Considered Harmful. Dijkstra was concerned about the difference between the divergence of the dynamic and the static representations of a program.
It means more test cases are needed to cover all the code paths. And more practically, more opportunities for bugs and difficult-to-follow code.
You'll most likely want to track it on a functional level. You can calculate it in your head with the formula E − N + 2, where using a control flow graph of the code, E is the number of edges, and N is the number of nodes. Most static analysis tools will calculate it for you. One example for Go is gocyclo.
What it won't solve: Cyclomatic complexity doesn't cover a whole class of software bugs. It isn't a silver bullet either. There are bound to be false positives – functions with high cyclomatic complexity that are less error-prone and more clear than those with lower complexity. It's a rough proxy for maintainability because of the number of test cases associated with cyclomatic complexity. On the other hand, it is also a rough proxy for lines of code, which we know to not be a useful metric.
McCabe's 1976 paper, A Complexity Measure.