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.