Devemos incentivar estilos de codificação em favor da autonomia do desenvolvedor ou desencorajá-lo em favor da consistência?

15

Um desenvolvedor escreve if/elseblocos com instruções de código de uma linha, como:

if (condition)
   // Do this one-line code
else
   // Do this one-line code

Outro usa chaves para todos eles:

if (condition) 
{
   // Do this one-line code
}
else
{
   // Do this one-line code
}

Um desenvolvedor instancia primeiro um objeto e depois o usa:

HelperClass helper = new HelperClass();
helper.DoSomething();

Outro desenvolvedor instancia e usa o objeto em uma linha:

new HelperClass().DoSomething();

Um desenvolvedor é mais fácil com matrizes e forloops:

string[] ordinals = new string[] {'First', 'Second', 'Third'};
for (i = 0; i < ordinals.Length; i++)
{
    // Do something
}

Outro escreve:

List<string> ordinals = new List<string>() {'First', 'Second', 'Third'};
foreach (string ordinal in ordinals)
{
    // Do something
}

Tenho certeza que você sabe do que estou falando. Eu chamo isso de estilo de codificação (porque não sei como é chamado). Mas o que chamamos, é bom ou ruim? O incentivo tem um efeito de maior produtividade dos desenvolvedores? Devemos pedir aos desenvolvedores que tentem escrever código da maneira que dizemos, para tornar todo o sistema consistente com o estilo?

Saeed Neamati
fonte
1
Na verdade, eu estava vindo aqui para fazer uma pergunta muito semelhante agora - quando as ferramentas de formatação automática de código estão disponíveis e são convenientes, é mais importante que essas ferramentas não sejam executadas (e preservem estilos pessoais inconsistentes) ou para que um estilo seja aplicado?
macio
O estilo consistente facilita a leitura do código, portanto, use um estilo consistente. Nos seus exemplos, o mais fácil de ler é 2, 1, 2. Embora o último caso seja diferente. Em aplicativos críticos para o desempenho, o loop for é mais rápido ao iterar nas listas. O desempenho é iterativo idêntico nas matrizes. E, em todos os casos, use em varvez do nome completo do tipo.
Stephen

Respostas:

19

Um documento de padrões de codificação é útil. É mais útil quando é curto o suficiente para que alguém possa se lembrar da coisa toda sem muitos problemas e quando não causa muita dor a ninguém.

Como você escolhe recuar o código em sua organização, colocar nomes em maiúscula, implementar seus loops ou comentar seu código não importa tanto; a parte útil é fazer com que todos escrevam um código parecido com o de todos os outros.

  • Isso evita que você gaste um minuto recalibrando sua expectativa de onde os aparelhos devem estar e assim toda vez que você olha o código de outra pessoa.
  • Evita ter vários estilos diferentes de código, todos no mesmo arquivo.
  • Talvez o mais importante seja que ter um padrão escrito evite argumentos sobre práticas de codificação durante as revisões de código.

Novamente, o que são os padrões não importa tanto quanto ter algum tipo de padrão simples e direto. Portanto, coloque todos os seus desenvolvedores em uma sala e deixe-os discutir sobre quais devem ser os padrões. Esta reunião pode durar indefinidamente, portanto as regras são:

  • Tudo o que não for decidido até o final da reunião será decidido pelo gerente.
  • A reunião terminará após duas horas, ou quando alguém começar a gritar ou chorar, o que ocorrer primeiro.
  • Todo o padrão cabe (em tamanho razoável!) Em uma ou duas folhas de papel, frente e verso somente se for absolutamente necessário.

Considere adotar alguém | de outra pessoa | padrões como ponto de partida para sua própria reunião de padrões de codificação ou como uma maneira de evitar a reunião por completo.

Uma vez acordado, os desenvolvedores devem poder (e deve-se) policiar a si mesmos. Desvios ocasionais do padrão não devem ser um grande problema (e podem até ser justificáveis), mas a recusa em abandonar algum estilo pessoal favorito em favor do padrão deve resultar em imediata mudança para o escritório com os canos de água com vazamento, ou o que seja .

Demian Brecht aponta para ferramentas de cotão. Estes são um complemento perfeito para um documento de padrões de codificação. É simplesmente bom manter os padrões de estilo de codificação ; é importante manter os padrões de codificação relacionados a práticas perigosas. Ninguém além do autor verificará se todas as linhas de código atendem ao padrão de estilo, mas você certamente deve considerar a possibilidade de criar uma ferramenta de fiapos no fluxo de trabalho de sua equipe para detectar automaticamente erros prováveis. Além disso, a própria ferramenta pode codificar as práticas aceitas, para que você não precise listá-las todas individualmente nos padrões de codificação; basta especificar a configuração da ferramenta.

Nota: A idéia "padrões de codificação" não é exclusiva da programação. Os "padrões de codificação" são usados ​​em muitos campos, às vezes dentro de uma organização, com mais frequência em toda uma indústria ou profissão. Alguns exemplos:

Em cada caso (e muitos outros), um profissional competente pode entender facilmente "código" que não atende ao padrão esperado. Por que tantas indústrias persistem em escrever requisitos detalhados para documentos que nem precisam ser analisados ​​por um compilador? Porque o estilo é importante . A apresentação de informações em um estilo padrão permite que o leitor se concentre inteiramente no conteúdo, torna a leitura mais rápida, ajuda na compreensão e reduz erros.

Caleb
fonte
1
Se você adicionar o uso de ferramentas linting ao seu post, eu vou apagar minha e +1 seu :)
Demian Brecht
@DemianBrecht, boa sugestão, obrigado. Foram adicionadas ferramentas de cotão para melhorar minha resposta, mas acho que você deve deixar a sua também.
Calebe
Bem, então. +1 de qualquer maneira :)
Demian Brecht
E também para você!
Calebe
+1 na "... realocação imediata ...", como na minha experiência, esse comportamento é consistente com as tendências sociopatas e / ou narcísicas, incompatíveis com as equipes de desenvolvimento de software.
mattnz
16

Estilo não importa.

Lá, eu disse.

Depois de 30 anos e centenas de sites de clientes e código de (estimando) 500 (ou mais) membros da equipe ao longo desses anos, eu descobri que esse estilo simplesmente não importa.

Faça com que funcione primeiro.

Faça com que ele use um volume ideal de recursos (ou seja, estrutura de dados correta, algoritmo correto).

Mexa-se com o "estilo" depois de tudo o mais ter sido resolvido. Confusão de "estilo" apenas com ferramentas, nunca manualmente.

S.Lott
fonte
2
Amém! Os padrões de codificação precisam ser justificados em termos de benefícios reais e a consistência não é um benefício real, mas um luxo.
JohnFx
12
Mas estilo raramente é sobre estilo. Trata-se de evitar erros comuns.
Martin York
6
Mas ajuda a evitar '=' em vez de '==' (não use a atribuição dentro da condição). Isso ajuda a evitar, if (t) { x;y;}e não if (t) x;y;(sempre use '{}' depois de se). Prefira o código correto const (é muito difícil adicionar correção const ao código depois que ele foi gravado. Use std :: cout / std :: cin não fprintf / scanf o primeiro tem muito mais probabilidade de causar erros. Use vetor em vez de matrizes (para ajudar a evitar transbordamentos).
Martin York
5
Obviamente, fazê-lo funcionar é fundamental. Mas só porque funciona não significa que está feito. Ele também precisa ser testado. E depois revisto. Isso tudo pode levar alguns dias. Então, nos anos seguintes, deve ser lido, compreendido e mantido. O código útil (por que escrever outro tipo?) Será lido muitas vezes mais do que está escrito, facilitando a leitura e a compreensão, melhorando a produtividade no futuro. Usar um estilo consistente em toda a organização é uma maneira de ajudar nesse sentido.
Calebe
1
E quanto a impor o uso de ferramentas de formatação automática? O Eclipse e o XCode tornam muito fácil manter o código formatado - mas um dos engenheiros com quem trabalho fica extremamente chateado se alguém formata automaticamente o código "dele" (ou seja, a empresa) para mantê-lo consistente com o restante da base de código. A formatação é apenas uma pequena parte do estilo, mas também é importante, especialmente para questões como aninhamento if / else e fluxo geral de código (para não mencionar a legibilidade).
macio
4

Existem estilos de codificação e cheiros de codificação. Não foi uma vez que eu encontrei:

    if(debugCondition)
//         printf("DEBUG: state:%s at debugCondition\n",dbg_state());

    for(i=0; i<MAX;i++)
    {
       //some essential business logic
    }

Meu empregador anterior proibiu rigorosamente o uso de múltiplas linhas if()sem chaves. Foi considerada uma falha do tipo "faça de novo e você será demitido". As construções permitidas foram

     if(condition) break; 
     if(condition) continue; 
     if(condition) return; 
     if(condition) for()...; 

Isso resultou de um erro como o que eu mostrei acima, que levou algumas horas para parar a página principal do portal.

Há coisas que você sempre deve fazer. Como switch():

     case 1:
         something();
     break;
     case 2:
         something();
     return;
     case 3:
         something();
     continue;
     case 4:
     case 5:
         something();
     break;
     case 6:
         something();
     //fallthrough;
     case 7:
     ...

Enquanto isso, digitando:

     case 1:
         something();
     case 2:
         something();
     break;

sem fechar um casecom //fallthroughé considerado um bug.

Geralmente, existe o padrão de codificação que são as diretrizes que podem ser ignoradas, interpretadas criativamente ou modificadas para determinadas necessidades. E há a seção "cheiros" e deve ser obedecida rigorosamente.

SF.
fonte
3

Crie consistência com um bom design inicial. O que você descreve na pergunta é nada menos que microgerenciamento. Eu faço muito desenvolvimento web. Portanto, sou a favor do desenvolvimento RESTful e CRUD exposto como serviços. Isso garante entidades simples e bem definidas que podem ser usadas de várias maneiras.

Esse design também permite delegar detalhes da implementação a outros desenvolvedores. Dessa forma, eles preenchem os espaços em branco em vez de criar um design de sistema inteiro.

A falta de um design geral cria inconsistências no sistema. A crítica de iterações básicas e construções de loop faz pouco para melhorar o design do sistema. Esses tipos de problemas são melhor resolvidos com uma abordagem prática , StyleCop.

Você pode desenhar um diagrama relativamente simples do design geral do sistema? Um design que descreve os elementos / entidades envolvidos em um novo desenvolvedor de equipe. Se você não puder, ou estiver altamente envolvido, o design estará ausente.

P.Brian.Mackey
fonte
3

IMHO isso depende ...

Seus dois primeiros exemplos não são apenas uma questão de gosto pessoal para mim.

if (condition)
   // Do this one-line code
else
   // Do this one-line code

(sem colchetes) = mais propenso a erros, se mais código for adicionado posteriormente:

if (condition)
   // Do this one-line code
else
   // Do this one-line code
   // ...and this line as well... oops! this will actually execute either way

E isso é menos conveniente para depurar:

new HelperClass().DoSomething(GetSomeData()); // etc.

Você não pode simplesmente definir um ponto de interrupção onde precisar. Se isso é único - é justo o suficiente, mas nós discutimos isso por uma questão de estilo, e uma vez que você tem coisas assim em todo o lugar, a depuração fica mais desagradável do que deveria ser.

Quanto ao seu terceiro exemplo (para vs foreach), eu vejo isso como uma questão de gosto.

Konrad Morawski
fonte
2

Nem. Eu evitaria regras rígidas de codificação para evitar ser tedioso, exigente, microgerencial e, o pior de tudo, perder tempo. Seu senso de autonomia é um problema seu. Se eu quiser que você se sinta melhor, comprarei uma rodada da sua bebida favorita. Fora isso, faça algo.

JeffO
fonte
2

O uso de convenções, nomes de variáveis, nomes de classes etc. é uma boa prática. Porém, estilos de codificação como os exemplos que você fornece são bastante triviais e não afetam a legibilidade ou a eficiência do código. Por outro lado, a sobrecarga de impor um determinado estilo combinado com o esforço dos desenvolvedores em segui-lo causará problemas.

AJC
fonte
2

Use uma ferramenta de fiapos padrão do setor (aparentemente FxCop para C #). Embora não seja a consistência final, tudo é importante em grandes projetos que têm várias pessoas trabalhando neles.

Se você está apenas trabalhando em seu próprio projeto ou em uma equipe pequena, muitos argumentam que é um exagero. Eu acredito no contrário (eu uso o PEP8 para Python, mesmo em meus projetos pessoais de desenvolvedor único).

A maioria dos exemplos que você deu, no entanto, provavelmente não seria pega por uma ferramenta de fiapos, pois eles simplesmente não importam.

Demian Brecht
fonte
1

A imposição de um estilo de codificação uniforme é sempre difícil. Idealmente, essa tarefa mundana deve ser deixada a cargo de uma ferramenta. Aplaudo a comunidade de idiomas Go por fazer isso.

grokus
fonte
1

É uma mistura de ambos. Só porque é um padrão, não o torna legível e sustentável. Se ainda não existe um padrão instilado ou se há aspectos defeituosos e ilegíveis, a revisão é apropriada.


fonte
1

Na análise final, é o programador que conduz a programação. Existem problemas de estilo, mas são secundários à divulgação do programa.

É útil dar aos programadores algumas orientações de estilo. Isso pode / deve ser feito antes que os programadores sejam colocados em funcionamento, especialmente se eles são iniciantes em relação ao ambiente ou à própria programação. Dada a orientação, alguns programadores terão muito estilo, outros menos. As orientações fornecidas no início do projeto ajudarão o primeiro grupo de programadores, facilitando assim a tarefa geral. Isso pode fazer pouco para o segundo grupo, que (espero) compensará em criatividade o que falta em conformidade.

Tom Au
fonte
1

Eu acho que tudo se resume ao tamanho do projeto e quantas pessoas estão trabalhando nele. Um programador experiente pode olhar para os dois estilos de formato diferentes e saber o que estava acontecendo nos dois, mas é preciso haver uma coerção para que os olhos possam vê-lo facilmente. Se você vai fazer suas declarações de linha única sem as chaves de curvatura, esse projeto não deve usá-las. Quem lidera esse projeto deve ter essa opção. Eu gosto que as coisas pareçam bem definidas e também muito compactas, pois eu as consigo. Se você for criar uma única linha se os estatutos melhor se parecerem com isso

if() {}
else() {}

Ou até:

if() {} else () {}

Mas uma única linha se não deve usar o espaçamento de uma mulitilina se. É assim que eu faço as coisas. Eu não me importo com a maneira como o objeto é chamado e isso depende de quantas vezes ele é chamado. se for chamado algumas vezes, prefiro iniciar o objeto e depende se ele possui construtores e o que não é também. Porque se você tem um construtor e chama:

Object.method();
Object.method2();

Em seguida, você acabou chamando o método de construção de objeto duas vezes quando poderia ter sido evitado instanciando o objeto completamente.

Quando se trata de foreach e loops Também é sobre o lanauge, alguns lanauges oferecem melhor controle ao olhar para a matriz em um loop foreach, para que você tenha a chave e o valor nas matrizes temporárias. E eu sei que algumas linguagens têm algum tipo de otimização porque podem olhar para o loop e saber exatamente quantas vezes serão chamadas.

WojonsTech
fonte
1

Embora seu primeiro exemplo não seja ótimo (o argumento de que é mais propenso a erros sob modificação tem algum peso), em geral, na verdade, comecei a preferir que os desenvolvedores usem estilos de codificação ligeiramente diferentes.

Depois de trabalhar com o código de outros membros da equipe, às vezes por apenas alguns meses, ele basicamente começa a trabalhar linha a linha git blame . Depois de estar na minha empresa há mais de 10 anos, provavelmente posso dizer com mais de 80% de precisão quem escreveu qualquer classe em qualquer lugar em nossas 500 mil linhas de código, apenas olhando para ela.

Embora exista um pouquinho de "tempo de rampa" quando você começa a olhar para o código que usa um estilo com o qual não concorda, o que realmente está fazendo nesse momento é dizer "oh, isso parece o código de John Doe (porque ele usa o estilo X, mas não o estilo Y, etc.) ". E isso traz consigo um monte de contexto. Para uma primeira aproximação, você sabe o que esperar do código de John - que outras partes da base de código ele entende bem e que partes não, se ele é um guru de SQL ou um novato em GUI, etc. etc.

A execução do código de todos através de um formatador retira essas informações, escondendo-as atrás de um git blame, que você pode não se dar ao trabalho de executar.

Matt McHenry
fonte
0

Isso realmente depende muito do tipo de organização.

Se você é um pequeno grupo de super-heróis, qualquer tipo de estilo é adequado. Se todo mundo tem seu próprio estilo, e é bom e consistente internamente, esse é todo o processo que você precisa. Os super-heróis dirão: "Jane tem colchetes, então é isso que ela quer dizer" ou "Jack usa camelCase para variáveis".

Os padrões universais tendem a ser melhores para tornar todos um jogador B +. Seus super-heróis serão atraídos por isso. Mas se você deseja que um jogador A e meia dúzia de jogadores B e meia dúzia de jogadores C atinjam a média do B +, então deseja padrões consistentes. Nesse caso, você quer que todos façam o mesmo para que o jogador A possa percorrer o código de todos o mais rápido possível.

Muitos de vocês comentam: "Mas espere, por que não acabar com os jogadores de B e C?"

A realidade é que não existem muitos super-heróis. Embora possa pagar para encontrá-los e nutri-los no Google, a criação de um novo sistema de cobrança para a Ma Bell pode ser mais econômica com a última equipe. (E se você realmente tiver super-heróis, 4 ou 5 deles serão duas vezes mais caros que uma dúzia de juniores)

MathAttack
fonte