yegor256
yegor256

Reputation: 105063

How to calculate cyclomatic complexity of a project (not a class/function)?

How to calculate cyclomatic complexity of the entire Java project? I have complexities for every method, but how to aggregate them all into one numeric metric? Any ideas or existing methods?

I'm not looking for a tool, but for an algorithm.

Simple average hardly works because there are many 1-complexity methods, which are not really of low complexity, but of low importance for the code base (in most cases).

Upvotes: 5

Views: 5427

Answers (4)

Aydin Homay
Aydin Homay

Reputation: 325

To my best knowledge, there is no answer to your question yet. But what Microsoft Visual Studio is doing is summing up all Cyclomatic Complexities for a given project and considering the result as assembly level Cyclomatic Complexity. But I personally will suggest you go with Max Cyclomatic Complexity. Just simply consider the Maximum Cyclomatic Complexity as Project Cyclomatic Complexity. The reason for that is as long as there is a method with higher Cyclomatic Complexity within a Project that Project is gonna be your bottleneck for your Software System. The other reason is because of strongly connected graph theory, according to the original paper of McCabe Cyclomatic Complexity for a strongly connected graph is the maximum Cyclomatic Complexity between Cyclomatic Complexities within independently existing circuits.

Upvotes: 0

Brian
Brian

Reputation: 17309

Entire books have been written on code metrics, so you're lucky that you're asking a more specific question. For Java cyclomatic complexity, you could find the number of methods that exceed a cyclomatic complexity of 5 or 6 (you pick the number here). If this number exceeds more than a certain percentage of your number of methods, then the overall cyclomatic complexity is poor. A good number for the percentage depends entirely on the size of the project, so maybe instead of dividing only by the number of methods, you can put less weight on the method count in the division by making it grow slowly for large numbers, such as a square root or logarithm to try and make it more stable as the project grows.

Maybe something like this:

public double evaluateCyclomaticComplexity(List<MethodStat> methodStats) {
    int bad = 0;
    for (MethodStat methodStat : methodStats)
        if (methodStat.getCyclomaticComplexity() >= 6)
            bad++;

    double denominator = Math.sqrt(methodStats.size());
    return bad * 100.0 / denominator;
}

The smaller the number returned here, the better. For really bad project, this will return something greater than 100.

The denominator function should represent how fast you're okay with the complexity growing as the code base grows. Typically, you want the CC to be lower per function as the code grows so that it remains maintainable, so something that grows slower as the project size increases would be best.

Test it, tweak it, etc. Ultimately, code metrics are hard to get just right, which I can attest to after reading several journal papers on open source software that use numbers to represent "maintainability". Anything we can come up with here can likely be greatly improved if enough time is spent on it.

Upvotes: 3

Juvanis
Juvanis

Reputation: 25950

I don't know whether this will help, but I just wanted to tell what I thought. You can use a global depth counter to get method-call depths and update it on every method invocation. You see the same snippet is injected in every method here manually, but there might be a solution for auto-injecting the code to all methods. With the level of stack-trace length, you can compute the aggregated complexity, I think.

public class Cyclomatic
{
    public static int max = Integer.MIN_VALUE;

    static void a() 
    {
        b();
        int temp = Thread.currentThread().getStackTrace().length;
        if (temp > max)
            max = temp;
    }

    static void b() 
    {
        c();
        int temp = Thread.currentThread().getStackTrace().length;
        if (temp > max)
            max = temp;
    }

    static void c() 
    {
        int temp = Thread.currentThread().getStackTrace().length;
        if (temp > max)
            max = temp;
    }

    public static void main(String[] args) 
    {
        a();
        System.out.println(max);
    }
}

Output:

5

Upvotes: 0

Baptiste Wicht
Baptiste Wicht

Reputation: 7663

I found that formula:

TCC = Sum(CC) - Count(CC) + 1
TCC: Total CC
Sum(CC): Sum of CC of all functions
Count(CC): Number of functions

Source: http://www.aivosto.com/project/help/pm-complexity.html

But perhaps it is too limited.

Another idea would be to consider the call graph of the program as a program itself and the compute the CC of the call graph. The nodes will be weighted by their CC. (I've no idea if it's feasible, it is just an idea)

Upvotes: 2

Related Questions