Подтвердить что ты не робот

Поиск разъяснений о структурировании кода для уменьшения циклической сложности

Недавно наша компания начала измерять циклическую сложность (CC) функций в нашем коде на еженедельной основе и сообщала, какие функции улучшились или ухудшились. Поэтому мы начали уделять гораздо больше внимания ЦК функций.

Я читал, что CC может быть неформально рассчитан как 1 + количество точек принятия решения в функции (например, если инструкция, для цикла, select и т.д.), а также количество путей через функцию...

Я понимаю, что самым простым способом сокращения CC является повторное использование рефакторинга метода извлечения...

Есть что-то, о чем я не уверен, например. что представляет собой CC следующих фрагментов кода?

1)

for (int i = 0; i < 3; i++)
    Console.WriteLine("Hello");

и

Console.WriteLine("Hello");
Console.WriteLine("Hello");
Console.WriteLine("Hello");

Они оба делают то же самое, но имеет ли первая версия более высокий CC из-за инструкции for?

2)

if (condition1)
    if (condition2)
        if (condition 3)
            Console.WriteLine("wibble");

и

if (condition1 && condition2 && condition3)
    Console.WriteLine("wibble");

Предполагая, что язык выполняет оценку короткого замыкания, такую ​​как С#, эти два фрагмента кода имеют одинаковый эффект... но является ли CC первого фрагмента выше, потому что в нем есть три точки принятия решения/если утверждения?

3)

if (condition1)
{
    Console.WriteLine("one");

    if (condition2)
        Console.WriteLine("one and two");
}

и

if (condition3)
    Console.WriteLine("fizz");

if (condition4)
    Console.WriteLine("buzz");

Эти два фрагмента кода делают разные вещи, но имеют ли они один и тот же CC? Или вложенные операторы if в первом фрагменте имеют более высокий CC? то есть вложенные, если утверждения мысленно более сложны для понимания, но это отражено в CC?

4b9b3361

Ответ 1

  • Да. В вашем первом примере есть точка принятия решения, а вторая - нет, поэтому первая имеет более высокий CC.
  • Да, может быть, ваш первый пример имеет несколько точек принятия решений и, следовательно, более высокий CC. (См. Ниже пояснения.)
  • Да-возможно. Очевидно, что они имеют одинаковое количество точек принятия решений, но есть разные способы вычисления CC, что означает...

... если ваша компания измеряет CC определенным образом, тогда вам нужно ознакомиться с этим методом (надеюсь, они используют инструменты для этого). Существуют разные способы вычисления CC для разных ситуаций (операторы case, булевы операторы и т.д.), Но вы должны получать такую ​​же информацию из метрики независимо от того, какое соглашение вы используете.

Большая проблема заключается в том, что другие упоминали, что ваша компания, похоже, больше сосредотачивается на CC, чем на коде, стоящем за ней. В общем, конечно, ниже 5 отлично, ниже 10 хорошо, ниже 20 в порядке, 21-50 должны быть предупреждающим знаком, а выше 50 должны быть большим предупреждающим знаком, но это рекомендации, а не абсолютные правила. Вероятно, вам следует изучить код в процедуре с CC выше 50, чтобы убедиться, что это не просто огромная куча кода, но, возможно, существует определенная причина, по которой процедура написана таким образом, и это невозможно (для любого количество причин) для рефакторинга.

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

Ответ 2

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

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

Ответ 3

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

То же самое с прикованным ifs в примере 2 - эта структура позволяет вам иметь статут, который будет выполнен, если только условие 1 и условие2 истинны. Это особый случай, который невозможен в случае использования & &. Таким образом, if-chain имеет больший потенциал для особых случаев, даже если вы не используете это в своем коде.

Ответ 4

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

Здесь нужно иметь в виду две вещи:

  • Достаточно большая база кода: в любом нетривиальном проекте у вас будут функции с очень высоким значением CC. Настолько высока, что это не имеет значения, если в одном из ваших примеров CC будет 2 или 3. Функция с CC разрешить сказать более 300, безусловно, что-то для анализа. Не имеет значения, имеет ли CC 301 или 302.
  • Не забудьте использовать свою голову. Существуют методы, которые требуют много точек принятия решений. Часто их можно реорганизовать как-то, чтобы иметь меньше, но иногда они не могут. Не переходите к правилу вроде "Refactor all methods with CC > xy". Посмотрите на них и используйте свой мозг, чтобы решить, что делать.

Мне нравится идея еженедельного анализа. В контроле качества анализ тенденций является очень эффективным инструментом для определения проблем во время их создания. Это намного лучше, чем ждать, пока они не станут настолько большими, чтобы они стали очевидными (см. SPC для некоторых деталей).

Ответ 5

Это опасность нанесения какой-либо метрики вслепую. Метрика CC, безусловно, имеет много достоинств, но, как и любой другой метод улучшения кода, он не может быть оценен в разводе из контекста. Направьте свое руководство на обсуждение Casper Jone по измерению строк кода (я бы мог найти ссылку для вас). Он указывает, что если строки кода являются хорошей мерой производительности, то разработчики ассемблерного языка являются наиболее производительными разработчиками на земле. Конечно, они не более эффективны, чем другие разработчики; он просто требует гораздо больше кода для выполнения того, что говорят языки более высокого уровня, с меньшим количеством исходного кода. Я упоминаю об этом, как я уже сказал, поэтому вы можете показать своим менеджерам, насколько глупыми они должны слепо применять метрики без разумного обзора того, что говорит вам метрика.

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

Ответ 6

Цикломатическая сложность аналогична температуре. Они оба являются измерениями, а в большинстве случаев бессмысленными без контекста. Если бы я сказал, что температура снаружи составляла 72 градуса, это не означает многого; но если бы я добавил, что я был на Северном полюсе, число 72 становится значительным. Если кто-то сказал мне, что метод имеет цикломатическую сложность 10, я не могу определить, хорошо это или плохо, без его контекста.

Когда я просматриваю существующее приложение, я нахожу цикломатическую сложность полезной меткой "начальной точки". Первое, что я проверю, это методы с CC > 10. Эти методы " > 10" не обязательно являются плохими. Они просто дают мне отправную точку для просмотра кода.

Общие правила при рассмотрении номера CC:

  • Отношения между CС# и # тестами должны быть CС# <= #tests
  • Рефакторинг для CС#, только если он увеличивается ремонтопригодность
  • CC выше 10 часто указывает один или несколько Code Smells

Ответ 7

[Off topic] Если вы предпочитаете читаемость над хорошим счетом в метриках (был ли это J.Spolsky, который сказал, "что измеряется, сделайте"? - что означает, что метрики злоупотребляют чаще, чем я полагаю), это часто лучше использовать имя с именем boolean, чтобы заменить сложную условную инструкцию.

затем

if (condition1 && condition2 && condition3)
    Console.WriteLine("wibble");

стать

bool/boolean theWeatherIsFine =  condition1 && condition2 && condition3;

if (theWeatherIsFine)
    Console.WriteLine("wibble");

Ответ 8

Я не эксперт в этом вопросе, но я думал, что дам свои два цента. И, возможно, все это стоит.

Cyclomatic Complexity, по-видимому, является просто автоматическим ярлыком для поиска потенциально (но не определенно) проблемных фрагментов кода. Но разве реальная проблема не может быть решена одним из испытаний? Сколько тестов требует код? Если CC выше, но количество тестовых примеров одинаково, а код чище, не беспокойтесь о CC.

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

1 тестовый пример для обоих

2.) В обоих случаях вы либо пишете "wibble", либо нет.

2 тестовых примера для

3.) Вначале не может быть ничего, "одного", "одного" и "одного и двух". 3 пути. 2-й не может привести ни к чему, ни к одному из них, ни к обоим. 4 пути.

3 тестовых примера для первого 4 тестовых примера для второго