Ищите разъяснения по структурированию кода для уменьшения цикломатической сложности - PullRequest
19 голосов
/ 15 октября 2008

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

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

Я понимаю, что самый простой способ уменьшить 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");

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

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?

Ответы [ 8 ]

9 голосов
/ 15 октября 2008
  1. Да. Ваш первый пример имеет точку принятия решения, а ваш второй - нет, поэтому первый пример имеет более высокий CC.
  2. Да, может быть, ваш первый пример имеет несколько точек принятия решения и, следовательно, более высокий CC. (См. Объяснение ниже.)
  3. Да-возможно. Очевидно, что они имеют одинаковое количество точек принятия решения, но существуют разные способы расчета CC, что означает ...

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

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

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

6 голосов
/ 15 октября 2008

После просмотра записи в Википедии и оригинальной статьи Томаса Дж. МакКейба, кажется, что упомянутые выше элементы - известные проблемы с метрикой.

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

4 голосов
/ 15 октября 2008

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

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

  1. Достаточно большая кодовая база: в любом нетривиальном проекте у вас будут функции с очень высоким значением CC. Настолько высоко, что не имеет значения, если в одном из ваших примеров CC будет 2 или 3. Функция с CC, скажем, более 300, определенно что-то для анализа. Не имеет значения, является ли CC 301 или 302.
  2. Не забудьте использовать свою голову. Есть методы, которые требуют много решений. Часто их можно как-то реорганизовать, чтобы их было меньше, но иногда нет. Не используйте правило типа «Перефакторинг всех методов с CC> xy». Посмотрите на них и используйте свой мозг, чтобы решить, что делать.

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

4 голосов
/ 15 октября 2008

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

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

1 голос
/ 06 января 2010

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

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

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

  • Соотношение между CC # и # тестами должно быть CC # <= # tests </li>
  • Рефакторинг для CC #, только если он увеличивается ремонтопригодность
  • CC выше 10 часто обозначает один или несколько запахов кода
1 голос
/ 15 октября 2008

Это опасность применения любой метрики вслепую. Метрика CC, безусловно, имеет много достоинств, но, как и с любым другим методом улучшения кода, ее нельзя оценить в отрыве от контекста. Направьте ваше руководство на обсуждение Каспером Джоном «Измерения линий кода» (хотелось бы найти ссылку для вас). Он указывает на то, что если Lines of Code является хорошим показателем производительности, то разработчики языка ассемблера являются наиболее продуктивными разработчиками на земле. Конечно, они не более продуктивны, чем другие разработчики; им просто требуется намного больше кода, чтобы выполнить то, что делают языки более высокого уровня с меньшим количеством исходного кода. Я упоминаю об этом, как я уже сказал, чтобы вы могли показать своим менеджерам, насколько глупо слепо применять метрики без интеллектуального анализа того, что метрика говорит вам.

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

0 голосов
/ 31 октября 2013

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

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

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

1 контрольный пример для обоих

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

2 теста для обоих

3.) Сначала можно привести ни к чему: «один» или «один» и «один и два». 3 дорожки. 2-й может привести ни к чему, ни к двум, ни к обоим. 4 дорожки.

3 теста для первого 4 теста для второго

0 голосов
/ 15 октября 2008

[Не по теме] Если вы предпочитаете удобочитаемость, а не хорошую оценку в метриках (неужели Дж. Спольски сказал: «что измерено, то сделано»? часто лучше использовать логическое имя с хорошим именем для замены вашего сложного условного выражения.

тогда

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

стать

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

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