Em termos de manutenção, "outro tempo" sem aparelhos intermediários é considerado seguro?


26

Os else whileaparelhos sem intervenção são considerados "seguros" na manutenção?

Escrever if-elsecódigo sem chaves como abaixo ...

if (blah)
    foo();
else
    bar();

... apresenta um risco porque a falta de chaves facilita muito a alteração inadvertida do significado do código.

No entanto, abaixo também é arriscado?

if (blah)
{
    ...
}
else while (!bloop())
{
    bar();
}

Ou é else whilesem aparelhos intermediários considerado "seguro"?


20
para mim else whileparece nojento. Eu usaria else { while (condition) { ... } }.
Joachim Sauer

7
Eu acho que é subjetivo demais para uma resposta adequada ... Eu mesmo não faria isso, pois não esperava um loop lá e acha que não espero dificultar a legibilidade.
Johannes

7
Gostaria de extrair método para enquanto-stuff
mosquito

12
Honestamente, isso me dá arrepios. ifé avaliada somente uma vez, mas whiledenota um loop, assim conectando tanto me dá uma sensação sem fundamento que a iffaz parte do circuito ... de alguma forma ...
user281377

4
E se na elsecláusula de que você quer fazer o while e fazer algo mais? Apenas use aparelho, por favor.
Carlos Campderrós

Respostas:


57

Isso me lembra este código:

if ( ... ) try {
..
} catch (Exception e) {
..
} else {
...
}

Toda vez que você combina dois tipos de blocos, esquece chaves e não aumenta o recuo, você está criando um código muito difícil de entender e manter.


18
Bom exemplo. Que maneira horrível de escrever.
21312 Leo

4
Uau, essa resposta é ridiculamente convincente!
Mehrdad

Você pode configurar facilmente IDEs modernos para formatar automaticamente o código ao salvar - incluindo a inserção de chaves e a correção do recuo. Portanto, isso é apenas meio argumento. Recuado adequadamente, isso não apresentaria problemas de legibilidade, se existem chaves ou não.
Hans-Peter Störr

55

Talvez seja porque eu aprendi meu ofício (quando) usando o método Jackson Entity Structure Diagram , mas subscrevo a visão de que o único termo correto e não abrigado após um ifou um elseé subsequente if(ou seja, permitindo uma else ifescada)

Qualquer outra coisa (sem trocadilhos) deixa potencial para mal-entendidos e / ou problemas de manutenção. Esse é o aspecto central da ideia do OP ser "inseguro".

Eu também ficaria muito cauteloso ao incluir o while()na mesma linha que o else- preparado ou não. Não me parece certo ... a falta de máscaras de recuo extras é a elsecláusula. E a falta de clareza gera mal-entendidos (veja acima).

Portanto, no exemplo, aconselho / recomendo fortemente (e insisto, na minha equipe):

if ( blah )
{
    ...
}
else
{
    while ( !bloop() )
    {
        bar();
    }
}

Claro, eu também esperaria ver comentários adequados.

- Editar -

Recentemente, a Apple sofria de uma vulnerabilidade SSL, causada por uma correção de manutenção ruim - que adicionava uma segunda linha a uma única linha sem suporte. Então, vamos colocar na cama a ideia de que linhas simples não-retocadas estão OK?


2
Concordo em ser o único termo correto a seguir um outro. Se houvesse um, else whileeu provavelmente nem notaria que havia um loop em uma rápida verificação do código, especialmente se a condição que eu estava procurando fosse satisfeita pelo if.
Drake Clarris

3
É engraçado. Todo mundo diz que é mais fácil ler se tudo está entre chaves. Acho o oposto verdadeiro. Se for apenas uma declaração, mantê-la fora do aparelho facilita a leitura. Menos desordem. Pode ser apenas porque eu sempre fiz dessa maneira.
Jeff Davis

2
@JeffDavis é uma boa pegada. "Mais fácil de ler" é um convite típico para uma guerra santa inútil. Eu prefiro chaves, mas não por causa do lixo irrelevante "easiertoread" (para mim, por exemplo, é exatamente o oposto), mas porque é mais difícil interromper a manutenção do código. A propósito, o OP expressou melhor em sua pergunta: sem aparelhos intermediários é considerado "seguro" ? else while
Gnat

@JeffDavis - Eu sei que esta discussão é de dois anos, mas a Apple recentemente descoberto por que não usar chaves não é uma boa idéia andrewbanks.com/...
Andrew

@ Andrew A propósito, a linguagem Swift da Apple agora proíbe explicitamente o controle de fluxo de uma linha. Esse bug pode ser uma das razões para fazê-lo.
Sulthan

6

Sempre fui ensinado a manter tudo entre chaves, recuado e comentado. Eu acredito que é muito mais fácil ler e detectar erros. Pessoalmente, acho que a modularidade é a chave, então eu sempre escreveria o código assim:

    if(blah)
    {
     ....
    }
    else
    {
       while(!bloop()
       {
        bar;
       }
    }

6

Eu extrairia o método e faria

if ( blah )
{
    ...
}
else
{
   newMethod();
}

Consulte a abordagem "método de extração" explicada no site do catálogo de refatoração :

Você tem um fragmento de código que pode ser agrupado.

Transforme o fragmento em um método cujo nome explica a finalidade do método.

void printOwing() {
    printBanner();

    //print details
    System.out.println ("name:    " + _name);
    System.out.println ("amount    " + getOutstanding());
}

                                                                                                         http://www.refactoring.com/catalog/arrow.gif

void printOwing() {
    printBanner();
    printDetails(getOutstanding());
}

void printDetails (double outstanding) {
    System.out.println ("name:    " + _name);
    System.out.println ("amount    " + outstanding);
}

Depende ... se, por exemplo, o loop while usasse dados de nível de função, agora você precisará mais desses dados para o módulo (ou classe, se estiver usando C ++). E se apenas um pequeno trecho de código, você adota métodos triviais. Mas às vezes, dependendo das circunstâncias, eu concordo.
22412 Andrew

1
+1 Os compiladores C ++ inteligentes podem incorporar uma função. No ambiente .Net, pequenas funções são melhores devido ao JIT.
Job

4

Eu consideraria isso um mau hábito de codificação. Às vezes, funciona perfeitamente bem e você não terá problemas ao compilar e executar o código. Outras vezes, pode causar erros graves e você acaba gastando horas corrigindo esse erro.

É sempre recomendável modularizar seu código. Se você precisar colocar um loop while em outra parte, coloque-o em um bloco para que outros, ao trabalhar no seu código, possam entender facilmente a lógica.

if ( blah )
{
    ...
}
else
{
    while ( !bloop() )
    {
        bar();
    }
}

É uma boa prática inserir código em blocos. Isso torna mais simples e fácil entender e depurar também.


4

Pode ser bom se permanecer simples assim, embora pessoalmente eu não goste e minha preferência seja usar chaves até mesmo para os blocos de código if / else mais simples. É apenas mais arrumado para mim.

No entanto, onde isso fica confuso é quando você aninhar se / else faz um loop em alguns com chaves, outros sem. Um loop While no meio de todo esse espaguete! Eu trabalhei com código tão ruim e é um pesadelo para depurar e entender. Isso segue desde o primeiro ponto; tudo fica bem quando fica simples e você está feliz com isso, mas outros programadores aparecem e adicionam coisas a ele, provavelmente um se mais dentro do loop while. Se está escrito limpo, em primeiro lugar, há menos chance disso acontecer.

O objetivo é esclarecer as coisas para que outros programadores possam ver rapidamente o que é certo e errado. Escreva o código para que o padrão pareça correto e não seja jar.

O outro lado disso é que talvez eu pudesse ver algumas pessoas alegando que, em certos casos, isso parece bem. Se eu tenho o recurso, preciso fazer esse processamento, enquanto espero algo fazer isso. Mesmo assim, para mim ainda não há diferença em aninhar o loop while dentro do bloco else.


3

Bem, apesar de todos argumentarem sobre o uso de aparelhos e parecem amá-los, na verdade prefiro o contrário. Só uso aparelho quando preciso, porque acho mais legível e conciso sem ele.

if (...)
   foo();
else while(...)
   bar();

... eu realmente acho isso " else while(...)" notavelmente legível! Até parece um inglês simples! Mas acho que as pessoas vão achar isso estranho, porque é incomum dizer o mínimo.

No final, todos nós tendemos a torná-lo à prova de idiotas com suspensórios ... porque, bem, você sabe.


3
isso será especialmente legível depois que algum mantenedor inocente mudar else while(...) bar();para algo como else while(...) foobar(); bar();:) #
1013

3
bem, eu diria que é um mantenedor inocente bastante estúpido e perigoso . Eu sei o princípio de emburrecê-lo para evitar erros estúpidos ... mas ir tão longe é, no entanto, bastante triste. Mas eu sabia que receberia tais comentários e votos negativos. Sem problemas.
Dagnelies

2
"Sempre codifique como se a pessoa que manterá seu código for um psicopata violento que sabe onde você mora." ( Alan Braggins )
gnat

1
Bem, tudo se resume ao que você acha que seria o nível mais estúpido de alguém trabalhando no seu código. Eu argumento que se o seu "mantenedor" fica confuso com essas quatro linhas de código ... então você tem um enorme problema em mãos. E se é um psicopata violento, você tem dois. ;)
dagnelies

1
if - bem, o link que me refiro acima, ampliou a versão desta citação: Programador 1: 'Há uma boa citação aqui - "Sempre codifique como se a pessoa que manter seu código for um psicopata violento que sabe onde você mora"' . Programador 2: (Examina o mantenedor) 'O que você quer dizer com "como se"?'
Gd

2

Eu sempre coloco aparelho, só porque você pode adicionar outra linha quando estiver com pressa, recuar, esquecer os aparelhos e coçar a cabeça o que está acontecendo. Eu mantenho o suporte de abertura na mesma linha, mas isso não importa. Nos dois casos, é melhor tê-los.

if(blah) {
    foo();
}
else {
    bar();
}

O posicionamento dos aparelhos provavelmente desencadeia mais argumentos do que qualquer coisa além (ou possivelmente incluindo) da religião!
22412 Andrew

Acordado. Editarei minha resposta para enfatizar sua existência, não posição.
Tsvetomir Dimitrov

2

O que há de tão errado com o aparelho que tantas pessoas estão tentando evitar escrevê-lo?

Que problema else whileresolve exatamente ?

Os aparelhos são baratos e bons, e tornam a intenção do código evidente e clara, ao contrário de inteligente e espirituoso.

Citando a Filosofia Unix:

Regra de clareza: Clareza é melhor que inteligência.

Como a manutenção é tão importante e cara, escreva programas como se a comunicação mais importante que eles fizerem não fosse o computador que os executa, mas os seres humanos que lerão e manterão o código-fonte no futuro (inclusive você).


1

Não há nada errado com

if (blah)
    foo();
else
    bar();

assim como não há nada de errado com

if (blah) foo(); else bar();

nas circunstâncias certas (suas circunstâncias podem variar, mas esse estilo específico é melhor usado quando você tem muito código repetitivo - a exibição de cada linha é mais importante que o recuo estilístico)

Mas se você escolher um caminho, mantenha-o - a consistência é o rei. Portanto, seu segundo exemplo é muito ruim, como a expressão if tinha colchetes para sua declaração, a declaração while deve estar dentro dos colchetes para a cláusula else, e não fora dela.


além disso, eu já vi esse código antes:

if (x) foo()
{
  bar();
}

e foi escrito pelo próprio nazi do padrão de codificação (que insistia em colchetes para tudo).


1

Os IDEs modernos podem ser facilmente configurados para reformatar (incluindo remover ou adicionar chaves desnecessárias) e / ou recuperar o código ao salvar um arquivo. Assim, seu exemplo se pareceria automaticamente, por exemplo

if (blah) {
  blub();
} else
  while (!bloop()) {
    bar();
  }

A indentação sempre torna o aninhamento facilmente visível, mesmo sem aparelhos desnecessários. Portanto, se você conseguir aplicar essas configurações de IDE, não vejo riscos.

Pessoalmente, acho o código que omite os chavetas e as quebras de linha muito mais legíveis, pois evita a confusão:

if (blah) blub();
else while (!bloop()) bar();

Mas é claro, muitos desenvolvedores ficam muito felizes em discutir sobre essas coisas para sempre e um dia.

Ao utilizar nosso site, você reconhece que leu e compreendeu nossa Política de Cookies e nossa Política de Privacidade.
Licensed under cc by-sa 3.0 with attribution required.