Почему рекомендуется избегать вложенных блоков в функции? (PHP)

Я установил бета-версию Netbeans 7.4, и есть новый намек, в котором говорится: «Слишком много вложенных блоков в объявлении функции – это хорошая практика для внедрения новой функции …».

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

Формальное название для этого – Cyclomatic Complexity .

Это показатель того, насколько сложна функция, основанная на количестве «точек принятия решений» в функции. Чем выше число, тем сложнее функция.

Сложность определяется количеством точек принятия решения в методе плюс один для ввода метода. Точками принятия решения являются «if», «while», «for» и «case labels». Как правило, 1-4 – низкая сложность, 5-7 – умеренная сложность, 8-10 – высокая сложность, а 11+ – очень высокая.

(взято из http://phpmd.org/rules/codesize.html )

Причина, по которой считается слишком сложной, слишком высока, потому что она затрудняет проверку функции.

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

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

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

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

Процесс тестирования функций в изоляции друг от друга называется Unit Testing . Это очень большая тема сама по себе, но стоит исследовать, если вы хотите узнать больше о хорошей практике разработки программного обеспечения.

Поскольку вы отметили этот вопрос PHP, я укажу вам в сторону нескольких инструментов, которые помогут вам:

  • Модуль PHP – это де-факто стандартный пакет тестирования модулей для PHP.
  • PHPMD – «PHP Mess Detector»; инструмент для анализа вашего кода, чтобы искать такие вещи, как чрезмерная сложность.
  • pDepend – другой подобный инструмент.

Есть множество других доступных инструментов, но этого, вероятно, достаточно, чтобы начать работу; сначала узнайте их. Вы будете сталкиваться с другими, естественно, при исследовании темы.

Как правило, функции / методы хорошо написаны, если они делают только одну вещь, но делают это хорошо.

Когда метод начинает проявлять гнездо за пределами 1 или 2 уровней, это верный признак, он пытается сделать больше чем одну вещь одновременно.

Когда в функции много гнездования и условностей, это также делает его логику более запутанной и трудной для подражания, а также более трудной для тестирования.

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

Хорошая выгода ограничена. Путем сокращения блока до отдельного метода вы даете понять будущим читателям, что этот фрагмент кода зависит только от заданных параметров.

В псевдокоде

$some_variable = "something"; $some_other_variable = "something else"; if(x < y) { ... lots of code ... some_method($some_variable); ... more code ... } 

Извлекая условное выражение на отдельный метод, становится ясно, что логика внутри этой ветви НЕ зависит от $some_other_variable .

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

Необычный код вызывает кошмары для обслуживания … По крайней мере, в модели KISS держите ее простой, и ваша отладка будет легкой.

Этот ответ сохраняется в модели KISS, это простой ответ