Я использую SonarLint для Eclipse с недавнего времени, и это мне очень помогло. Однако, это подняло мне вопрос о цикломатической сложности.
SonarLint считает приемлемым CC 10, и в некоторых случаях я превышаю его, около 5 или 6 единиц. Эти части относятся к картографам, где значения зависят от разных переменных, например:
- Поле A опирается на строку sA;
- Поле B опирается на строку sB;
- Поле C опирается на String sC;
- так далее ...
У меня нет другого выбора что положить if
для каждого поля. Это не мой выбор (к счастью), но уже существующая и сложная система, которую я не могу изменить самостоятельно.
Суть моего вопроса: почему так важно не иметь слишком высокий CC в одном методе ? Если вы перенесете некоторые из ваших условий одним или несколькими вспомогательными методами, чтобы уменьшить сложность, это не уменьшит стоимость вашей общей функции, а просто переместит проблему в другое место, я полагаю?
(Извините за мелкие ошибки, если есть).
РЕДАКТИРОВАТЬ
Мой вопрос касается не глобальной цикломатической сложности, а только сложности одного метода и разделения метода (у меня есть трудное время, чтобы объяснить, что именно я имею в виду, извините). Я спрашиваю, почему допустимо разделить ваши условия на более мелкие методы, если они все еще принадлежат «супер-методу», который будет просто выполнять каждый суб-метод, тем самым добавляя сложности алгоритму.
Однако вторая ссылка ( об анти-паттерне ) очень полезна.
источник
Ответы:
Основная вещь здесь: «емкость мозга».
Видите ли, одна из основных функций кода ... для чтения . И код может быть легко читаемым и понятным; или сложно.
А наличие высокого CC просто подразумевает множество «уровней» в рамках одного метода. И это подразумевает: вам, читателю, будет трудно понять этот метод.
Когда вы читаете исходный код, ваш мозг автоматически пытается представить вещи в перспективе: другими словами - он пытается создать некую форму «контекста».
И когда у вас есть маленький метод (с хорошим именем), который состоит только из нескольких строк и очень низкого CC; тогда ваш мозг может легко принять этот «блок». Вы читаете это, вы понимаете это; СДЕЛАННЫЙ.
С другой стороны, если ваш код имеет высокий уровень CC, ваш мозг будет тратить много «циклов» больше, чтобы вычесть то, что происходит.
Другой способ сказать это: вы всегда должны склоняться к тому, чтобы отдавать предпочтение сложной сети простых вещей, а не простой сети сложных вещей. Потому что ваш мозг лучше понимает мелочи.
источник
CC, как и все другие эмпирические правила для запахов кода, является эвристическим . Это не безопасный критерий, который говорит вам абсолютную правду. Если бы это было так, разумно было бы просто сделать такие методы незаконными в языке и заставить людей достичь своих целей другим способом.
Но это не так, как работают индикаторы. В большинстве случаев их функция заключается в предупреждении людей о вещах, о которых они не знали. В вашем случае вы знаете, что логика запутанная и альтернативные решения сделают ее еще более запутанной. Следовательно, нет смысла пытаться удовлетворить примитивное эмпирическое правило, когда его основная цель - выпускать предупреждения людям, которые не знают о наличии проблемы.
источник
Вкратце: все дело в удобочитаемости и, следовательно, удобстве сопровождения вашего кода.
Если у вас есть длинный, сложный метод с большим количеством (вложенных)
if
, становится трудно сказать, что он на самом деле делает. Если вы извлекаете некоторые частные методы и называете их осмысленно, это намного проще.источник
Цикломатическая сложность метода связана с количеством тестовых случаев, необходимых для метода. В частности, цикломатическая сложность 10 означает, что 10 является верхней границей для тестовых случаев, чтобы иметь полное покрытие ветвления для вашего метода. Это также связано с количеством путей, которые должны быть проверены, за вычетом любых невозможных путей.
Кроме того, я согласен с другими ответами по другим соображениям - умственные способности разработчика или индикатор потенциальных проблем или рефакторинг или мера читаемости и ремонтопригодности кода .
источник
CC - это просто эвристика, и от того, насколько «плох» конкретный результат, зависит многое.
Тем не менее, вы всегда должны рассматривать высокий CC как нечто, что выделяет код, который можно / нужно реорганизовать. Вы говорите, что перемещение
if
оператора в другой метод скрывает проблему - но есть ли там шаблон, который вы можете абстрагировать вместо вставки копий n раз? Если это длиннаяif-else
цепочка, можете ли вы превратить ее в оператор switch, или, возможно, использовать полиморфизм или что-то еще? Если есть глубокое вложение, можно ли объединить некоторые из ваших условных предложений, или это указывает на отдельные обязанности, которые следует разделить на разные классы?источник
Я вижу цикломатическую сложность как предупреждение. Если вы можете прочитать код, и он не слишком сложен для понимания, то я бы не стал сильно беспокоиться об этом, возможно, есть более важные вещи, о которых стоит беспокоиться, они всегда есть.
Один из способов уменьшить тип CC, который вы упоминаете, - это использовать полиморфизм, поскольку вы пометили свой вопрос тегом Java. Таким образом, вместо строковых путей кода вы можете использовать хорошо именованные классы. Это может помочь, но иногда излишне и может сделать ваш код еще сложнее для понимания.
Однако это может быть признаком кода, который будет сложно поддерживать. Легко ли увидеть, какой путь кода вы будете использовать при каждом чтении при чтении метода? Сможете ли вы пропустить этот метод, если вы плохо знаете кодовую базу и искали что-то связанное, но дальше в коде? Я знаю, что некоторые люди выступают за разделение методов на множество методов длиной в 1/2 строки с описательными именами, но иногда я думаю, что это даже сложнее читать, чем код, который он должен был заменить.
В конечном итоге ремонтопригодность является сложной проблемой, и вам решать, что, по вашему мнению, будет легче читать. Тот факт, что вы вообще об этом думаете, означает, что вы на правильном пути. Просто помните, что сопровождающим, который должен попытаться расшифровать этот код через несколько лет, может быть вы. Поэтому сделайте это как можно проще для них.
источник
Все сводится к тому, сколько времени тратится на просмотр (циклы мозга) кода и понимание того, что делает код.
Кроме того, более крупные методы сложнее тестировать и труднее предсказать, какое поведение может произойти.
Цикломатическая сложность является мерой. В этом случае более высокие значения являются индикаторами потенциальных проблем. Сложный код требует больше времени для понимания и, вероятно, не тестируется так тщательно, как менее сложные методы. Поэтому важно отметить, какие области кода являются сложными с этой мерой для целей рефакторинга и обслуживания.
Еще одна вещь, которую следует учитывать, это обновление сложного кода. При проведении анализа разработчик может сообщить, что изменение кода более или менее рискованно, если посмотреть на его сложность.
Таким образом, есть много ценности для измерения сложности, которые можно использовать и использовать для целей принятия решений.
источник