Почему этот код имеет высокую цикломатическую сложность — или это ошибка PHPMD в Jenkins?

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

У меня есть функция, которая выглядит так:

protected function update($uuid, $data, $householdUuid, $androidId) {
    $household = $this->householdService->getHouseholdByUuid($householdUuid);

    $this->updatePeriod($household, $data);
    $this->updateNickname($household, $data, $androidId);
    $this->updateDateOrder($household, $data);
    $this->updateCurrency($household, $data);
    $this->updateAccounts($household, $data);

    $household->save();
    return $this->respondUpdated();
}

Это помечается как имеющее цикломатическую сложность 10. Как это возможно? Судя по документации, я бы оценил это как 1. Единственная возможность состоит в том, что PHPMD спускается вниз в различные вызовы методов.

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

Или, может быть, проблема проще - я запускаю PHPMD через непрерывную интеграцию, настроенную с Jenkins. Может ли быть проблема, когда PHPMD не использует самый последний код? У меня были несколько похожие проблемы, когда он помечал класс как имеющий слишком много строк после того, как я уже провел рефакторинг класса ниже ограничения количества строк.


person matt    schedule 03.12.2013    source источник
comment
Похоже, 10 = 1 (для метода) + 9 (для каждого '->'), но у меня нет объяснения.   -  person Tom Blodget    schedule 05.12.2013
comment
Согласитесь, что это выглядит именно так, но это ужасно и не соответствует документации.   -  person matt    schedule 05.12.2013
comment
Это также все еще не добавляет до 10   -  person Chris Rasys    schedule 27.12.2014


Ответы (2)


Я мог бы подумать, что каждый вызов функции добавляет +1 к сложности, поскольку технически это проход по коду, но согласно документации он не должен этого делать. Даже определение цикломатической сложности не поддерживает этот подсчет.

Я бы подумал, что это ошибка в PHP Mess Detector, так как расчет сложности PHP_CodeSniffer не дает 10 по этому поводу.

person Steven Scott    schedule 12.12.2013
comment
Даже если это то, что он делал (в чем я очень сомневаюсь), он все равно не составил бы 10. - person Chris Rasys; 27.12.2014
comment
Как я уже сказал, я не уверен, как вы получаете этот номер в PHP Mess Detector. Проверяли ли вы это с помощью других инструментов, поскольку я знаю, что PHP_CodeSniffer может делать аналогичный подсчет, и я полагаю, что PHPUnit/XDebug может произвести аналогичный подсчет в дампе документации, если он включен. - person Steven Scott; 29.12.2014

Я думаю, это ошибка. Я не изолировал его, но я свернул одну из своих функций на {return false} и повторно запустил задание jenkins. У меня все еще была сложность NPath 4000 (даже). Когда я запустил phpmd из командной строки, он правильно вычислил его.

При более подробном рассмотрении phpmd полагается на pdepend, а pdepend выполняет некоторое кэширование. Если вы запускаете pdepend напрямую, вы можете указать кэширование «памяти» или «файла» в конфигурации. Но я не знаю, как и возможно ли повлиять на то, как phpmd его использует. Я думал, что, возможно, перезапуск Дженкинса прояснит ситуацию, но это не так. Как только моя функция была помечена как «слишком сложная», она, кажется, осталась с ней.

В репозитории phpmd на github есть несколько проблем с кэшированием. Но все как-то расплывчато. Если я выделю это как воспроизводимую ошибку, а не какую-то причуду моей установки, я отправлю отчет об ошибке.

person spm    schedule 05.03.2015