Sempre ouvi falar de uma função de ponto de saída único como uma maneira ruim de codificar porque você perde capacidade de leitura e eficiência. Nunca ouvi ninguém argumentar do outro lado.
Achei que isso tivesse algo a ver com CS, mas essa questão foi descartada em cstheory stackexchange.
coding-style
hex bob-omb
fonte
fonte
Respostas:
Existem diferentes escolas de pensamento, e em grande parte se resume à preferência pessoal.
Uma é que é menos confuso se houver apenas um único ponto de saída - você tem um único caminho através do método e sabe onde procurar a saída. No lado negativo, se você usar indentação para representar aninhamento, seu código acabará recuado massivamente para a direita e se tornará muito difícil seguir todos os escopos aninhados.
Outra é que você pode verificar as pré-condições e sair mais cedo no início de um método, de modo que saiba no corpo do método que certas condições são verdadeiras, sem que todo o corpo do método seja recuado 5 milhas para a direita. Isso geralmente minimiza o número de escopos com os quais você precisa se preocupar, o que torna o código muito mais fácil de seguir.
Uma terceira é que você pode sair de onde quiser. Isso costumava ser mais confuso no passado, mas agora que temos editores e compiladores para colorir sintaxe que detectam código inacessível, é muito mais fácil lidar com ele.
Estou exatamente no meio do campo. Impor um único ponto de saída é uma restrição IMHO inútil ou mesmo contraproducente, enquanto sair aleatoriamente em um método pode às vezes levar a uma lógica complicada e difícil de seguir, onde se torna difícil ver se um determinado pedaço de código será ou não executado. Mas "bloquear" o seu método torna possível simplificar significativamente o corpo do método.
fonte
singe exit
paradigma por meio dego to
declarações. Além disso, tem-se a oportunidade de realizar algum pós-processamento sob oError
rótulo local da função , o que é impossível com váriosreturn
s.Minha recomendação geral é que as instruções de retorno devem, quando possível, ser localizadas antes do primeiro código que tem efeitos colaterais ou depois do último código que tem efeitos colaterais. Eu consideraria algo como:
mais claro que:
Se uma determinada condição deve impedir uma função de fazer qualquer coisa, prefiro retornar antes da função em um ponto acima do ponto onde a função faria qualquer coisa. Uma vez que a função tenha empreendido ações com efeitos colaterais, porém, prefiro voltar do fundo, para deixar claro que todos os efeitos colaterais devem ser tratados.
fonte
ok
variável, parece a abordagem de retorno único para mim. Além disso, o bloco if-else pode ser simplesmente reescrito para:return ok ? 0 : ERR_NOT_OK;
return
no início antes de todo o código que faz tudo. Quanto ao uso do?:
operador, escrevê-lo em linhas separadas torna mais fácil em muitos IDEs anexar um ponto de interrupção de depuração ao cenário não ok. BTW, a verdadeira chave para "único ponto de saída" está em entender que o que importa é que para cada chamada específica para uma função normal, o ponto de saída é o ponto imediatamente após a chamada . Os programadores hoje em dia consideram isso normal, mas as coisas nem sempre foram assim. Em alguns casos raros, o código pode ter que sobreviver sem espaço de pilha, levando a funções ...Um único ponto de entrada e saída era o conceito original de programação estruturada vs Spaghetti Coding passo a passo. Acredita-se que múltiplas funções de ponto de saída requerem mais código, uma vez que é necessário limpar adequadamente os espaços de memória alocados para as variáveis. Considere um cenário em que a função aloca variáveis (recursos) e sair da função mais cedo e sem a limpeza adequada resultaria em vazamentos de recursos. Além disso, construir uma limpeza antes de cada saída criaria uma grande quantidade de código redundante.
fonte
Com quase tudo, tudo se resume às necessidades do produto final. Nos "velhos tempos", o código espaguete com vários pontos de retorno provocava vazamentos de memória, já que os programadores que preferiam esse método normalmente não faziam uma boa limpeza. Também houve problemas com alguns compiladores "perdendo" a referência à variável de retorno quando a pilha foi estourada durante o retorno, no caso de retornar de um escopo aninhado. O problema mais geral era o do código reentrante, que tenta fazer com que o estado de chamada de uma função seja exatamente o mesmo que seu estado de retorno. Mutadores de oop violaram isso e o conceito foi arquivado.
Existem produtos, principalmente kernels, que precisam da velocidade que vários pontos de saída fornecem. Esses ambientes normalmente têm sua própria memória e gerenciamento de processos, de modo que o risco de vazamento é minimizado.
Pessoalmente, gosto de ter um único ponto de saída, já que costumo usá-lo para inserir um ponto de interrupção na instrução de retorno e executar uma inspeção de código de como o código determinou essa solução. Eu poderia simplesmente ir até a entrada e passar, o que faço com soluções extensivamente aninhadas e recursivas. Como revisor de código, vários retornos em uma função requerem uma análise muito mais profunda - portanto, se você está fazendo isso para acelerar a implementação, está roubando Peter para salvar Paul. Mais tempo será necessário nas revisões de código, invalidando a presunção de implementação eficiente.
- 2 centavos
Consulte este documento para obter mais detalhes: NISTIR 5459
fonte
multiple returns in a function requires a much deeper analysis
apenas se a função já for enorme (> 1 tela), caso contrário, torna a análise mais fácilEm minha opinião, o conselho para sair de uma função (ou outra estrutura de controle) em apenas um ponto muitas vezes é exagerado. Normalmente, são apresentados dois motivos para sair em apenas um ponto:
O segundo motivo é sutil e tem algum mérito, especialmente se a função retornar uma grande estrutura de dados. No entanto, eu não me preocuparia muito com isso, exceto ...
Se for aluno, você deseja obter as melhores notas em sua classe. Faça o que o instrutor preferir. Ele provavelmente tem um bom motivo de sua perspectiva; então, no mínimo, você aprenderá sua perspectiva. Isso tem valor em si.
Boa sorte.
fonte
Eu costumava ser um defensor do estilo de saída única. Meu raciocínio veio principalmente da dor ...
A saída única é mais fácil de depurar.
Dadas as técnicas e ferramentas que temos hoje, essa é uma posição muito menos razoável de se tomar, pois os testes de unidade e o registro podem tornar a saída única desnecessária. Dito isso, quando você precisa observar a execução do código em um depurador, é muito mais difícil entender e trabalhar com o código que contém vários pontos de saída.
Isso se tornou especialmente verdadeiro quando você precisava interpor atribuições para examinar o estado (substituído por expressões de observação em depuradores modernos). Também era muito fácil alterar o fluxo de controle de maneiras que ocultassem o problema ou interrompessem totalmente a execução.
Os métodos de saída única eram mais fáceis de percorrer no depurador e mais fáceis de separar sem quebrar a lógica.
fonte
A resposta depende muito do contexto. Se você estiver fazendo uma GUI e tiver uma função que inicializa APIs e abre janelas no início de sua principal, ela estará cheia de chamadas que podem lançar erros, cada um dos quais faria com que a instância do programa fosse fechada. Se você usasse instruções IF aninhadas e indentasse, seu código poderia rapidamente ficar muito inclinado para a direita. Retornar um erro em cada estágio pode ser melhor e realmente mais legível, além de ser igualmente fácil de depurar com alguns sinalizadores no código.
Se, entretanto, você estiver testando condições diferentes e retornando valores diferentes dependendo dos resultados em seu método, pode ser uma prática muito melhor ter um único ponto de saída. Eu costumava trabalhar com scripts de processamento de imagens no MATLAB, que podiam ficar muito grandes. Vários pontos de saída podem tornar o código extremamente difícil de seguir. As declarações switch eram muito mais apropriadas.
A melhor coisa a fazer seria aprender conforme você avança. Se você está escrevendo código para algo, tente encontrar o código de outras pessoas e ver como elas o implementam. Decida quais partes você gosta e quais não gosta.
fonte
Se você sentir que precisa de vários pontos de saída em uma função, a função é muito grande e está executando muito.
Eu recomendaria a leitura do capítulo sobre funções no livro de Robert C. Martin, Clean Code.
Essencialmente, você deve tentar escrever funções com 4 linhas de código ou menos.
Algumas notas do blog de Mike Long :
fonte