É necessário adicionar o caso padrão ao usar casos de comutação?

39

Durante uma recente revisão de código, fui solicitado a colocar default casos em todos os arquivos onde switch block fosse usado, mesmo que não houvesse nada para fazer em default . Isso significa que tenho que colocar o caso default e não escrever nada nele.

Esta é a coisa certa a fazer? Com que finalidade isso serviria?

    
por Ankit 04.01.2013 / 06:57
fonte

8 respostas

30

Parece que há três casos em que uma declaração default não é necessária:

  1. nenhum outro caso resta, porque há um conjunto limitado de valores que insere o switch case . Mas isso pode mudar com o tempo (intencionalmente ou acidentalmente), e seria bom ter um default case se alguma coisa muda _ você poderia registrar ou avisar o usuário sobre um valor errado.

  2. você sabe como e onde o switch case será usado e quais valores serão inseridos. Novamente, isso pode mudar e um processamento extra pode ser necessário.

  3. outros casos não precisam de nenhum processamento especial. Se esse for o caso, acho que você é solicitado a adicionar um default case , porque é um estilo de codificação aceito e torna seu código mais legível.

Os dois primeiros casos são baseados em suposições. Então (supondo que você trabalhe em uma equipe não tão pequena, já que você tem revisões regulares de código), você não pode permitir fazer essas suposições. Você não sabe quem estará trabalhando com seu código ou fazendo chamadas para funções / invocando métodos em seu código. Da mesma forma, talvez seja necessário trabalhar com o código de outra pessoa. Ter o mesmo estilo de codificação tornará mais fácil lidar com o código de alguém (incluindo o seu).

    
por 04.01.2013 / 07:20
fonte
28

Is this the right thiong to do? What purpose would it serve ?

Não é incomum que os padrões de codificação da empresa exijam um caso padrão para todas as instruções switch . Uma razão para isso é que isso torna fácil para os leitores encontrarem o fim do switch . Outra razão, provavelmente melhor, é que faz você pensar por um segundo sobre o que seu código deve fazer quando a condição não corresponder às suas expectativas. Independentemente do motivo da exigência, se for um padrão da empresa, você deve segui-la, a menos que haja uma razão impermeável para não fazê-lo.

Se você acredita que seu switch inclui casos para todas as condições possíveis, uma boa coisa a fazer é colocar uma instrução assert no caso padrão. Dessa forma, quando alguém altera o código e, inadvertidamente, adiciona uma condição que o switch não cobre, eles atingem o assert e percebem que precisam abordar essa parte do código.

Se o seu switch cobrir apenas algumas das condições possíveis, mas nada especial tiver que ser feito para os outros, você poderá deixar o caso padrão vazio. É uma boa idéia adicionar um comentário nesse caso para indicar que o caso padrão está intencionalmente vazio porque as condições que o atingiram não precisam de nenhum trabalho a ser feito.

    
por 04.01.2013 / 07:31
fonte
12

Se você "alternar" no tipo de enumeração pura, é perigoso ter um fallback padrão. Quando mais tarde você adicionar valores ao tipo de enumeração, o compilador destacará as opções com novos valores não cobertos. Se você tem uma cláusula default, o compilador vai ficar em silêncio, e você pode errar.

    
por 04.01.2013 / 08:24
fonte
9

Em muitos aspectos, essa pergunta é a mesma que a frequentemente solicitada: Eu preciso de uma cláusula else no final de uma if / else if ladder que cobre todas as opções .

A resposta é, sintaticamente falando, não você não. Mas há um porém ...

Uma cláusula default pode estar lá por (pelo menos) dois motivos:

  1. Como um manipulador de erros - com certeza, Nunca deve chegar aqui! é uma afirmação que pode ser feita, mas E se ocorrer? Corrupção de dados ou, pior ainda, nenhuma validação de dados são rotas para a falha do programa, se não forem adequadamente interceptadas. Neste caso, não deveria ser uma cláusula vazia!
  2. Cobertura de design / código - mesmo na forma mais simples de um fluxograma, há duas rotas de uma declaração if e sempre uma otherwise de um caso. Não há razão alguma para não incluí-los no código-fonte.

Minha filosofia é sempre bastante simples - avalie o pior cenário das duas opções e escolha o mais seguro possível. No caso de uma cláusula else ou default vazia, as opções de pior caso são:

  • Incluí-los: três ou quatro linhas extras de código "redundante".
  • Não inclua: dados desonestos ou uma condição inesperada não são interceptados, o que pode causar uma falha no programa.

Overdramatic? Talvez ... mas meu software tem o potencial de matar pessoas se der errado. Eu prefiro não correr esse risco.

Como um aparte, as diretrizes MISRA-C {ver perfil para afiliação} recomenda uma cláusula default para cada switch

    
por 04.01.2013 / 08:05
fonte
6

O Java não obriga você a ter uma instrução 'default', mas é uma boa prática ter uma o tempo todo, mesmo que o código nunca seja alcançado (agora). Aqui estão algumas razões:

Por ter uma cláusula padrão inacessível, você mostra ao leitor do seu código que você considerou os valores e sabe o que está fazendo. Você também permite alterações futuras, por exemplo: um novo valor de enum é adicionado; o switch não deve ignorar silenciosamente o novo valor; você pode jogar uma exceção lá ou fazer outra coisa.

Para capturar um valor inesperado (caso você não esteja ligando um enum) que é passado - pode ser maior ou menor do que o esperado, por exemplo.

Para lidar com ações 'padrão' - onde os switches são para um comportamento especial. Por exemplo, uma variável pode ser declarada fora do switch, mas não inicializada, e cada caso a inicializa para algo diferente. O padrão, neste caso, poderia inicializá-lo para um valor padrão, de forma que o código imediatamente após o switch não apresentasse erros / lançasse uma exceção.

Mesmo que você decida não colocar nada no padrão (sem exceções, registros, etc.), até mesmo um comentário para dizer que você considerou o fato de o padrão nunca ocorrerá pode ajudar na legibilidade do seu código; mas isso se resume a preferência pessoal.

    
por 04.01.2013 / 07:19
fonte
2

Eu também acrescentaria que isso depende da filosofia da linguagem que você está usando. Em Erlang, por exemplo, onde é uma abordagem comum para "deixar travar", você não definiria um caso padrão, mas deixaria que sua instrução case gerasse um erro se ocorresse uma situação que não fosse atendida.

    
por 04.01.2013 / 18:06
fonte
0

Você deve sempre ter um padrão, a menos que tenha coberto de forma comprovada e permanente todos os casos. Não custa nada, e é seguro contra a falha em manter sua instrução switch em um programa em evolução.

Se você realmente tiver certeza de que não se importa com nenhum outro caso, o padrão: break; // não se importa mas o padrão deve ser algo como default: throw new Error ("valor inesperado");

Da mesma forma, você nunca deve "passar por" uma construção de caso não trivial sem adicionar um comentário ao efeito que pretende descartar. Java entendeu errado no estágio de projeto.

    
por 09.01.2013 / 19:12
fonte
-2

Considere

enum Gender
{
       MALE ,
       FEMALE ;
}

e

void run ( Gender g )
{
      switch ( g )
      {
           case MALE :
                 // code related to males
                 break ;
           default :
                 assert Gender . FEMALE . equals ( g ) ;
                 // code related to females
                 break ;
      }
}

Eu diria que isso é melhor do que ter um caso masculino, um caso FEMININO e um caso padrão que gera uma exceção.

Durante a fase de testes, o computador irá verificar se g é FEMALE. Durante a produção, o cheque será omitido. (Sim uma microoptimização!)

Mais importante, você manterá sua meta de cobertura de código de 100%. Se você escreveu um caso padrão que gera uma exceção, como você poderia testá-lo?

    
por 05.01.2013 / 04:12
fonte