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

StackOverflow https://stackoverflow.com/questions/204369

Вопрос

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

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

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

Есть кое-что, в чем я не уверен, напримеркаков 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?т. е.вложенные операторы if ментально более сложны для понимания, но отражено ли это в CC?

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

Решение

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

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

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

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

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

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

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

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

Здесь следует иметь в виду две вещи:

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

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

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

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

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

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

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

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

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

  • Связь между CC # и # тестов должна быть CC# <= #тесты
  • Оптимизация для CC# только если она увеличивается ремонтопригодность
  • CC выше 10 часто указывает на один или несколько Код Пахнет

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

тогда

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

стать

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

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

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

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

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

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

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

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

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

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

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