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

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

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

Ответы

Ответ 1

Официальное название для этого - 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 - Еще один подобный инструмент.

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

Ответ 2

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

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

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

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

Ответ 3

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

В псевдокоде

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

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

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

Ответ 4

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

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