Вопрос

Thanks to a question over at Code Review I got into a little disagreement (which essentially is an opportunity to learn something) about what exactly the Cyclomatic Complexity is for the below code.

public static void main(String[] args) {
    try {
        thro();
        thro();
        thro();
        thro();
        thro();
        thro();
        thro();
    }
    catch (NullPointerException e) {
    }
}

private static Random random = new Random();

public static void thro() throws NullPointerException {
    if (random.nextBoolean())
        throw new NullPointerException();
    System.out.println("No crash this time");
}

When writing this code in Eclipse and using the Eclipse metrics plugin, it tells me that the McCabe Cyclomatic Complexity for the main method is 2, and for the thro method it says 2.

However, someone else tells me that the complexity of calling thro multiple times is number of calls * method complexity, and therefore claims that the complexity of the main method is 7 * 2 = 14.

Are we measuring different things? Can both of us be correct? Or what is the actual cyclomatic complexity here?

Это было полезно?

Решение

When I understood this correctly, the Cyclomatic Complexity of main is 8 - that is the number of linearly independent paths through the code. You either get an exception at one of the seven lines, or none, but never more than one. Each of that possible "exception points" corresponds exactly to one different path through the code.

I guess when McCabe invented that metric, he did not have programming languages with exception handling in mind.

Другие советы

Being 'the other guy', I'll answer here, and be precise about what I say (which I was not particularly precise with over on other formums).

Using the code example above, I calculate the cyclomatic complexity as 8, and I have comments in the code to show how I calculate that. To describe the paths I will consider a successful loop through all the thro() calls as the 'main' 'code path' (or 'CP=1'):

public static void main(String[] args) {
  try {
             // This is the 'main' Code Path: CP = 1
    thro();  // this has a branch, can succeed CP=1 or throw CP=2
    thro();  // this has a branch, can succeed CP=1 or throw CP=3
    thro();  // this has a branch, can succeed CP=1 or throw CP=4
    thro();  // this has a branch, can succeed CP=1 or throw CP=5
    thro();  // this has a branch, can succeed CP=1 or throw CP=6
    thro();  // this has a branch, can succeed CP=1 or throw CP=7
    thro();  // this has a branch, can succeed CP=1 or throw CP=8
  }
  catch (NullPointerException e) {
  }
}

So, I count 8 code paths in this main method, which, to me is a Cyclomatic Complexity of 8.

In Java terms, each mechanism for exiting a function counts to it's complexity, so, a method that has a success-state, and, throws, for example, possibly up to 3 exceptions, has 4 documented exit paths.

The complexity of a method which calls such a function, is:

CC(method) = 1 + sum (methodCallComplexity - 1)

I think other things to consider, is that, in my opinion, the catch clause does not contribute to the complexity of the method, the catch is simply the target of a throws branch, and thus a catch block that is the target of multiple throws counts 1 time for each throw, and not just once for everything.

Лицензировано под: CC-BY-SA с атрибуция
scroll top