Как рассчитать цикломатическую сложность проекта (не класса/функции)?

Как рассчитать цикломатическая сложность всего проекта Java? У меня есть сложности для каждого метода, но как объединить их все в одну числовую метрику? Любые идеи или существующие методы?

Я ищу не инструмент, а алгоритм.

Простое среднее вряд ли работает, потому что существует много методов 1 сложности, которые на самом деле не имеют низкой сложности, но мало важны для кодовой базы (в большинстве случаев).


person yegor256    schedule 26.11.2012    source источник


Ответы (3)


О метриках кода написаны целые книги, так что вам повезло, что вы задаете более конкретный вопрос. Для цикломатической сложности Java вы можете найти количество методов, которые превышают цикломатическую сложность 5 или 6 (вы выбираете число здесь). Если это число превышает определенный процент от вашего количества методов, то общая цикломатическая сложность неудовлетворительна. Хорошее число для процента полностью зависит от размера проекта, поэтому, возможно, вместо деления только на количество методов вы можете придать меньшее значение количеству методов в делении, заставив его медленно расти для больших чисел, таких как квадратный корень или логарифм, чтобы попытаться сделать его более стабильным по мере роста проекта.

Может быть, что-то вроде этого:

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;
}

Чем меньше число вернулось сюда, тем лучше. Для действительно плохого проекта возвращается значение больше 100.

Функция знаменателя должна показывать, насколько быстро вы справляетесь с ростом сложности по мере роста базы кода. Как правило, вы хотите, чтобы CC для каждой функции был ниже по мере роста кода, чтобы его можно было поддерживать, поэтому лучше всего будет что-то, что растет медленнее по мере увеличения размера проекта.

Протестируйте его, настройте и т. д. В конечном счете, метрики кода трудно получить правильно, что я могу подтвердить после прочтения нескольких журнальных статей о программном обеспечении с открытым исходным кодом, в которых числа используются для представления «обслуживаемости». Все, что мы можем здесь придумать, может быть значительно улучшено, если на это будет потрачено достаточно времени.

person Brian    schedule 26.11.2012

Я нашел эту формулу:

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

Источник: http://www.aivosto.com/project/help/pm-complexity.html

Но, возможно, он слишком ограничен.

Другая идея состоит в том, чтобы рассматривать граф вызовов программы как саму программу и вычислять CC графа вызовов. Узлы будут взвешены по их CC. (Я понятия не имею, возможно ли это, это просто идея)

person Baptiste Wicht    schedule 26.11.2012

Я не знаю, поможет ли это, но я просто хотел сказать, что я думаю. Вы можете использовать глобальный счетчик глубины для получения глубины вызова метода и обновления его при каждом вызове метода. Вы видите, что один и тот же фрагмент вводится в каждый метод вручную, но может быть решение для автоматического внедрения кода во все методы. Я думаю, что с уровнем длины трассировки стека вы можете вычислить совокупную сложность.

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);
    }
}

Вывод:

5
person Juvanis    schedule 26.11.2012