Às vezes me deparei com um código semelhante ao exemplo a seguir (o que essa função faz exatamente está fora do escopo desta pergunta):
function doSomething(value) {
if (check1(value)) {
return -1;
}
else if (check2(value)) {
return value;
}
else {
return false;
}
}
Como você pode ver, if
, else if
e else
instruções são utilizados em conjunto com o return
comunicado. Isso parece bastante intuitivo para um observador casual, mas acho que seria mais elegante (da perspectiva de um desenvolvedor de software) descartar o else
-s e simplificar o código da seguinte forma:
function doSomething(value) {
if (check1(value)) {
return -1;
}
if (check2(value)) {
return value;
}
return false;
}
Isso faz sentido, pois tudo o que segue uma return
instrução (no mesmo escopo) nunca será executado, tornando o código acima semanticamente igual ao primeiro exemplo.
Qual das opções acima se encaixa mais nas boas práticas de codificação? Existem desvantagens em qualquer método no que diz respeito à legibilidade do código?
Editar: Uma sugestão duplicada foi feita com esta pergunta fornecida como referência. Acredito que minha pergunta aborda um tópico diferente, pois não estou perguntando sobre evitar declarações duplicadas, como apresentado na outra pergunta. Ambas as questões buscam reduzir as repetições, embora de maneiras ligeiramente diferentes.
fonte
else
é menor, o problema maior é que você obviamente está retornando dois tipos de dados de uma única função, o que torna a API da função imprevisível.-1
é um número,false
é um booleano evalue
não é especificado aqui, portanto, pode ser qualquer tipo de objeto.value
verdade fosse um número inteiro. Se pode ser qualquer coisa, então é ainda pior.Respostas:
Eu gosto do que está sem
else
e aqui está o porquê:Porque fazer isso não quebrou nada que não deveria.
Odeie a interdependência em todas as suas formas (incluindo nomear uma função
check2()
). Isole tudo o que pode ser isolado. Às vezes você precisa,else
mas eu não vejo isso aqui.fonte
if
bloco} //else
para deixar claro, ao ler o código, que a única execução pretendida após oif
bloco de código é se a condição naif
instrução for falsa. Sem algo assim, especialmente se o código dentro doif
bloco se tornar mais complexo, pode não estar claro para quem está mantendo o código que a intenção era nunca executar além doif
bloco quando aif
condição for verdadeira.if
para deixar claro que esta seção do código está concluída e a estrutura concluída. Para fazer isso, faço o que não fiz aqui (porque não queria me distrair do ponto principal do OP fazendo outras alterações). Faço a coisa mais simples possível que consegue tudo isso sem se distrair. Eu adiciono uma linha em branco.Eu acho que depende da semântica do código. Se seus três casos dependem um do outro, indique-o explicitamente. Isso aumenta a legibilidade do código e facilita o entendimento para qualquer outra pessoa. Exemplo:
Aqui você está claramente dependendo do valor de
x
todos os três casos. Se você omitir o últimoelse
, isso seria menos claro.Se seus casos não dependem diretamente um do outro, omita-o:
É difícil mostrar isso em um exemplo simples, sem contexto, mas espero que você entenda meu ponto de vista.
fonte
Eu prefiro a segunda opção (separada
ifs
com noelse if
e earlyreturn
), MAS é contanto que os blocos de código sejam curtos .Se os blocos de código são longos, é melhor usar
else if
, porque, de outro modo, você não entenderia claramente os vários pontos de saída que o código possui.Por exemplo:
Nesse caso, é melhor usar
else if
, armazenar o código de retorno em uma variável e ter apenas uma frase de retorno no final.Mas, como alguém deve se esforçar para que as funções sejam curtas, eu diria que seja curta e saia mais cedo, como no seu primeiro trecho de código.
fonte
return
está dentro de 3 linhasif
ou menos,else if
mesmo depois de 200 linhas de código. O estilo de retorno único que você introduz aqui é uma tradição de c e outros idiomas que não relatam erros com exceções. O objetivo era criar um único local para limpar recursos. Os idiomas de exceção usam umfinally
bloco para isso. Suponho que isso também crie um local para colocar um ponto de interrupção se o depurador não permitir que você coloque um nas funções que fecham a chave.retVal
. Se você puder sair com segurança de uma função, faça-o imediatamente, sem atribuir o valor seguro a ser retornado a uma variável de uma única saída da função. Quando você usa o ponto de retorno único em uma função realmente longa, geralmente não confio em outros programadores e acabo procurando no restante da função por outras modificações no valor de retorno. Falhar rápido e voltar cedo são, entre outras, duas regras pelas quais eu vivo.Eu uso os dois em diferentes circunstâncias. Em uma verificação de validação, eu omito o resto. Em um fluxo de controle, eu uso o else.
vs
O primeiro caso parece mais como se você estivesse verificando todos os pré-requisitos primeiro, tirando-os do caminho e depois progredindo para o código real que deseja executar. Como tal, o código interessante que você realmente deseja executar pertence diretamente ao escopo da função; é sobre o que realmente trata a função.
O segundo caso é mais parecido com os dois caminhos: um código válido a ser executado que é tão relevante para a função quanto o outro com base em alguma condição. Como tal, eles pertencem em níveis de escopo semelhantes entre si.
fonte
A única situação que eu já vi realmente importa é um código como este:
Há claramente algo errado aqui. O problema é que não está claro se
return
deve ser adicionado ouArrays.asList
removido. Você não pode corrigir isso sem uma inspeção mais profunda dos métodos relacionados. Você pode evitar essa ambiguidade usando sempre blocos se-else totalmente exaustivos. Este:não será compilado (em idiomas verificados estaticamente), a menos que você adicione retorno explícito primeiro
if
.Alguns idiomas nem permitem o primeiro estilo. Eu tento usá-lo apenas em um contexto estritamente imperativo ou para pré-condições em métodos longos:
fonte
Ter três saídas da função assim é realmente confuso se você estiver tentando seguir o código e praticar mal.
Se você tiver um único ponto de saída para a função, os outros serão necessários.
De fato, vamos ainda mais longe.
É justo que você possa argumentar sobre um único retorno antecipado da validação de entrada. Apenas evite agrupar todo o lote se sua lógica for um if.
fonte
Eu prefiro omitir a declaração else redundante. Sempre que o vejo (na revisão ou refatoração de código), pergunto-me se o autor entendeu o fluxo de controle e se pode haver um erro no código.
Se o autor acreditava que a declaração else era necessária e, portanto, não entendia as implicações do fluxo de controle da declaração de retorno, certamente essa falta de entendimento é a principal fonte de erros, nessa função e em geral.
fonte