Por que os desenvolvedores C # abrem os colchetes de abertura? [fechadas]

37

Passei a maior parte dos últimos anos trabalhando principalmente com C # e SQL. Todo programador com quem trabalhei nesse período tinha o hábito de colocar a chave de abertura de uma função ou uma instrução de fluxo de controle em uma nova linha. Então ...

public void MyFunction(string myArgument)
{
     //do stuff
}

if(myBoolean == true)
{
    //do something
}
else
{
    //do something else
}

Sempre fiquei impressionado com o quanto esse espaço é um desperdício, especialmente em declarações if / else. E eu sei que existem alternativas em versões posteriores do C #, como:

if(myBoolean == true)
    //do something on one line of code

Mas quase ninguém usou. Todo mundo fez a coisa de chave-na-nova-linha.

Depois voltei a fazer JavaScript depois de uma longa ausência. Na minha memória, os desenvolvedores de JavaScript costumavam fazer exatamente a mesma coisa, mas com todas as novas bibliotecas e coisas novas, a maioria dos desenvolvedores colocava a chave de abertura após a declaração:

function MyJavaScriptFunction() {
    //do something
}

Você pode ver o sentido disso, porque desde que o uso de closures e ponteiros de função se tornou popular em JavaScript, ele economiza muito espaço e torna as coisas mais legíveis. Então eu me perguntava por que não era visto como o feito em C #. Na verdade, se você tentar a construção acima no Visual Studio 2013, ela realmente reformata para você, colocando a chave de abertura em uma nova linha!

Agora, acabei de ver esta pergunta no Code Review SE: link Em que eu aprendi que em Java, uma língua que eu não estou muito familiarizado, é considerado de-rigor para abrir suas chaves após a declaração, na forma moderna de JavaScript.

Eu sempre entendi que o C # foi originalmente modelado depois do Java, e mantive muitos dos mesmos padrões de codificação basal. Mas neste caso, parece que não. Então presumo que deve haver uma boa razão: qual é o motivo? Por que os desenvolvedores C # (e o Visual Studio) aplicam as chaves de abertura em uma nova linha?

    
por Matt Thrower 25.04.2014 / 15:07
fonte

4 respostas

62

A chave no final da linha é o antigo padrão K & RC, do livro de Brian Kernighan e Dennis Ritchie A Linguagem de Programação C , que publicaram em 1978 depois de co-inventar o sistema operacional UNIX e a linguagem de programação C (acho que o C foi projetado principalmente por Ritchie), na AT & T.

Costumava haver guerras flamejantes sobre "o único estilo de chave verdadeira".

Ritchie inventou a linguagem C, e Kernighan escreveu o primeiro tutorial, quando a tela do computador mostrava apenas algumas linhas de texto. Na verdade, o desenvolvimento do UNICS (posterior UNIX) começou em um DEC PDP-7, que usava uma máquina de escrever, uma impressora e uma fita de papel para uma interface de usuário. O UNIX e o C foram finalizados no PDP-11, com terminais de texto de 24 linhas. Então, o espaço vertical era de fato um prêmio. Todos nós temos monitores ligeiramente melhores e impressoras de maior resolução hoje, certo? Quero dizer, eu não sei sobre você, mas eu tenho três (3) displays de 24 "1080p na minha frente agora: -)

Além disso, muito desse pequeno livro A linguagem de programação C é código amostras que colocam as chaves nas extremidades das linhas em vez de em suas próprias linhas supostamente economizaram uma quantia considerável de dinheiro na impressão.

O que é verdadeiramente importante é a consistência ao longo de um projeto, ou pelo menos dentro de um determinado arquivo de código-fonte.

Existem também estudos científicos que mostram que a chave em sua própria linha (recuada no mesmo nível do código, na verdade) melhora a compreensão do código, apesar do que as pessoas pensam da estética. Isso deixa muito claro para o leitor, visualmente e instintivamente, qual código é executado em qual contexto.

if( true )
    {
    // do some stuff
    }

O C # tem sempre suporte para avaliar um único comando após uma expressão de ramificação, a propósito. Na verdade, é a única coisa que faz, mesmo agora. Colocar o código entre chaves depois de uma expressão de ramificação apenas faz com que um comando goto (o compilador cria o escopo usando instruções jmp). C ++, Java, C # e JavaScript são mais ou menos baseados em C, com as mesmas regras subjacentes de análise, na maior parte. Então, nesse sentido, o C # não é "baseado em Java".

Resumindo, isso é uma questão religiosa / de guerra de chamas. Mas há estudos deixando bem claro que organizar código em blocos melhora a compreensão humana . O compilador não poderia se importar menos. Mas isso também está relacionado com a razão pela qual eu nunca coloquei uma linha de código depois de um branch sem chaves - é muito fácil para mim ou outro programador colocar outra linha de código lá mais tarde e escorregar no fato de que não executar no mesmo contexto com a linha logo antes ou depois.

EDITAR : Basta procurar o bug goto fail da Apple para obter um exemplo perfeito desse problema exato, que teve consequências muito sérias no mundo real.

if( true )
    doSomething();

torna-se ...

if( true )
    doSomething();
    doSomethingElse();

Nesse caso, doSomethingElse() é executado sempre, independentemente do resultado do teste, mas como é recuado para o mesmo nível da instrução doSomething() , é fácil ignorar. Isso não é realmente discutível; estuda isso de volta. Esta é uma grande fonte de erros introduzidos no código-fonte durante a manutenção.

Ainda assim, admito que a sintaxe de fechamento do JavaScript parece um pouco boba com chaves em suas próprias linhas ... esteticamente. : -)

    
por 25.04.2014 / 16:37
fonte
27

A razão pela qual os desenvolvedores de C # fazem isso é porque é a configuração padrão do formatador automático do Visual Studio. Embora essa configuração possa ser alterada, a maioria das pessoas não o faz e, portanto, todos os desenvolvedores de uma equipe precisam ir com a maioria.

Por que esse é o padrão no Visual Studio, eu não sei.

    
por 25.04.2014 / 16:32
fonte
15

Como eu especulei nesta resposta aqui - link - Eu suponho que a decisão de usar o aparelho de Allman poderia ser um sinal da herança de Pascal, dado que Hejlsberg criou o Delphi antes de projetar o C #. Igual ao caso do Pascal para nomes de métodos.

Pessoalmente, acredito em seguir o provérbio "em Roma, como fazem os romanos". Eu uso o Allman's em C #, mas o K & R em Java. Estou tão acostumada a isso que mudar a convenção de qualquer maneira é chocante para mim.

Acredito que a diversidade de convenções é realmente benéfica para um desenvolvedor "multilíngue", pois ajuda a lembrar em qual idioma eles estão codificando no momento e facilita a diferenciação de vários hábitos. É um equivalente mental da memória muscular, por assim dizer.

    
por 25.04.2014 / 16:59
fonte
12

A convenção que você associa ao Java é o estilo K & R ou o "estilo de um verdadeiro colchete" e vem originalmente de C. Esta página indent-style do venerável Arquivo Jargon mostra a idade da distinção.

Sempre achei que o estilo Allman e suas variantes são um reflexo de como os autores pensam sobre código, elevando os delimitadores de bloco ao nível de palavras-chave semelhantes a como alguns idiomas usam "begin" e "end" em torno de blocos de código.

    
por 25.04.2014 / 16:26
fonte