Обычно это хорошо делать, когда это возможно, но мне нравится думать о такой работе не как о «шагах», а как о подзадачах .
Подзадача - это конкретная единица работы, которая может быть выполнена: она несет определенную ответственность, а также определенные входные данные и выходные данные (подумайте о «S» в SOLID ). Подзадача не нуждается в повторном использовании: некоторые люди склонны думать: «Мне никогда не придется вызывать это из чего-либо еще, так зачем писать это как функцию?» но это заблуждение
Я постараюсь также обрисовать преимущества, а также то, как это применяется к вложенным функциям (замыканиям) по сравнению с просто еще одной функцией в классе. Вообще говоря, я бы рекомендовал не использовать замыкания, если они вам не нужны (их много, но разделение кода на логические блоки не входит в их число).
Читаемость.
Более 200 строк процедурного кода (тела функции) трудно читать. Функции 2-20 строк легко читаются. Код для людей.
Вложенные или нет, вы в основном получаете преимущество читабельности, если вы не используете много переменных из родительской области, в этом случае это может быть так же трудно читать.
Предел переменной области
Наличие другой функции заставляет вас ограничивать область видимости переменной и, в частности, передавать то, что вам нужно.
Это часто также делает вашу структуру лучше, потому что если вам нужна какая-то переменная состояния из более раннего «шага», вы можете обнаружить, что на самом деле есть другая подзадача, которая должна быть написана и выполнена первой, чтобы получить это значение. Или, другими словами, это затрудняет написание сильно связанных кусков кода.
Наличие вложенных функций позволяет обращаться к переменным в родительской области изнутри вложенной функции (замыкание). Это может быть очень полезно, но также может привести к тонким, трудно обнаруживаемым ошибкам, поскольку выполнение функции может не происходить так, как написано. Это даже больше в случае, если вы изменяете переменные в родительской области (вообще очень плохая идея).
Модульные тесты
Каждая подзадача, реализованная функцией (или даже классом), является отдельным, тестируемым фрагментом кода. Преимущества модульного тестирования и TDD хорошо документированы в других местах.
Использование вложенных функций / замыканий не позволяет выполнять модульное тестирование. Для меня это нарушение условий и причина, по которой вы должны просто выполнять другую функцию, если нет особой необходимости закрытия.
Работа в команде / Дизайн сверху вниз
Подзадачи могут быть написаны разными людьми, независимо, при необходимости.
Даже при написании кода может быть полезно просто вызвать некоторую подзадачу, которая еще не существует, при создании основной функциональности и заботиться о фактической реализации подзадачи только после того, как вы узнаете, что она получит необходимые вам результаты в осмысленно. Это также называется нисходящим дизайном / программированием.
Повторное использование кода
Хорошо, так что, несмотря на то, что я сказал ранее, иногда на самом деле в конечном итоге возникает причина для повторного использования подзадачи для чего-то другого. Я вовсе не сторонник "архитектурного астронавта", а просто потому, что при написании слабосвязанного кода вы можете в конечном итоге получить выгоду от повторного использования.
Часто такое повторное использование означает некоторый рефакторинг, что вполне ожидаемо, но рефакторинг входных параметров для небольшой автономной функции НАМНОГО проще, чем извлечение ее из 200+ строковых функций через месяцы после ее написания, что на самом деле является моей точкой зрения здесь.
Если вы используете вложенную функцию, то ее повторное использование, как правило, в любом случае является вопросом рефакторинга на отдельную функцию, и поэтому я бы сказал, что вложенная функция - это не тот путь.