Nossa organização possui uma regra de codificação necessária (sem qualquer explicação) que:
if… else se construções devem ser finalizadas com uma cláusula else
Exemplo 1:
if ( x < 0 )
{
x = 0;
} /* else not needed */
Exemplo 2:
if ( x < 0 )
{
x = 0;
}
else if ( y < 0 )
{
x = 3;
}
else /* this else clause is required, even if the */
{ /* programmer expects this will never be reached */
/* no change in value of x */
}
Que case de borda é projetado para lidar com isso?
O que também me preocupa sobre o motivo é que o Exemplo 1 não precisa de um, else
mas o Exemplo 2 precisa. Se o motivo é a reutilização e a extensibilidade, acho que else
deve ser usado nos dois casos.
assert(false, "should never go here")
pode fazer sentidoif (x < 0) { x = 0; } else { if (y < 0) { x = 3; }}
. Ou você pode simplesmente seguir essas regras, muitas das quais são tolas, simplesmente porque você é obrigado.< 0
verificações), para que a afirmação continue travar o programa no que provavelmente é o caso mais comum em que os valores estão dentro dos limites esperados.Respostas:
Como mencionado em outra resposta, isso é das diretrizes de codificação MISRA-C. O objetivo é a programação defensiva, um conceito que é frequentemente usado na programação de missão crítica.
Ou seja, todo mundo
if - else if
deve terminar com umelse
, e todo mundoswitch
deve terminar com umdefault
.Há duas razões para isso:
Código de auto-documentação. Se você escreve um,
else
mas o deixa vazio, significa: "Definitivamente, considerei o cenário em que nemif
nemelse if
são verdadeiros".Não escrever um
else
lá significa: "ou considerei o cenário em que nemif
nemelse if
somos verdadeiros, ou esqueci completamente de considerá-lo e há potencialmente um bug gordo aqui no meu código".Pare o código descontrolado. No software de missão crítica, você precisa escrever programas robustos que respondem até pelo altamente improvável. Então você pode ver código como
Esse código será completamente estranho para programadores de PC e cientistas da computação, mas faz todo o sentido em software de missão crítica, porque identifica o caso em que o "mybool" foi corrompido, por qualquer motivo.
Historicamente, você temeria a corrupção da memória RAM devido a EMI / ruído. Hoje isso não é grande coisa. Muito provavelmente, a corrupção de memória ocorre devido a erros em outras partes do código: ponteiros para locais errados, erros de array fora dos limites, excesso de pilha, código descontrolado etc.
Portanto, na maioria das vezes, um código como esse volta para dar um tapa na cara quando você escreve bugs durante o estágio de implementação. Isso significa que também pode ser usado como uma técnica de depuração: o programa que você está escrevendo informa quando você escreve bugs.
EDITAR
Quanto ao porquê
else
não é necessário depois de cada umif
:Um
if-else
ouif-else if-else
abrange completamente todos os valores possíveis que uma variável pode ter. Mas umaif
declaração simples não está necessariamente lá para cobrir todos os valores possíveis, ela tem um uso muito mais amplo. Na maioria das vezes você só deseja verificar uma determinada condição e, se não for atendida, não faça nada. Simplesmente não faz sentido escrever uma programação defensiva para cobrir oelse
caso.Além disso, ele iria desordenar completamente o código se você escrevesse um vazio
else
depois de cada umif
.MISRA-C: 2012 15.7 não explica por que
else
não é necessário, apenas afirma:fonte
if/else if/else
compilado com o que você espera? E mais uma para verificar o verificador anterior também?mybool
tenha um tipo não-booleano, como era o caso antes de C ter o seu própriobool
; então o compilador não faria a suposição sem análise estática adicional). E sobre o assunto 'Se você escreve um outro, mas o deixa vazio, significa: "Definitivamente, considerei o cenário em que nem se nem mais se são verdadeiros".': Minha primeira reação é presumir que o programador esqueceu de inserir código. o bloco else, caso contrário, por que um bloco else vazio está parado lá? Um// unused
comentário seria apropriado, não apenas um bloco vazio.else
bloco precisa conter algum tipo de comentário se não houver código. Prática comum para vazioelse
é um único ponto e vírgula, mais um comentário:else { ; // doesn't matter }
. Como não há razão para que alguém simplesmente digite um ponto e vírgula único recuado em uma linha própria. Prática semelhante às vezes é usado em loops vazias:while(something) { ; // do nothing }
. (código com quebras de linha, obviamente tão comentários não permitem-los.)Sua empresa seguiu as orientações de codificação MISRA. Existem algumas versões dessas diretrizes que contêm essa regra, mas de MISRA-C: 2004 † :
No MISRA-C: 2012 , que substitui a versão de 2004 e é a recomendação atual para novos projetos, a mesma regra existe, mas é numerada em 15.7 .
Exemplo 1: em um programador de instrução if if pode precisar verificar n número de condições e executar uma única operação.
Em um uso regular, executar uma operação não é necessário o tempo todo quando
if
é usado.Exemplo 2: Aqui o programador verifica n número de condições e executa várias operações. No uso regular,
if..else if
é como seswitch
você precisasse executar uma operação como padrão. Portanto, o usoelse
é necessário conforme o padrão misra† As versões atuais e anteriores dessas publicações estão disponíveis para compra na loja virtual da MISRA ( via ).
fonte
else
cláusula seja inacessível? (Deixar fora da condição final em vez disso, lançar um erro, talvez?)Esse item adicional diminuirá a cobertura do código do seu programa.
Na minha experiência com a portabilidade do kernel Linux, ou código Android para plataformas diferentes, muitas vezes fazemos algo errado e, no logcat, vemos algum erro como
fonte
__FILE__
e__LINE__
macros são um útil para fazer o local de origem fácil de encontrar se a mensagem é sempre impresso.Apenas uma breve explicação, desde que fiz isso há cerca de 5 anos.
Não existe (na maioria dos idiomas) nenhum requisito sintático para incluir a
else
declaração "nula" (e desnecessária{..}
), e em "pequenos programas simples" não há necessidade. Porém, programadores reais não escrevem "pequenos programas simples" e, igualmente importante, não escrevem programas que serão usados uma vez e depois descartados.Quando alguém escreve um if / else:
tudo parece simples e dificilmente se vê o ponto de acrescentar
{..}
.Mas, algum dia, daqui a alguns meses, algum outro programador (você nunca cometeria esse erro!) Precisará "aprimorar" o programa e incluirá uma declaração.
De repente,
doSomethingElse
meio que esquece que deveria estar naelse
perna.Então você é um bom programador e sempre usa
{..}
. Mas você escreve:Está tudo bem até que o novo garoto faça uma modificação à meia-noite:
Sim, está formatado incorretamente, mas metade do código do projeto e o "formatador automático" ficam embolados em todas as
#ifdef
instruções. E, é claro, o código real é muito mais complicado que este exemplo de brinquedo.Infelizmente (ou não), estou sem esse tipo de coisa há alguns anos, então não tenho um exemplo "real" novo em mente - o acima é (obviamente) artificial e um pouco obsceno.
fonte
Isso é feito para tornar o código mais legível, para referências posteriores e para esclarecer, para um revisor posterior, que os casos restantes tratados pelo último
else
são casos de nada fazer , para que não sejam negligenciados à primeira vista.Essa é uma boa prática de programação, que torna o código reutilizável e extensível .
fonte
Gostaria de acrescentar - e parcialmente contradizer - as respostas anteriores. Embora seja certamente comum usar if-else se de uma maneira semelhante a uma opção que cubra toda a gama de valores pensáveis para uma expressão, não é de forma alguma garantido que qualquer faixa de condições possíveis seja totalmente coberta. O mesmo pode ser dito sobre a própria construção do comutador, daí o requisito de usar uma cláusula padrão, que captura todos os valores restantes e pode, se não for necessário de outra forma, ser usado como uma salvaguarda de asserção.
A pergunta em si apresenta um bom contra-exemplo: a segunda condição não se relaciona com x (de modo que é a razão pela qual eu prefiro a variante baseada em if mais flexível do que a variante baseada em switch). A partir do exemplo, é óbvio que, se a condição A for atendida, x deve ser definido com um determinado valor. Se A não for atendido, a condição B será testada. Se for atendido, x deve receber outro valor. Se nem A nem B forem atendidos, x deve permanecer inalterado.
Aqui podemos ver que um ramo else vazio deve ser usado para comentar a intenção do programador para o leitor.
Por outro lado, não vejo por que deve haver uma cláusula else especialmente para a declaração if mais recente e mais interna. Em C, não existe um 'else if'. Existe apenas se e mais. Em vez disso, de acordo com MISRA, o construto deve ser formalmente recuado dessa maneira (e eu deveria ter colocado as chaves de abertura em suas próprias linhas, mas não gosto disso):
Quando MISRA pede para colocar chaves em todos os ramos, ele se contradiz mencionando "se ... senão se constrói".
Qualquer um pode imaginar a feiúra das árvores profundamente aninhadas, veja aqui em uma nota lateral . Agora imagine que essa construção possa ser arbitrariamente estendida em qualquer lugar. Então, pedir uma cláusula else no final, mas não em nenhum outro lugar, torna-se absurdo.
Portanto, tenho certeza de que as pessoas que desenvolveram as diretrizes da MISRA tinham em mente a intenção de alternar entre outros fatores.
No final, cabe a eles definir com precisão o que se entende por um "se ... outro se constrói"
fonte
O motivo básico é provavelmente a cobertura do código e o mais implícito: como o código se comportará se a condição não for verdadeira? Para testes genuínos, você precisa de alguma maneira de verificar se testou com a condição false. Se todos os casos de teste que você passar pela cláusula if, seu código poderá ter problemas no mundo real devido a uma condição que você não testou.
No entanto, algumas condições podem ser apropriadamente como o Exemplo 1, como em uma declaração de imposto: "Se o resultado for menor que 0, insira 0." Você ainda precisa fazer um teste em que a condição é falsa.
fonte
Logicamente, qualquer teste implica duas ramificações. O que você faz se for verdade e o que você faz se for falso.
Nos casos em que um dos ramos não tem funcionalidade, é razoável adicionar um comentário sobre o motivo pelo qual não precisa ter funcionalidade.
Isso pode ser benéfico para o próximo programador de manutenção. Eles não devem ter que procurar muito longe para decidir se o código está correto. Você pode meio que caçar o elefante .
Pessoalmente, isso me ajuda, pois me força a olhar para o caso else e avaliá-lo. Pode ser uma condição impossível, caso em que posso lançar uma exceção quando o contrato for violado. Pode ser benigno, caso em que um comentário pode ser suficiente.
Sua milhagem pode variar.
fonte
Na maioria das vezes, quando você só tem uma única
if
declaração, é provavelmente um dos motivos, como:Exemplo
Mas quando você faz
if .. else if
isso, é provavelmente um dos motivos, como:E se o seu
if .. else if
abrange todas as possibilidades, nesse caso o seu últimoif (...)
não é necessário, você pode simplesmente removê-lo, porque nesse momento os únicos valores possíveis são os cobertos por essa condição.Exemplo
E, na maioria desses motivos, é possível que algo não se encaixe em nenhuma das categorias da sua empresa
if .. else if
; portanto, é necessário tratá-las em umaelse
cláusula final . ..etc.Exemplo
Esta
else
cláusula final é bastante semelhante a poucas outras coisas em idiomas comoJava
eC++
, como:default
caso em uma instrução switchcatch(...)
que vem depois de todos oscatch
blocos específicosfinally
em uma cláusula try-catchfonte
Nosso software não era de missão crítica, mas também decidimos usar essa regra por causa da programação defensiva. Adicionamos uma exceção de lançamento ao código teoricamente inacessível (switch + if-else). E isso nos salvou muitas vezes, pois o software falhou rapidamente, por exemplo, quando um novo tipo foi adicionado e esquecemos de mudar um ou dois se-outro ou mudar. Como bônus, ficou super fácil encontrar o problema.
fonte
Bem, meu exemplo envolve comportamento indefinido, mas às vezes algumas pessoas tentam ser extravagantes e falham bastante, dê uma olhada:
Você provavelmente nunca esperaria ter o
bool
que não étrue
nemfalse
, no entanto, pode acontecer. Pessoalmente, acredito que esse seja um problema causado por uma pessoa que decide fazer algo sofisticado, maselse
declarações adicionais podem impedir outros problemas.fonte
Atualmente, estou trabalhando com PHP. Criando um formulário de registro e um formulário de login. Estou apenas usando puramente se e mais. Não há mais se ou qualquer coisa que seja desnecessária.
Se o usuário clicar no botão enviar -> ele passará para a próxima instrução if ... se o nome de usuário for menor que a quantidade de caracteres 'X' e alertá-lo. Se for bem-sucedido, verifique o tamanho da senha e assim por diante.
Não há necessidade de código extra, como outro, se isso puder dispensar a confiabilidade do tempo de carregamento do servidor para verificar todo o código extra.
fonte