Declaração única se chaves - ou não? [fechadas]

59

Qual é o melhor / mais aceito?

Este:

if(condition)
{
  statement;
}

Ou:

if(condition)
  statement;

Eu tendem a preferir o primeiro, porque acho que fica mais fácil dizer o que realmente pertence ao bloco if, evita que outras pessoas adicionem o aparelho mais tarde (ou criem um bug esquecendo-se de) e faz todas as suas declarações if uniforme em vez de alguns com aparelho e outros sem. O segundo, no entanto, ainda é sintaticamente correto e definitivamente mais compacto. Estou curioso para ver o que é mais geralmente preferido pelos outros.

Zannjaminderson
fonte
2
Mas você tem sua chave de abertura na posição errada. Isso é certo.
Christian Mann
Em muitos idiomas, um bloco é uma declaração e, portanto, sintaticamente, é sempre uma declaração if (expressão)
Ingo
2
Desde que você não especificou um idioma ... Que tal statement if condition;?
Dave Sherohman 9/09/11
@ Christian - bom. Essa seria outra questão separada disso, não?
Zannjaminderson 9/09/11
@ Ingo - bom ponto.
Zannjaminderson 9/09/11

Respostas:

131

O primeiro é melhor porque o segundo é propenso a erros. Por exemplo, digamos que você esteja comentando temporariamente o código para depurar algo:

if(condition) 
//      statement;
otherStatement;

Ou adicionando código com pressa:

if(condition) 
    statement;
    otherStatement;

Isso é obviamente ruim. Por outro lado, o primeiro parece muito detalhado às vezes. Portanto, prefiro colocar tudo em uma linha se for suficientemente curto e simples:

if(condition) statement;

Isso reduz o ruído sintático e, ao mesmo tempo, faz com que a construção pareça fazer o que realmente faz, tornando-a menos propensa a erros. Desde que essa sintaxe seja usada apenas para condições e instruções muito simples e curtas, acho perfeitamente legível.

dsimcha
fonte
35
Bom ponto de colocar tudo em uma linha.
Neil Aitken
7
@artjomka: Se a declaração for longa e tiver que seguir sua própria linha, então uso chaves para facilitar a leitura. O ponto é que você deseja a construção mais curta e menos sintaticamente barulhenta que não seja ambígua para um humano que a esteja lendo rapidamente, em vez de examiná-la.
dsimcha
15
Eu prefiro aquele com aparelho pelos motivos já mencionados. Eu não gosto do one-liner, porque não é imediatamente óbvio o que acontece quando eu passo por cima da linha no depurador. Eu tenho que dar o passo separado para ver qual condição é avaliada.
Jim A
10
O espaço em branco da @TMN é gratuito, os monitores são grandes e seu cérebro aprende a reconhecer a forma que ajuda a analisar o código.
Murph
5
@ Murph: espaço em branco é gratuito? Eu devo ter perdido essa, Na minha tela, ocupa muito espaço. Muito mais do que 50%, na verdade. O que no meu livro parece um grande desperdício. Pessoalmente, gosto de maximizar o conteúdo por centímetro quadrado no código.
Konrad Rudolph
44

Eu sempre uso colchetes apenas para estar seguro.

Tudo bem quando você escreve, mas sabe que alguém virá no futuro e inserirá outra declaração sem colocar colchetes.

Neil Aitken
fonte
20
As pessoas realmente viram isso acontecer? Acho que nunca vi isso em 10 anos de programação. Talvez eu tenha sido muito protegido. :)
David
9
Eu adoraria dizer não, mas infelizmente eu já vi.
Neil Aitken #
13
Você sempre usa colchetes para nunca esquecer de usá-los - é tão simples quanto isso.
Murph
12
+1 a @Murph. O mesmo motivo que eu uso os indicadores de mudança de direção quando ninguém está por perto - e nos estacionamentos!
Dan Ray
7
Essa é uma boa prática para ajudar a evitar erros ao mesclar de ramificação para tronco ou entre ramificações.
precisa saber é o seguinte
27

Prefiro a versão sem aparelho, sempre que possível.

A explicação a seguir é longa. Por favor, tenha paciência comigo. Vou dar uma razão convincente para eu preferir esse estilo. Também explicarei por que acho que o contra-argumento usual não se sustenta.

Linhas (quase) vazias são um desperdício

A razão para isso é que a chave de fechamento requer uma linha extra de código - e a chave de abertura, dependendo do estilo. 1 1

Este é um grande negócio? Superficialmente, não. Afinal, a maioria das pessoas também coloca linhas vazias em seu código para separar blocos logicamente ligeiramente independentes, o que melhora bastante a legibilidade.

No entanto, detesto desperdiçar espaço vertical. Na verdade, os monitores modernos têm amplo espaço horizontal. Mas o espaço vertical ainda é muito, muito limitado (a menos que você use um monitor na posição vertical, o que não é incomum). Esse espaço vertical limitado é um problema: é amplamente reconhecido que os métodos individuais devem ser tão curtos quanto possível e que as chaves correspondentes (ou outros delimitadores de bloco) não devem ter mais que uma altura de tela na diferença, para que você possa ver o bloco inteiro sem rolagem.

Esse é um problema fundamental : depois que você não consegue mais ver o bloco inteiro na tela, fica difícil entender.

Como conseqüência, detesto linhas vazias redundantes. Onde linhas vazias únicas são cruciais para delimitar blocos independentes (basta olhar para a aparência visual deste texto), linhas vazias consecutivas são um estilo muito ruim no meu livro (e, na minha experiência, elas geralmente são um sinal de programadores iniciantes).

Da mesma forma, linhas que simplesmente se sustentam e que podem ser economizadas devem ser. Um bloco de instrução única que é delimitado por chaves desperdiça uma a duas linhas. Com apenas 50 linhas ish por altura da tela, isso é perceptível.

Omitir aparelho não faz mal nenhum

Há apenas um argumento contra a omissão de chaves: que alguém mais tarde adicione outra declaração ao bloco em questão e esqueça de adicioná-las, alterando inadvertidamente a semântica do código.

Isso seria realmente um grande negócio.

Mas na minha experiência, não é. Sou um programador desleixado; e, no entanto, em minha década de experiência em programação, posso dizer honestamente que nunca esqueci de adicionar chaves ao adicionar uma declaração extra a um bloco singleton.

Até acho implausível que esse seja um erro comum: os blocos são uma parte fundamental da programação. A resolução e o escopo no nível do bloco são um processo mental automático e arraigado para os programadores. O cérebro simplesmente faz isso (caso contrário, raciocinar sobre programação seria muito mais difícil). Não há esforço mental adicional necessário para lembrar de colocar os aparelhos: o programador também se lembra de recuar a declaração recém-adicionada corretamente, afinal; então o programador já processou mentalmente que um bloco está envolvido.

Agora, eu estou não dizer que omitindo chaves não causar erros. O que estou dizendo é que não temos evidências de um jeito ou de outro. Simplesmente não sabemos se isso causa danos.

Então, até que alguém possa me mostrar dados concretos, coletados de experimentos científicos, demonstrando que isso é realmente um problema na prática, essa teoria permanece uma " história mais ou menos ": uma hipótese muito convincente que nunca foi posta à prova e que não deve ser usado como argumento.


1 Às vezes, esse problema é resolvido colocando tudo - inclusive o aparelho - na mesma linha:

if (condition)
{ do_something(); }

No entanto, acredito que é seguro dizer que a maioria das pessoas despreza isso. Além disso, ele teria os mesmos problemas que a variante sem chaves, por isso é o pior dos dois mundos.

Konrad Rudolph
fonte
6
A omissão de chaves prejudica a legibilidade e pode facilmente causar problemas quando o código é modificado.
Josh K
15
@ Josh: a primeira afirmação é ridícula, como mostram linguagens como o Python (faça o backup com evidências, se você pensa o contrário). O segundo foi combatido na minha resposta. Você tem evidências para fazer o backup? Caso contrário, seu comentário é uma indicação de que você realmente não leu meu texto. Por favor, faça-o antes de criticá-lo.
amigos estão dizendo sobre Konrad Rudolph
8
+1 por seus pensamentos, mas acho que sua posição é autodestrutiva. Você diz "mostre-me dados concretos, coletados de experimentos científicos, mostrando que isso é realmente um problema na prática" e, no entanto, recorra à experiência anedótica (sua) para defender sua posição. Você diz: "na minha experiência ... na minha década de experiência ... acho implausível ..." e assim por diante. Você pode mostrar dados concretos, coletados de experimentos científicos, apoiando sua alegação de que "omitir aparelho não faz mal"? A experiência pessoal é boa para apoiar uma opinião, mas não peça mais "evidências" do que você está disposto a dar.
bedwyr 3/11
3
@bedwyr: há uma diferença qualitativa, no entanto. Primeiro, deixo claro que realmente serei persuadido pelos dados, e deixo igualmente claro que a minha é apenas uma hipótese, não apoiada por dados. Em segundo lugar, afirmei um argumento (pelo menos para mim) plausível para a minha crença de que a afirmação é falsa e por que ela precisa ser corroborada. O que me leva a terceiro: o ônus aqui é a oposição de provar sua afirmação, e não de eu refutá-la. Além do problema de plausibilidade, mostrei um argumento factual não relacionado que apóia meu estilo de codificação.
Konrad Rudolph
4
@Konrad - python não mostra o contrário, porque o recuo é significativo e, portanto, as chaves estão implícitas. Bons programadores brilhantes, do tipo que está aqui, provavelmente não cometerão erros com frequência, se é que há algum tempo (em muitos anos eu provavelmente já vi problemas apenas em algumas ocasiões), mas há muito menos problemas programadores por aí que fazem coisas estúpidas, que é uma das razões pelas quais os padrões de codificação são necessários em primeiro lugar. (. E porque os prazos e stress pode fazer o melhor de nós menos bom)
Murph
19

Eu vou com o segundo. É mais sucinto e menos detalhado.

Eu tento não escrever para o menor denominador comum, então espero que outros desenvolvedores saibam como escrever uma das estruturas de fluxo de controle mais comuns na programação hoje.

Steven Evers
fonte
11
absolutamente! afinal, se o código foi difícil de escrever, também deve ser difícil de manter! ;-)
Steven A. Lowe
3
@ Steven Se você esquecer aparelho, acho que existem outros problemas aqui.
TheLQ
mais succint == menos detalhado
UncleZeiv
5
@SnOrfus: um tanto sarcástico, já que os 2 caracteres extras são sobrecarga trivial e evitam um erro de manutenção muito comum. Sua milhagem pode variar ;-)
Steven A. Lowe
11
Para mim, o recuo deixa claro o que está acontecendo. A primeira forma ocupa espaço extra na tela e, portanto, é negativa para mim.
Loren Pechtel
16

Eu usaria o seguinte (o consenso aqui):

if (condition) {
    any_number_of_statements;
}

Também é possível:

if(condition) single_compact_statement;

Não é tão bom, especialmente em idiomas semelhantes ao C / C ++:

if(condition) 
    single_compact_statement;

(Nenhuma escolha aqui em Python ;-)


No Perl , você usaria:

$C = $A**3 if $A != $B;

ou

$C = $A**3 unless $A == $B;

(Este não é um pseudocódigo ;-)

botas de borracha
fonte
11
Meus pensamentos exatamente. Se a instrução única parecer boa em uma única linha após a ifcláusula, não uso chaves. Para qualquer outra ifdeclaração (ou qualquer declaração que use várias linhas), eu sempre uso chaves. Em particular, se houver uma elsecláusula, cada caso sempre terá chaves.
eswald
9
Eu nunca vi alguém confundir perl com pseudocódigo antes. Caracteres aleatórios sim, pseudocódigo - não.
Joe D
3
Pergunto-me se alguém fez um gerador de programa Perl apenas ligar / dev / random para um intérprete de Perl ...
Christian Mann
Eu gosto da abordagem do ruby ​​aqui. Ele oferece o estilo perl de linha única <statement> if <condition>ou um estilo de bloco com várias linhas if <condition>/ <do something>/ end(ruby evita chaves, então aqui a chave de abertura é implícita ife a chave final é substituída por um literal end). Ele nem sequer oferece a estranha declaração multilinha-mas-realmente-apenas-única-linha.
Ben Lee
O one-liner não funciona com a maioria dos depuradores (não é possível acionar uma interrupção quando o conteúdo da cláusula 'if' estiver prestes a ser executado).
Peter Mortensen
11

Eu uso o método chaves - por todos os motivos acima, mais um.

O código é mesclado. Sabe-se que isso acontece em projetos nos quais trabalhei nessa declaração única, que foi quebrada por fusões automáticas. O mais assustador é que o recuo parece correto, mesmo que o código esteja errado, então esse tipo de bug é difícil de detectar.

Então eu vou com aparelho - em suas próprias linhas. É mais fácil identificar os níveis dessa maneira. Sim, desperdiça espaço na tela vertical e isso é uma desvantagem genuína. No entanto, acho que vale a pena.

user36294
fonte
10

Sem aparelho. Se algum outro programador adicionar uma segunda declaração ao meu código, não será mais minha culpa do que deixar alguém dirigir meu carro e eles atravessarem um penhasco.

Covar
fonte
3
Exatamente! Não é nossa culpa que ele / ela não conheça a sintaxe.
kirk.burleson
3
Mau exemplo. Um bom é um carro com pedais fora de lugar - gasolina em vez de freio. É o seu carro, para que você não se importe com mais ninguém. Existe um problema que eles não sabem sobre o seu posicionamento exclusivo dos pedais. Você é um bom engenheiro de automóveis nesse caso?
precisa saber é o seguinte
Seria sua culpa se você desse a eles seu carro sabendo que eles podem estar bêbados. Da mesma forma, devemos tentar assumir o mínimo possível sobre futuros desenvolvedores para ajudar a facilitar a manutenção.
Aram Kocharyan
8

Tivemos esse argumento mais de uma vez aqui, e o consenso geral é sempre usar aparelho. As principais razões são sobre legibilidade / manutenção.

Se você precisar adicionar código ao ifbloco, não precisará se lembrar / procurar chaves. Quando futuros programadores leem o código, as chaves são sempre inequívocas.

No lado positivo, o ReSharper adicionará automaticamente os aparelhos para programadores preguiçosos no Visual Studio, e presumo que haja complementos para outros IDEs que também o farão.

shimonyk
fonte
3
Eu categoricamente não compro a reivindicação de legibilidade. Python é uma das linguagens mais legíveis que existem e não precisa de delimitadores. Essa afirmação simplesmente não é verdadeira. Também não compro a reivindicação de manutenção, porque ainda não foi comprovada e ainda é repetida repetidamente. Mas, neste caso, estou realmente muito interessado em evidências empíricas. Isso é algo que um estudo poderia facilmente descobrir e resolver de uma vez por todas.
amigos estão dizendo sobre Konrad Rudolph
Como o Python usa indentação em vez de delimitadores, eles estão implícitos, não sendo uma comparação válida.
Murph
@ Konrad - evidência empírica: Quando eu era um novo programador, eu adicionei código pessoalmente a um bloco if sem suporte, sem perceber que o programador anterior não havia se incomodado com chaves. Eu pessoalmente vi outras pessoas fazendo isso com meus próprios olhos. É verdade que apenas uma vez vi alguém precisar de ajuda para encontrar o problema após executar o código, mas isso tinha mais a ver com habilidades ruins de teste.
shimonyk
@ shimonyk: Então, basicamente, suas observações apoiam minha afirmação de que esse problema é inconseqüente? A propósito, as observações pessoais são anedotas, não contam como evidência empírica.
Konrad Rudolph
@ Konrad muito bem, por favor, cite suas fontes também. Suponho que você tenha um estudo duplo-cego revisado por pares que você está consultando? Caso contrário, meramente zombar de suas próprias anedotas na tentativa de provar que os outros estão errados, enquanto exige outro pôster, referir-se a 'evidência' é hipócrita na melhor das hipóteses. Como alguém que escreveu mais adiante sobre esse mesmo tópico escreveu "o ônus aqui é a oposição de provar sua afirmação, não de eu refutá-la".
shimonyk
7

Eu uso a primeira sintaxe, quase sem exceção. Porque não pode ser mal interpretado .

"Não me faça pensar" não se aplica apenas a interfaces de usuário, todos ;-)

Steven A. Lowe
fonte
4
Eu costumava fazer isso, mas fui vencido pelo argumento de que os programadores precisam conhecer a linguagem e eles devem pensar.
kirk.burleson
2
Considero uma cortesia comum ... para o meu futuro eu.
Steven A. Lowe
5

Eu pessoalmente prefiro o segundo. O primeiro parece feio, estranho e desperdiça espaço horizontal. Os principais problemas com o segundo são macros e as pessoas modificam seu código posteriormente, entendendo errado.

Para isso, eu digo "não use macros". Eu também digo: "indente seu maldito código corretamente". Considerando como todo editor de texto / IDE usado para programação faz recuo automaticamente, isso não deve ser tão difícil de fazer. Ao escrever código no Emacs, usaria o recuo automático para identificar se escrevi algo errado em uma linha anterior. Sempre que o Emacs começa a estragar o recuo, geralmente sei que fiz algo errado.

Na prática, acabo seguindo qualquer convenção de codificação que tenha sido definida diante de mim. Mas esses me incomodam (e me deixam muito mais feliz quando eu codigo em Python e todo esse desastre de suporte desaparece):

if (condition) {
    statement;
} // stupid extra brace looks ugly

Então

if (condition) // the brackets have now just become noise
{ statement; } // also can't see the indentation, harder to read

Embora honestamente, duas declarações em uma declaração if me incomodam muito mais do que uma única declaração. Principalmente porque os colchetes são obrigatórios e ainda parece engraçado com apenas duas instruções na instrução if.

jsternberg
fonte
Se você for escrever macros, escreva-as para garantir que possam ser inseridas em qualquer parte do código sem interromper de qualquer maneira.
Covar 5/11
4

Eu uso a versão de duas linhas sem chaves (o segundo formulário), mas não para economizar espaço.

Uso esse formulário porque acho mais legível, visualmente atraente e mais fácil de digitar. Eu só uso esse formulário se essas condições forem atendidas; ou seja, a ifcondição deve se encaixar perfeitamente em uma única linha e a instrução correspondente deve se encaixar perfeitamente na linha a seguir. Se não for esse o caso, usarei aparelhos para melhorar a legibilidade.

Se eu usar este formulário, verifique se há uma linha vazia (ou uma linha contendo apenas uma chave) antes e depois da ifdeclaração (ou acima do comentário, se houver). Embora essa não seja uma regra que eu sigo conscientemente, percebo isso agora depois de ler esta pergunta.

Economizar espaço na tela não é uma prioridade para mim. Se eu precisasse de mais espaço, usaria um monitor maior. Minha tela já é grande o suficiente para que eu possa ler qualquer coisa em que possa precisar focar minha atenção. É improvável que eu precise me concentrar em tantas linhas de código ao mesmo tempo que ocupem minha tela inteira. Se há tanto aninhamento acontecendo com um pedaço de código que eu não consigo entender sem visualizá-lo mais de uma vez, então eu teria que considerar se a lógica poderia ser melhor representada pela refatoração.

Abaixo estão alguns exemplos que demonstram como eu uso esse formulário da ifdeclaração.

    string GuardConditions(Plan planForWorldDomination)
    {
        if (planForWorldDomination == null)
            throw new ArgumentNullException("planForWorldDomination");

        if (!planForWorldDomination.IsComplete())
            return "Doh!";

        planForWorldDomination.Execute();
    }

    void ProcessingLogic()
    {
        OneBlankLineAbove();

        if (simpleCondition)
            simpleStatement();

        OneBlankLineBelow();
        OneBlankLineAbove();

        // optional comment on the line above an if statement
        if (simpleCondition)
            simpleStatement();

        OneBlankLineBelow();
    }

    void Assignment(string drive)
    {
        OneBlankLineAbove();

        string prompt;
        if (simpleCondition)
            prompt = "simple assignment";
        else
            prompt = null;

        OneBlankLineBelow();
    }

    string Return()
    {
        OneBlankLineAbove();

        if (simpleCondition)
            return "simple return";
        else
            return null;

        OneBlankLineBelow();
    }
Aprendiz do Dr. Wily
fonte
3

Suspensórios. Sempre. Sou meio fã deles, porque isso dá ao código alguma consistência. E também como o @dsimcha escreveu - menos chance de erros ao adicionar linhas de código adicionais.

A "feiúra" de chaves em torno de uma única linha de código é menos prejudicial que o trabalho adicional, o que é provável nesses casos com depuração e / ou adição de código.

Vedran Krivokuća
fonte
11
Eu nunca vi alguém cometer o erro que você está falando.
kirk.burleson
11
Acabei de chegar ontem em outro código. :-) Apenas me pergunto como será o fluxo de dados, entre outras adições ao código, adicionando chaves em todos os seus ifs, porque ele realmente parece estar do lado diferente de mim nesse aspecto. :-) (acalme-se, eu estou brincando, editado apenas o que eu tinha que ...)
Vedran Krivokuća
2

Pessoalmente, eu vou entre parênteses.

Por quê?

Bem, se alguém aparecer e precisar adicionar código à instrução if, é 100% claro onde está o escopo.

Ele mantém o formato das ifinstruções consistentes, independentemente de quantas instruções existem no bloco.

No entanto, se o estilo do projeto não for adequado, atenha-se a isso.

ChrisF
fonte
1

Eu quase sempre uso os suportes apenas para estar do lado seguro. No entanto, às vezes, se o conteúdo do bloco for realmente curto, eu os deixarei de fora e o tornarei único:

if (x==5) Console.WriteLine("It's a five!");
JohnFx
fonte
Acho que alguém não é fã de concisão.
JohnFx
2
Brevidade por uma questão de legibilidade? Absolutamente não. É código, não um concurso de golfe.
Josh K
3
Eu acho que a legibilidade é um ótimo motivo de brevidade, pessoalmente. De qualquer forma: o espaço em branco não conta no meu livro de regras sobre código de golfe.
JohnFx
O único problema com isto é que se presta a abusos
Conrad Frix
2
Então não abuse. Não estou dizendo para usá-lo como um padrão de codificação. Acontece muitas vezes quando você tem um condicional muito curto seguido de uma única declaração muito curta e isso funciona bem. Por exemplo, um if (assert) log.write ("assert falhou");
JohnFx
1

Prefiro chaves para consistência, mas não desperdiçando muito espaço em branco (o código formatado de forma mais legível está no meu campo de visão limitado). Então, eu escrevo isso para linhas curtas o suficiente:

If (cond) { statement; }
hotpaw2
fonte
Interessante, eu realmente não vejo código assim, mas meio que gosto disso.
Thomas Eding
0

Eu costumo usar aparelho, mas há alguns casos em que não uso.

object GetObject() {
    // calculate obj1
    if(obj1 != null)
        return obj1;

    // calculate obj2
    if(obj2 != null)
        return obj2;

    // calculate obj3
    if(obj3 != null)
        return obj3;

    return defaultObj;
}

Para mim, seria tolo adicioná-los lá. Se alguém adicionar uma declaração após a ocorrência return, teremos problemas maiores do que problemas de escopo.

Nota para auto-pensar em um nome
fonte
Você poderia usar com a mesma facilidadereturn (obj != null) ? obj : "Error";
Josh K
@ Josh, veja edit
Note to self - pense em um nome
Nesse caso, eu usaria algo parecido Object returnObj = defaultObj; /* Three else-if's to change it to obj1/2/3 */ return returnObj;.
Josh K
@ Josh, Leia stackoverflow.com/questions/36707/… . Primeiro comentário sobre a primeira resposta: "Embora ter vários pontos de saída possa ficar fora de controle, eu definitivamente acho que é melhor do que colocar toda a sua função em um bloco IF ".
Note to self - pense em um nome
0

Se o IDE tiver formatação de código disponível, não uso chaves.

Por outro lado, onde o código pode ser editado em outros editores que não suportam a formatação automática, é perigoso não colocar chaves como mencionado em outras postagens. Mas mesmo assim eu prefiro não usar aparelho, e isso não foi problema para mim.

nimcap
fonte