Чому цикломатична складність важлива для одного методу?


10

Я використовую SonarLint для Eclipse з недавнього часу, і це мені дуже допомогло. Однак воно постало перед нами питання про цикломатичну складність.

SonarLint вважає прийнятним CC 10, і є деякі випадки, коли я перевищую це, приблизно 5 або 6 одиниць. Ці частини пов'язані з картографами, де значення спираються на різні змінні, наприклад:

  • Поле A спирається на String sA;
  • Поле B спирається на String sB;
  • Поле C спирається на String sC;
  • тощо ...

У мене немає іншого вибору, як розмістити ifдля кожного поля. Це не мій вибір (на щастя), а вже існуюча і складна система, яку я не можу змінити сам.


Ядро мого питання полягає в тому, чому так важливо не мати занадто високий КК в одному методі ? Якщо ви переміщуєте деякі свої умови одним або декількома під-методами, щоб зменшити складність, це не знижує вартість вашої загальної функції, це просто перенесення проблеми в інше місце, я думаю?

(Вибачте за невеликі помилки, якщо такі є).


EDIT

Моє запитання не стосується глобальної цикломатичної складності, а лише складності єдиного методу та розбиття методу (у мене є орієнтовний час пояснення, що саме я маю на увазі, вибачте). Я запитую, чому дозволено розділити ваші умови на більш дрібні методи, якщо вони все ще належать до "супер методу", який просто виконає кожен під-метод, додавши таким чином складність алгоритму.

Однак, друге посилання ( про анти-візерунок ) дуже допомагає.




^^^ "Стрілецьке" питання, мабуть, кращий дублікат у тому сенсі, що він пояснює, як поліпшити свій код, але я вибрав перший через детальне пояснення, відповідаючи на частину вашого запитання про цикломатичну складність
gnat

Розбиття методу на більш дрібні частини не зменшує загальну кількість виконуваного коду, але дає зрозуміти окремі завдання, що відбуваються; кожного з них можна зрозуміти набагато легше індивідуально, ніж коли всі вони заплутані у більшому цілому. Принаймні, це вилучає багато проміжних змінних, що використовуються одноразово, з більшої області застосування.
Довал

1
Для вашого конкретного описаного випадку я б зробив щось із вашого основного методу, наприклад "A = extraAFrom (sA);" для кожного поля. Можливо, ви можете придумати кращі назви, оскільки знаєте фактичні поля та їх використання.
Олов'яна людина

Відповіді:


32

Тут головна річ: «ємність мозку».

Розумієте, одна з головних функцій коду - це ... читати . І код можна легко прочитати та зрозуміти; або важко.

А наявність високого КС просто передбачає багато "рівнів" в межах одного методу. І це означає: ви, як читач людини, будете важко розуміти цей метод.

Коли ви читаєте вихідний код, ваш мозок автоматично намагається поставити речі в перспективу: іншими словами - він намагається створити певну форму "контексту".

І коли у вас є невеликий метод (з хорошим ім’ям), який складається лише з декількох рядків, і дуже низький рівень CC; тоді ваш мозок може легко прийняти цей «блок». Ти читаєш його, розумієш; Зроблено.

З іншого боку, якщо ваш код має високий рівень CC, ваш мозок витратить багато багатьох "циклів" більше, щоб вирахувати, що відбувається.

Ще один спосіб сказати, що: ви завжди повинні схилятися до переваги складної мережі простих речей, ніж простої мережі складних речей. Тому що ваш мозок краще розуміє дрібниці.


9
То в основному справа не в технічних питаннях, а в людських ? Це справді звучить розумно, я не знаю, як я не думав про це раніше. Дякую !
Яссін Бадаш

4
Якщо так, я від усієї душі рекомендую придбати Роберт Мартін "Чистий код" (ви можете знайти pdf безкоштовно в мережах). Розумієте, створення читабельного коду - одна з найважливіших, але дуже часто ігнорованих чеснот хорошого програміста.
GhostCat вітає Моніку С.

@YassineBadache CC також ускладнює тестування кожного куточка (повне покриття).
Tulains Córdova

У цьому й полягала суть готського паперу Діжкстри .
Сет Баттін

На мій досвід, помилки майже завжди є у методах з високим КС, і коли помилки використовуються в методі з низьким рівнем CC, вони, як правило, абсолютно очевидні, ніякого способу вони не можуть ховатися за першим запуском коду. Крім того, я вважаю, що майже ніколи не доводиться змінювати метод із низьким рівнем концентрації крові - більше навантаження знімається з мозку.
Лорен Печтел

6

CC, як і всі інші великі правила щодо запаху коду, є евристичним . Критерій, який не відповідає безпеці, не говорить про абсолютну правду. Якби це було, розумною справою було б просто зробити такі методи незаконними мовою та змусити людей досягати своїх цілей по-іншому.

Але це не так, як працюють показники. Більшість випадків їх функцією є оповіщення людей про речі, про які вони не були обізнані. У вашому випадку ви усвідомлюєте, що логіка вивернута, і альтернативні рішення роблять це ще більш викривленим. Тому немає сенсу намагатися задовольнити примітивне правило, коли його головна мета - виносити попередження людям, які не усвідомлюють, що існує проблема.


2
Якщо "FieldA покладається на String sA", як заявляє ОП, я не переконаний, що переміщення цього переходу в CalculateFieldA (String sA) створює більш складний код.
Taemyr

2

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

Якщо у вас довгий складний метод з великою кількістю (вкладених) if, важко сказати, що він насправді робить. Якщо витягнути деякі приватні методи та назвати їх змістовно, це набагато простіше.


Хоча це відповідь хороша, вона трохи коротша. Було б добре, якщо ви можете навести приклад того, що ви говорите, і бути більш конкретним щодо питання, яке задає ОП: "чому так важливо не мати занадто високий КК в одному методі?".
Мачадо

2

Цикломатична складність методу пов'язана з кількістю тестових випадків, необхідних для методу. Зокрема, цикломатична складність 10 означає, що 10 є верхньою межею для тестових випадків, щоб мати повне покриття галузей для вашого методу. Це також пов’язано з кількістю шляхів, які необхідно перевірити, мінус неможливі шляхи.

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


0

CC - це лише евристика, і від того, наскільки «поганим» є конкретний бал, залежить багато речей.

З цього приводу, ви завжди повинні розглядати високий КС як щось, що виділяє код, який може / повинен бути відновлений. Ви говорите, що переміщення ifоператора на інший метод приховує проблему - але чи існує там шаблон, який ви можете абстрагувати замість копіювання вставлення n разів? Якщо це довгий if-elseланцюг, чи можете ви перетворити його на заяву переключення, чи, можливо, використати поліморфізм чи щось інше? Якщо є глибоке гніздування, чи можуть бути приєднані деякі ваші умовні пропозиції чи це вказує на окремі обов'язки, які слід розділити на різні класи?


0

Я бачу цикломатичну складність як попередження. Якщо ви можете прочитати код, і він не надто складний, щоб зрозуміти, я б не переймався над цим багато, мабуть, важливіші речі неправильно турбуватися, завжди є.

Один із способів зменшити вид CC, який ви згадуєте, - це використовувати поліморфізм, оскільки ви позначили своє питання тегом Java. Тож замість строкових набраних кодових шляхів можна використовувати добре названі класи. Це може допомогти, але іноді є надмірним і може зробити ваш код ще складнішим для розуміння.

Однак це може бути ознакою коду, який буде важко підтримувати. Читаючи метод, чи легко зрозуміти, який шлях коду ви пройдете в кожному випадку? Чи вдалося б вам пропустити цей метод, якщо ви не знаєте добре кодової бази та шукали щось пов'язане, але далі в коді? Я знаю, що деякі люди виступають за розділення методів на багато 1/2 рядкових методів з описовими іменами, але іноді я думаю, що це навіть важче прочитати, ніж код, який мав на увазі замінити.

Зрештою, технічне обслуговування - це важка проблема, і вирішувати, на вашу думку, буде легше читати. Те, що ви взагалі про це думаєте, означає, що ви на правильному шляху. Пам'ятайте лише, що вашим обслуговувачем, який повинен спробувати розшифрувати цей код за кілька років. Тому зробіть їх максимально простим.


0

Це зводиться до того, скільки часу витрачається на перегляд (цикли мозку) коду та розуміння того, що робить код.

  • Розглянемо метод 10 рядків - ймовірно, знадобиться кілька хвилин, щоб зрозуміти, що це робить.
  • Розгляньте метод 100 рядків - можливо, знадобиться година чи більше, щоб зрозуміти, що робиться.
  • Розглянемо метод 1000 рядків - можливо, знадобиться день або більше, щоб зрозуміти, що робиться.

Також більші методи важче перевірити і складніше передбачити, яка поведінка може відбутися.

Цикломатична складність - міра. У цьому випадку більш високі значення є показниками потенційних проблем. Складний код займає більше часу, щоб зрозуміти його і, ймовірно, не перевіряється так ретельно, як менш складні методи. Отже, важливо зазначити, які області коду є складними з цим заходом для рефакторингу та обслуговування.

Інша річ, яку слід врахувати, - це оновлення складного коду. Роблячи аналіз, розробник міг повідомити, що змінювати код більш-менш ризиковано, дивлячись на його складність.

Отже, велика цінність для вимірювання складності, яку можна використовувати і використовувати для цілей прийняття рішень.


1
На жаль, відповідь Cat Ghost дуже схожа, повинна бути оновлена ​​сторінка.
Джон Рейнор
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.