Muitas vezes me deparei com erros que foram causados pelo uso da ELSE
construção. Um excelente exemplo é algo como:
If (passwordCheck() == false){
displayMessage();
}else{
letThemIn();
}
Para mim, isso grita um problema de segurança. Sei que o passwordCheck provavelmente será um booleano, mas não colocaria a segurança dos meus aplicativos nele. O que aconteceria se fosse uma string, int etc?
Normalmente, tento evitar o uso ELSE
e, em vez disso, opto por duas instruções IF completamente separadas para testar o que espero. Qualquer outra coisa que seja ignorada OU será tratada especificamente.
Certamente, essa é a melhor maneira de impedir que bugs / problemas de segurança entrem no seu aplicativo.
Como vocês fazem isso?
self-improvement
programming-practices
security
billy.bob
fonte
fonte
I know that passwordCheck is likely to be a boolean...
O que você quer dizer? Em qualquer linguagem de tipo forte.passwordCheck
será o que você quiser que seja.else
declarações ...passwordCheck()
não ser booleano (o que pode ser uma preocupação razoável) e depois o culpaelse
? Não vejo que problemas aselse
causas.Respostas:
O
else
bloco deve sempre consistir no que você deseja que seja o comportamento padrão.Não há necessidade de evitá-los, apenas tome cuidado para usá-los adequadamente.
No seu exemplo, o estado padrão deve ser o de não permitir acesso. Um pouco de refatoração deixa você com:
ou seja, se a verificação da senha funcionar, deixe-os entrar, caso contrário, é sempre válido mostrar alguma mensagem de erro.
Obviamente, você pode adicionar verificações adicionais à sua lógica usando instruções em
else if
vez deif
instruções completamente separadas .fonte
passwordCheck
pode ser qualquer coisa, fenull
, o que tornariapasswordCheck == false
afalse
e que o usuário deixe de login devido a um erro interno.if
requer umbool
, variáveis devem ser definitivamente atribuída, todos os caminhos deve retornar um valor, etc., eu não consigo pensar em qualquer motivo, a ordem deif
eelse
importaria além legibilidade. Ou seja,if(a){b();}{c();}
deve ser equivalente aif(!a){c();{b();}
. Em JavaScript, por outro lado, você deve estar ciente de quepasswordCheck
pode serundefined
etc.Não, não há nada errado
ELSE
.ELSE
não é novoGOTO
. De fato, usar doisIF
s em vez deELSE
pode levar a vários problemas.Exemplo um:
Você vê a copiar e colar? Apenas espera o dia em que você muda um e esquece o outro.
Exemplo dois:
Como você pode ver, o segundo
IF
também será executado para o primeiro item, porque a condição já foi alterada. Nos programas do mundo real, esses erros são mais difíceis de detectar.fonte
if
instrução e inverter sua expressão booleana apenas para evitar umaelse
- agora que é uma programação ruim! Não só você está duplicação de código ( má programação), você também está a abrandar o desempenho (se o cheque é realmente complicado, você está agora a fazê-lo duas vezes - ba-- uh, bem, você sabe o que eles dizem sobre otimizações prematuras hoje em dia ... não é tão boa programação!).Sempre há um ELSE. Se você escrever
você realmente escreve
Tudo o que você colocar no caminho ELSE é de sua responsabilidade.
fonte
Pessoalmente, costumo evitar
else
o máximo que posso, mas não é para qualquer problema de segurança .Ao ler o código, instruções aninhadas tornam mais difícil seguir a lógica, porque você precisa lembrar qual conjunto de condições levará até lá. Por esse motivo, sou um grande fã de saída antecipada:
Isto também se aplica
for
ewhile
laços em que vou usarcontinue
ebreak
sempre que evita um nível de recuo.Chris Lattner diz isso melhor do que eu nos padrões de codificação LLVM .
fonte
*writes an answer*
Em seguida, basta substituí-los,
fonte
If ((passwordCheck == true) == true)
? :-)Como Matthieu M., prefiro a saída antecipada a outros blocos profundamente aninhados ... Ilustra uma programação bem defensiva (se más condições, não há motivo para continuar). Muitas pessoas discordam de nós, preferindo um ponto de saída único; não é o objetivo do debate (eu acho).
Agora, eu certamente uso
else
quando faz sentido, particularmente para alternativas simples e curtas. Como dito, duplicar o teste é uma perda de tempo (programadores e CPU), uma fonte de confusão e, posteriormente, de bugs (quando um é alterado, não o outro).Em algum momento, adiciono um comentário à
else
peça, lembrando qual era a condição (principalmente se aif
peça é longa, por exemplo, no código legado) ou qual é a alternativa.Observe que alguns defensores extremos da programação funcional se propõem a se livrar inteiramente
if
, em favor da correspondência de padrões ... Um pouco extremo demais para o meu gosto. :-)fonte
Não há nada de errado em usar o ELSE. No entanto, pode levar a códigos excessivamente complexos que são difíceis de ler e entender. Isso pode indicar um design incorreto. Certamente indica casos de uso adicionais que precisarão ser testados.
Tente remover os ELSEs, se puder - mas não fique paranóico com isso. Steve McConnell chama esse código de linha reta no Code Complete. Ou seja, existe um caminho claro e simples através do seu código.
Abordagens para tentar o seu problema específico:
Em geral - o seguinte pode ajudar a reduzir os ELSEs no seu código:
fonte
Sua suposição de que o código é um vazamento de segurança pode ou não ser verdadeira dependendo do idioma que você está usando. No código C, pode ser um problema (principalmente porque em C um booleano é apenas um int que não é zero ou zero) - mas nas linguagens mais fortemente tipadas (ou seja, verificação do tipo de tempo de execução) se a
passwordCheck
variável foi declarada como booleana, não há como atribuir outra coisa a ele. De fato, tudo em umif
predicado deve resolver para um booleano, se você usa os operadores booleanos ou simplesmente usa o valor. Se você conseguisse ter outro tipo de objeto vinculado aopasswordCheck
tempo de execução, lançaria algum tipo de exceção de conversão ilegal.Construções simples if / else são muito mais fáceis de ler do que construções if / if - e menos propensas a problemas inadvertidos se alguém tentar inverter a construção. Vamos dar o mesmo exemplo por um segundo:
O significado das cláusulas mutuamente exclusivas que você deseja executar acima está perdido. É isso que a construção if / else transmite. Dois ramos de execução mutuamente exclusivos, onde um deles sempre será executado. Essa é uma parte importante da segurança - garantindo que não haja como
letThemIn
fazê-lo após a ligaçãodenyAccess
.Para fins de clareza do código e para garantir que as seções críticas sejam mais protegidas, elas devem estar dentro da cláusula primária (a
if
parte). O comportamento padrão não conforme deve estar na cláusula alternativa (aelse
parte). Por exemplo:NOTA: ao trabalhar com idiomas diferentes, desenvolvi um habbit de codificação que ajuda a evitar a pergunta "e se for uma string?" Essencialmente, é colocar a constante em primeiro lugar na expressão booleana. Por exemplo, em vez de verificar
passwordCheck == false
, estou verificandofalse == passwordCheck
. Isso também evita o problema de atribuição acidental possível em C ++. Usando essa abordagem, o compilador reclamará se eu digitar=
vez de==
. Em linguagens como Java e C #, o compilador trataria a atribuição na cláusula if como um erro, mas o C ++ aceitará com satisfação. É por isso que também costumo fazer verificação nula com anull
primeira.Se você muda rotineiramente os idiomas, colocar a constante em primeiro lugar é muito útil. No entanto, na minha equipe, é oposto ao padrão de codificação e o compilador captura esses problemas de qualquer maneira. Pode ser um hábito difícil de quebrar.
fonte
Dizer que usar
else
quando programar é ruim é como dizer que usarotherwise
quando falar é ruim.Claro, os dois podem ser usados de maneiras ruins, mas isso não significa que eles devam ser evitados apenas porque você cometeu um erro que os incluiu. Eu não ficaria surpreso se muitos erros dependessem de um
default
caso ausente em umaswitch
declaração.fonte
Pense
Else
na lista branca de seu fluxo de aplicativos. Você verifica as condições que DEVEM permitir que o fluxo do aplicativo continue, e se elas não forem atendidas, o seuElse
será executado para resolver o problema, interromper a execução do aplicativo ou algo semelhante.Else
por si só não é ruim, mas se você o usar mal, poderá ver efeitos indesejados.Além disso, em relação à sua declaração sobre
"Eu sei que o passwordCheck provavelmente será um booleano, mas eu não colocaria a segurança dos meus aplicativos nele."
Para métodos desenvolvidos, SEMPRE retorne um tipo de dados. Embora o PHP Core esteja repleto de códigos que retornam dois ou mais tipos de dados, essa é uma prática ruim, pois adivinha as chamadas de função. Se você precisar retornar mais de um tipo de dados, considere lançar uma exceção (acho que esse é o motivo pelo qual eu gostaria de retornar outro tipo de dados - algo deu horrivelmente, muito errado) ou considere reestruturar seu código para que você possa retorna apenas um tipo de dados.
fonte
Em primeiro lugar. RI MUITO! Não há motivo para evitar mais nada. NÃO é uma má prática, seja de que forma for.
Se alguma coisa o código deve ser
Não há dois ifs lá e ele não tem mais. É isso que faço em todos os meus aplicativos, exceto um no qual lancei uma exceção. A exceção é capturada na minha função, que verifica o URL da página apropriada a ser exibida (ou, alternativamente, eu posso colocar a função catch / check na função de erro asp.net). Ele imprime uma página genérica que diz não autorizar ou qualquer mensagem que eu use na exceção (eu sempre verifico o tipo de exceção e defino o código de status http).
-Editar- como mostrado no exemplo de muniçãoQ dois ifs é ridículo. Realmente o resto é tão bom ou melhor que um if. Se alguma coisa for evitada (embora eu pessoalmente não. Mas eu uso muito retorno e quebrei), como já foi dito, mais caminhos de código aumentam a probabilidade de erros. Vejo Complexidade Ciclomática
-Editar 2- Se você está preocupado com o uso if / else. Também observarei que minha preferência é colocar o bloco de código mais curto no topo, como
Pelo contrário,
fonte
Eu gosto de definir um padrão antes das condicionais quando posso. Sinto que é um pouco mais fácil de ler e um pouco mais explícito, mas isso é apenas uma preferência. Eu tenho uma tendência a tentar evitar condições negativas no meu código. Não sou muito fã de procurar! Foo ou false == foo e sinto que o resto é meio equivalente condicional a um negativo.
ao invés de ...
O bloco de código anterior parece um pouco mais fácil para eu ler. Parece-me mais natural ter uma espécie de paranóia cética sobre o meu código. Definir um padrão independentemente de qualquer condição me faz sentir confortável: P
fonte
Eu argumentaria que o uso de lógica de ramificação de qualquer tipo deve ser evitado o máximo possível. Embora nada esteja errado com ELSE ou IF, existem várias maneiras de escrever código para minimizar a necessidade de usar qualquer lógica de ramificação. Não estou dizendo que a lógica de ramificação possa ser totalmente eliminada - será necessária em alguns lugares - mas é possível refatorar o código para eliminar uma boa parte dela. Na maioria dos casos, isso melhorará a inteligibilidade e a precisão do seu código.
Como exemplo, os operadores ternários também são geralmente bons candidatos:
Usando uma abordagem ternária:
Os operadores ternários deslocam a ramificação para a direita em um bom caminho.
fonte