Muitas vezes, escrevi esse tipo de função nos dois formatos, e fiquei pensando se um formato é preferido em relação a outro e por quê.
public void SomeFunction(bool someCondition)
{
if (someCondition)
{
// Do Something
}
}
ou
public void SomeFunction(bool someCondition)
{
if (!someCondition)
return;
// Do Something
}
Normalmente, codigo com o primeiro, pois é assim que meu cérebro funciona durante a codificação, embora eu prefira o segundo, pois cuida de qualquer tratamento de erro imediatamente e acho mais fácil ler
Respostas:
Eu prefiro o segundo estilo. Tire os casos inválidos primeiro, simplesmente saindo ou criando exceções, conforme apropriado, coloque uma linha em branco e adicione o corpo "real" do método. Acho mais fácil ler.
fonte
Definitivamente o último. O primeiro não parece ruim no momento, mas quando você obtém um código mais complexo, não consigo imaginar que alguém pensaria isso:
é mais legível do que
Admito plenamente que nunca entendi a vantagem de pontos de saída únicos.
fonte
return value;
ajuda!?! Então é preciso caçar meia dúziavalue = ...
, com a desvantagem de que você nunca tem certeza de que o valor não será alterado entre essa tarefa e o retorno final. Pelo menos um retorno imediato é claro que nada mudará mais o resultado.Depende - em geral, não vou me esforçar para tentar mover um monte de código para interromper a função mais cedo - o compilador geralmente cuidará disso para mim. Dito isto, porém, se houver alguns parâmetros básicos no topo que eu preciso e não puder continuar de outra forma, vou me libertar mais cedo. Da mesma forma, se uma condição gerar um
if
bloco gigante em função, também terei seu rompimento mais cedo.Dito isso, se uma função exigir alguns dados quando for chamada, geralmente lançarei uma exceção (veja o exemplo) em vez de apenas retornar.
fonte
Eu prefiro o retorno antecipado.
Se você tem um ponto de entrada e um ponto de saída, sempre precisa rastrear todo o código em sua cabeça até o ponto de saída (você nunca sabe se algum outro pedaço de código abaixo faz outra coisa com o resultado, então você tem que rastreá-lo até o existir). Você faz isso, não importa qual ramo determina o resultado final. Isso é difícil de seguir.
Com uma entrada e várias, você retorna quando obtém o resultado e não se incomoda em rastreá-lo até o fim para ver que ninguém faz mais nada (porque não haverá mais nada desde que você retornou). É como dividir o corpo do método em mais etapas, cada uma com a possibilidade de retornar o resultado ou deixar a próxima etapa tentar a sorte.
fonte
Na programação C, em que é necessário limpar manualmente, há muito a ser dito para o retorno em um ponto. Mesmo que agora não haja necessidade de limpar algo, alguém pode editar sua função, alocar algo e precisar limpá-lo antes de retornar. Se isso acontecer, será um trabalho de pesadelo examinar todas as declarações de retorno.
Na programação C ++, você tem destruidores e até agora guardas de saída de escopo. Tudo isso precisa estar aqui para garantir que o código seja protegido contra exceções em primeiro lugar, para que o código seja bem protegido contra saída antecipada e, portanto, isso não tem desvantagem lógica e é puramente um problema de estilo.
Eu não tenho conhecimento suficiente sobre Java, se o código de bloco "finalmente" será chamado e se os finalizadores podem lidar com a situação de necessidade de garantir que algo aconteça.
C # Eu certamente não posso responder.
A linguagem D fornece protetores de saída de escopo internos adequados e, portanto, está bem preparada para saída antecipada e, portanto, não deve apresentar outro problema além do estilo.
Obviamente, as funções não devem demorar tanto tempo e, se você tiver uma declaração enorme de switch, seu código provavelmente também será mal considerado.
fonte
goto
e, possivelmente, um retorno de dois pontos. Exemplo (formatação de código não é possível nos comentários):foo() { init(); if (bad) goto err; bar(); if (bad) goto err; baz(); return 0; err: cleanup(); return 1; }
Retornos antecipados para ganhar. Eles podem parecer feios, mas muito menos feios do que
if
embalagens grandes , especialmente se houver várias condições para verificar.fonte
Eu uso os dois.
Se
DoSomething
houver 3-5 linhas de código, o código ficará bonito usando o primeiro método de formatação.Mas se tiver muito mais linhas do que isso, prefiro o segundo formato. Não gosto quando os colchetes de abertura e fechamento não estão na mesma tela.
fonte
Um motivo clássico para uma única entrada e uma saída é que, de outro modo, a semântica formal se torna indescritivelmente feia (caso contrário, o GOTO foi considerado prejudicial).
Em outras palavras, é mais fácil pensar em quando seu software sairá da rotina se você tiver apenas 1 retorno. O que também é um argumento contra exceções.
Normalmente, minimizo a abordagem de retorno antecipado.
fonte
Pessoalmente, prefiro fazer verificações de condições de aprovação / reprovação no início. Isso permite que eu agrupe a maioria das falhas mais comuns na parte superior da função com o restante da lógica a seguir.
fonte
Depende.
Retorno antecipado, se houver alguma condição óbvia de beco sem saída para verificar imediatamente, o que tornaria inútil a execução do restante da função. *
Defina Retval + retorno único se a função for mais complexa e, caso contrário, poderia ter vários pontos de saída (problema de legibilidade).
* Isso geralmente pode indicar um problema de design. Se você achar que muitos dos seus métodos precisam verificar algum estado externo / paramater ou algo semelhante antes de executar o restante do código, isso provavelmente é algo que deve ser tratado pelo chamador.
fonte
Fred
da janela já estaráFred
e definir o nome do controle para seu estado atual forçaria um redesenho (o que, embora potencialmente útil em alguns casos, seria irritante no caso), seria perfeitamente razoável que o método set-name saia antecipadamente se os nomes antigo e novo corresponderem.Use um If
No livro de Don Knuth sobre os GOTO, li-o dar uma razão para sempre ter a condição mais provável em primeiro lugar em uma declaração if. Partindo do pressuposto de que essa ainda é uma idéia razoável (e não por pura consideração pela velocidade da época). Eu diria que retornos antecipados não são uma boa prática de programação, especialmente considerando o fato de que eles costumam ser usados para tratamento de erros, a menos que seu código tenha mais probabilidade de falhar do que não falhar :-)
Se você seguir o conselho acima, precisará colocar esse retorno na parte inferior da função e, em seguida, é melhor nem chamá-lo de retorno lá, basta definir o código de erro e, em seguida, retornar duas linhas. Conseguindo assim a 1 entrada 1 saída ideal.
Delphi Specific ...
Sou de opinião que essa é uma boa prática de programação para programadores Delphi, embora eu não tenha nenhuma prova. Antes do D2009, não temos uma maneira atômica de retornar um valor, temos
exit;
e /result := foo;
ou poderíamos simplesmente lançar exceções.Se você tivesse que substituir
para
você pode ficar cansado de ver isso no topo de todas as suas funções e preferir
e apenas evite
exit
completamente.fonte
if true then Exit(foo);
eu uso muitas vezes a técnica de primeira inicializarresult
anil
ouFALSE
, respectivamente, em seguida, verificar todas as condições de erro e apenasExit;
se for atendida. O caso de sucessoresult
é então (normalmente) definido em algum lugar no final do método.Eu concordo com a seguinte declaração:
Retirado desta pergunta no stackoverflow .
fonte
Eu uso retornos antecipados quase exclusivamente nos dias de hoje, ao extremo. Eu escrevo isso
Como
mas isso realmente não importa. Se você tiver mais de um ou dois níveis de aninhamento em suas funções, eles precisam ser eliminados.
fonte
Eu preferiria escrever:
fonte
DoSomeFunctionIfSomeCondition
?Como você, eu costumo escrever o primeiro, mas prefiro o último. Se eu tiver muitas verificações aninhadas, geralmente refatoro para o segundo método.
Não gosto de como a manipulação de erros é afastada da verificação.
Eu prefiro isso:
fonte
As condições no topo são chamadas "pré-condições". Ao colocar
if(!precond) return;
, você visualiza todas as pré-condições.Usar o bloco "if-else" grande pode aumentar a sobrecarga do recuo (esqueci a citação sobre recuos de três níveis).
fonte
Eu prefiro manter as declarações se pequenas.
Então, escolhendo entre:
e
Eu escolheria o que você descreveu como "retorno antecipado".
Lembre-se, eu não me importo com retornos antecipados ou o que seja, eu realmente gosto de simplificar o código, encurtar os corpos das declarações if etc.
Aninhados se e para e enquanto são horríveis , evite-os a todo custo.
fonte
Como outros dizem, isso depende. Para pequenas funções que retornam valores, posso codificar retornos antecipados. Mas, para funções importantes, eu sempre gosto de ter um lugar no código onde sei que posso colocar algo que será executado antes que ele retorne.
fonte
Eu pratico fail-fast no nível da função. Mantém o código consistente e limpo (para mim e para aqueles com quem trabalhei). Por isso, eu sempre volto cedo.
Para algumas condições frequentemente verificadas, você pode implementar aspectos dessas verificações se usar o AOP.
fonte