How to lower cyclomatic complexity?
January 7, 2018 ยท View on GitHub
This article describes how to lower cyclomatic complexity.
Example: test function
This is a simple example, in which a test function is too long:
void test()
{
assert(do_main( { "main" } ) == 1);
assert(do_main( { "main", "too", "many" } ) == 1);
assert(do_main( { "main", "0" } ) == 1);
assert(do_main( { "main", "1" } ) == 0);
assert(do_main( { "main", "7" } ) == 1);
assert(int_to_word(1) == "one");
assert(int_to_word(2) == "two");
assert(int_to_word(3) == "three");
assert(int_to_word(4) == "four");
assert(int_to_word(5) == "five");
assert(int_to_word(6) == "six");
}
Too bad, cyclomatic complexity is too high. Sure, a human can easily read it, but in this course, the tools tell us what is correct.
To simplify test, spread the tests over two functions:
void test_do_main()
{
assert(do_main( { "main" } ) == 1);
assert(do_main( { "main", "too", "many" } ) == 1);
assert(do_main( { "main", "0" } ) == 1);
assert(do_main( { "main", "1" } ) == 0);
assert(do_main( { "main", "7" } ) == 1);
}
void test_int_to_word()
{
assert(int_to_word(1) == "one");
assert(int_to_word(2) == "two");
assert(int_to_word(3) == "three");
assert(int_to_word(4) == "four");
assert(int_to_word(5) == "five");
assert(int_to_word(6) == "six");
}
void test()
{
test_do_main();
test_int_to_word();
}
Example: extract a function
Good comments describe what happens in the code at a higher level. If a group of statements belong together, these can be grouped in a function.
For example:
void f()
{
std::vector<int> v;
// [many things happen to v]
// Get the sum of all values in v
int total{0};
for (const int i: v) { total += i; }
// ['total' is only read]
}
This can easily be rewritten to:
int sum(const std::vector<int>& v)
{
int total{0};
for (const int i: v) { total += i; }
return total;
}
void f()
{
std::vector<int> v;
// [many things happen to v]
const int total{sum(v)};
// ['total' is only read]
}
Notice that total becomes a const value, as it should. Just striving for const-correctness helps you
find opportunities to simplify your code.
More experienced programmers do not write such a sum function, as they know the STL algorithms and use std::accumulate:
void f()
{
std::vector<int> v;
// [many things happen to v]
const int total{std::accumulate(std::begin(v), std::end(v), 0)};
// ['total' is only read]
}