Geralmente é bom fazer isso sempre que possível, mas eu gosto de pensar nesse tipo de trabalho não como "etapas", mas como subtarefas .
Uma subtarefa é uma unidade específica de trabalho que pode ser executada: possui uma responsabilidade específica e entradas e saídas definidas (pense no "S" no SOLID ). Uma subtarefa não precisa ser reutilizável: algumas pessoas tendem a pensar "Eu nunca precisarei chamar isso de outra coisa; por que escrevê-lo como uma função?" mas isso é uma falácia.
Vou tentar também descrever os benefícios e também como isso se aplica a funções aninhadas (fechamentos) versus apenas outra função da classe. De um modo geral, eu recomendaria não usar encerramentos, a menos que você precise especificamente de um (existem muitos usos, mas separar o código em blocos lógicos não é um deles).
Legibilidade.
Mais de 200 linhas de código processual (corpo de uma função) são difíceis de ler. As funções de 2-20 linhas são fáceis de ler. Código é para humanos.
Aninhado ou não, você obtém o benefício da legibilidade, a menos que esteja usando muitas variáveis do escopo pai; nesse caso, pode ser igualmente difícil de ler.
Limitar o escopo da variável
Ter outra função obriga a limitar o escopo da variável e a passar especificamente o que você precisa.
Isso geralmente melhora a estrutura do código, porque se você precisar de algum tipo de variável de estado de uma "etapa" anterior, poderá descobrir que há outra subtarefa que deve ser escrita e executada primeiro para obter esse valor. Ou, em outras palavras, torna mais difícil escrever trechos de código altamente acoplados.
Ter funções aninhadas permite acessar variáveis no escopo pai de dentro da função aninhada (fechamento). Isso pode ser muito útil, mas também pode levar a erros sutis e difíceis de encontrar, pois a execução da função pode não ocorrer da maneira como está escrita. Esse é ainda mais o caso se você estiver modificando variáveis no escopo pai (uma péssima idéia, geralmente).
Testes unitários
Cada subtarefa, implementada uma função (ou mesmo uma classe), é um trecho de código testável e independente. Os benefícios do teste de unidade e TDD estão bem documentados em outros lugares.
O uso de funções / fechamentos aninhados não permite testes de unidade. Para mim, este é um rompimento de acordos e a razão pela qual você deve apenas outra função, a menos que haja uma necessidade específica de fechamento.
Trabalhando em equipe / Design de cima para baixo
As subtarefas podem ser escritas por pessoas diferentes, independentemente, se necessário.
Mesmo você mesmo, pode ser útil ao escrever código para simplesmente chamar alguma subtarefa que ainda não existe, ao criar a funcionalidade principal e se preocupar em realmente implementar a subtarefa somente depois que você souber que obterá os resultados necessários em um maneira significativa. Isso também é chamado de design / programação de cima para baixo.
Reutilização de código
Ok, apesar do que eu disse anteriormente, às vezes, na verdade, acaba havendo uma razão para reutilizar uma subtarefa para outra coisa. Não estou de todo defendendo o isismo "astronauta da arquitetura", mas apenas que, ao escrever código pouco acoplado, você pode acabar se beneficiando mais tarde da reutilização.
Muitas vezes, essa reutilização significa refatoração, o que é perfeitamente esperado, mas refatorar os parâmetros de entrada para uma função autônoma pequena é MUITO mais fácil do que extraí-lo de mais de 200 funções de linha meses após a gravação, o que é realmente o meu ponto aqui.
Se você usar uma função aninhada, reutilizá-la geralmente é uma questão de refatorar para uma função separada, e, novamente, é por isso que eu argumentaria que aninhado não é o caminho a seguir.