CyclomaticComplexity
Since Checkstyle 3.2
Description
The complexity is equal to the number of decision points + 1
.
Decision points:
-
if
,while
,do
,for
,?:
,catch
,switch
,case
statements. -
Operators
&&
and||
in the body of target. -
when
expression in case labels, also known as guards.
By pure theory level 1-4 is considered easy to test, 5-7 OK, 8-10 consider re-factoring to ease testing, and 11+ re-factor now as testing will be painful.
When it comes to code quality measurement by this metric level 10 is very good level as a ultimate target (that is hard to archive). Do not be ashamed to have complexity level 15 or even higher, but keep it below 20 to catch really bad-designed code automatically.
Please use Suppression to avoid violations on cases that could not be split in few methods without damaging readability of code or encapsulation.
Properties
name | description | type | default value | since |
---|---|---|---|---|
max | Specify the maximum threshold allowed. | int | 10 |
3.2 |
switchBlockAsSingleDecisionPoint | Control whether to treat the whole switch block as a single decision point. | boolean | false |
6.11 |
tokens | tokens to check | subset of tokens LITERAL_WHILE , LITERAL_DO , LITERAL_FOR , LITERAL_IF , LITERAL_SWITCH , LITERAL_CASE , LITERAL_CATCH , QUESTION , LAND , LOR , LITERAL_WHEN . | LITERAL_WHILE , LITERAL_DO , LITERAL_FOR , LITERAL_IF , LITERAL_SWITCH , LITERAL_CASE , LITERAL_CATCH , QUESTION , LAND , LOR , LITERAL_WHEN . | 3.2 |
Examples
To configure the check:
<module name="Checker">
<module name="TreeWalker">
<module name="CyclomaticComplexity"/>
</module>
</module>
Example:
class Example1 {
int a, b, c, d, e, n;
public void testMethod1() {
while (a < b && a > c) {
fun1();
}
if (a == b) {
do {
fun1();
} while (d==a);
} else if (c == d) {
while (c > 0) {
fun1();
}
do {
fun1();
} while (a==d);
}
}
// violation below, 'Cyclomatic Complexity is 13 (max allowed is 10)'
public void testMethod2() { // 1, function declaration
if (a == b) { // 2, if
fun1();
} else if (a == 0 // 3, if
&& b == c) { // 4, && operator
if (c == -1) { // 5, if
fun1();
}
} else if (a == c // 6, if
|| a == d) { // 7, || operator
fun1();
} else if (d == e) { //8, if
try {
fun1();
} catch (Exception e) { // 9, catch
}
} else {
switch(n) {
case 1: // 10, case
fun1();
break;
case 2: // 11, case
fun1();
break;
case 3: // 12, case
fun1();
break;
default:
break;
}
}
a = a > 0 ? b : c; // 13, ternary operator
}
private void fun1() {}
}
To configure the check with a threshold of 4 and check only for while and do-while loops:
<module name="Checker">
<module name="TreeWalker">
<module name="CyclomaticComplexity">
<property name="max" value="4"/>
<property name="tokens" value="LITERAL_WHILE, LITERAL_DO"/>
</module>
</module>
</module>
Example:
class Example2 {
int a, b, c, d, e, n;
// violation below, 'Cyclomatic Complexity is 5 (max allowed is 4)'
public void testMethod1() { // 1, function declaration
while (a < b && a > c) { // 2, while
fun1();
}
if (a == b) {
do { // 3, do
fun1();
} while (d==a);
} else if (c == d) {
while (c > 0) { // 4, while
fun1();
}
do { // 5, do-while
fun1();
} while (a==d);
}
}
public void testMethod2() {
if (a == b) {
fun1();
} else if (a == 0
&& b == c) {
if (c == -1) {
fun1();
}
} else if (a == c
|| a == d) {
fun1();
} else if (d == e) {
try {
fun1();
} catch (Exception e) {
}
} else {
switch(n) {
case 1:
fun1();
break;
case 2:
fun1();
break;
case 3:
fun1();
break;
default:
break;
}
}
a = a > 0 ? b : c;
}
private void fun1() {}
}
To configure the check to consider switch-case block as one decision point.
<module name="Checker">
<module name="TreeWalker">
<module name="CyclomaticComplexity">
<property name="switchBlockAsSingleDecisionPoint" value="true"/>
</module>
</module>
</module>
Example:
class Example3 {
int a, b, c, d, e, n;
public void testMethod1() {
while (a < b && a > c) {
fun1();
}
if (a == b) {
do {
fun1();
} while (d==a);
} else if (c == d) {
while (c > 0) {
fun1();
}
do {
fun1();
} while (a==d);
}
}
// violation below, 'Cyclomatic Complexity is 11 (max allowed is 10)'
public void testMethod2() { // 1, function declaration
if (a == b) { // 2, if
fun1();
} else if (a == 0 // 3, if
&& b == c) { // 4, && operator
if (c == -1) { // 5, if
fun1();
}
} else if (a == c // 6, if
|| a == d) { // 7, || operator
fun1();
} else if (d == e) { // 8, if
try {
fun1();
} catch (Exception e) { // 9, catch
}
} else {
switch(n) { // 10, switch
case 1:
fun1();
break;
case 2:
fun1();
break;
case 3: // 10, case
fun1();
break;
default:
break;
}
}
a = a > 0 ? b : c; // 11, ternary operator
}
private void fun1() {}
}
Example of Usage
Violation Messages
All messages can be customized if the default message doesn't suit you. Please see the documentation to learn how to.
Package
com.puppycrawl.tools.checkstyle.checks.metrics