O código com comentários pode ser uma documentação valiosa?

79

Eu escrevi o seguinte código:

if (boutique == null) {
    boutique = new Boutique();

    boutique.setSite(site);
    boutique.setUrlLogo(CmsProperties.URL_FLUX_BOUTIQUE+fluxBoutique.getLogo());
    boutique.setUrlBoutique(CmsProperties.URL_FLUX_BOUTIQUE+fluxBoutique.getUrl());
    boutique.setNom(fluxBoutique.getNom());
    boutique.setSelected(false);
    boutique.setIdWebSC(fluxBoutique.getId());
    boutique.setDateModification(new Date());

    boutiqueDao.persist(boutique);
} else {
    boutique.setSite(site);
    boutique.setUrlLogo(CmsProperties.URL_FLUX_BOUTIQUE+fluxBoutique.getLogo());
    boutique.setUrlBoutique(CmsProperties.URL_FLUX_BOUTIQUE+fluxBoutique.getUrl());
    boutique.setNom(fluxBoutique.getNom());
    //boutique.setSelected(false);
    boutique.setIdWebSC(fluxBoutique.getId());
    boutique.setDateModification(new Date());

    boutiqueDao.merge(boutique);
}

Há uma linha comentada aqui. Mas acho que isso torna o código mais claro, tornando óbvia a diferença entre if e else . A diferença é ainda mais notável com destaque de cores.

O comentário de código como este pode ser uma boa ideia?

    
por Alexis Dufrenoy 11.03.2013 / 10:36
fonte

13 respostas

100

A maioria das respostas se concentra em como refatorar esse caso específico, mas deixe-me oferecer uma resposta geral sobre o motivo pelo qual o código comentado geralmente é ruim:

Primeiro, o código comentado não é compilado. Isso é óbvio, mas significa que:

  1. O código pode nem funcionar.

  2. Quando as dependências do comentário mudam, obviamente não irá quebrar.

O código comentado é muito "código morto". Quanto mais tempo ele fica lá, mais ele apodrece e fornece menos e menos valor para o próximo desenvolvedor.

Em segundo lugar, o objetivo não é claro. Você realmente precisa de um comentário mais longo que forneça contexto para o motivo de haver linhas comentadas aleatoriamente. Quando vejo apenas uma linha de código comentada, tenho que pesquisar como ela chegou lá apenas para entender por que ela chegou lá. Quem escreveu isso? O que cometer? Qual foi a mensagem / contexto de commit? Etcetera.

Considere alternativas:

  • Se o objetivo for fornecer exemplos de uso de uma função / api, forneça um teste de unidade. Os testes unitários são códigos reais e serão interrompidos quando não estiverem mais corretos.
  • Se o objetivo é preservar uma versão anterior do código, use o controle de origem. Eu prefiro dar uma olhada em uma versão anterior e alternar os comentários em toda a base de código para "reverter" uma alteração.
  • Se o objetivo for manter uma versão alternativa do mesmo código, use o controle de origem (novamente). É para isso que os ramos são, afinal.
  • Se o objetivo é esclarecer a estrutura, considere como você pode reestruturar o código para torná-lo mais óbvio. A maioria das outras respostas são bons exemplos de como você pode fazer isso.
por 12.03.2013 / 05:25
fonte
257

O maior problema com este código é que você duplicou essas 6 linhas. Depois de eliminar essa duplicação, esse comentário é inútil.

Se você criar um método boutiqueDao.mergeOrPersist , poderá reescrever isso como:

if (boutique == null) {
    boutique = new Boutique();
    boutique.setSelected(false);
}

boutique.setSite(site);
boutique.setUrlLogo(CmsProperties.URL_FLUX_BOUTIQUE+fluxBoutique.getLogo());
boutique.setUrlBoutique(CmsProperties.URL_FLUX_BOUTIQUE+fluxBoutique.getUrl());
boutique.setNom(fluxBoutique.getNom());
boutique.setIdWebSC(fluxBoutique.getId());
boutique.setDateModification(new Date());

boutiqueDao.mergeOrPersist(boutique);

O código que cria ou atualiza um determinado objeto é comum, portanto, você deve resolvê-lo uma vez, por exemplo, criando um método mergeOrPersist . Você certamente não deve duplicar todo o código de atribuição para esses dois casos.

Muitos ORMs criaram suporte para isso de alguma forma. Por exemplo, eles podem criar uma nova linha se o id for zero e atualizar uma linha existente se o id não for zero. A forma exata depende do ORM em questão e, como não estou familiarizado com a tecnologia que você está usando, não posso ajudá-lo com isso.

Se você não quiser criar um método mergeOrPersist , deverá eliminar a duplicação de alguma outra forma, por exemplo, introduzindo um sinalizador isNewBoutique . Isso pode não ser bonito, mas ainda é muito melhor do que duplicar toda a lógica de atribuição.

bool isNewBoutique = boutique == null;
if (isNewBoutique) {
    boutique = new Boutique();
    boutique.setSelected(false);
}

boutique.setSite(site);
boutique.setUrlLogo(CmsProperties.URL_FLUX_BOUTIQUE + fluxBoutique.getLogo());
boutique.setUrlBoutique(CmsProperties.URL_FLUX_BOUTIQUE + fluxBoutique.getUrl());
boutique.setNom(fluxBoutique.getNom());
boutique.setIdWebSC(fluxBoutique.getId());
boutique.setDateModification(new Date());

if (isNewBoutique)
    boutiqueDao.persist(boutique);
else
    boutiqueDao.merge(boutique);
    
por 11.03.2013 / 10:45
fonte
161

Esta é uma ideia absolutamente horripilante . Não deixa claro qual é a intenção. O desenvolvedor comentou a linha por engano? Para testar alguma coisa? O que está acontecendo?!

Além do fato de que eu vejo 6 linhas que são absolutamente iguais em ambos os casos. Em vez disso, você deve evitar essa duplicação de código. Então ficará mais claro que em um caso você também chama setSelected.

    
por 11.03.2013 / 10:41
fonte
117

Não, é uma ideia terrível. Com base nesse pedaço de código, os seguintes pensamentos vêm à minha mente:

  • Esta linha está comentado porque o desenvolvedor estava depurando e esqueceu de restaurar a linha ao estado anterior
  • Esta linha é comentada porque fazia parte da lógica de negócios, mas não é mais o caso
  • Esta linha foi comentada porque causou problemas de desempenho na produção e o desenvolvedor queria ver qual era o impacto em um sistema de produção

Depois de ver milhares de linhas de código comentadas, agora estou fazendo a única coisa sensata quando a vejo: eu a removo imediatamente.

Não há motivo razoável para verificar o código com comentários em um repositório.

Além disso, seu código usa muita duplicação. Eu sugiro que você otimize isso para a legibilidade humana o mais rápido possível.

    
por 11.03.2013 / 10:47
fonte
49

Gostaria apenas de acrescentar à resposta da CodesInChaos, indicando que você pode refatorar ainda mais em pequenos métodos . Compartilhar funcionalidade comum por composição evita condicionais:

function fill(boutique) {    
  boutique.setSite(site);
  boutique.setUrlLogo(CmsProperties.URL_FLUX_BOUTIQUE+fluxBoutique.getLogo());
  boutique.setUrlBoutique(CmsProperties.URL_FLUX_BOUTIQUE+fluxBoutique.getUrl());
  boutique.setNom(fluxBoutique.getNom());
  boutique.setIdWebSC(fluxBoutique.getId());
  boutique.setDateModification(new Date());
}    

function create() {
  boutique = new Boutique();      
  fill(boutique);
  boutique.setSelected(false);
  return boutiqueDao.persist(boutique);
}

function update(boutique) {
  fill(boutiquie);
  return boutiquieDao.merge(boutique); 
}

function createOrUpdate(boutique) {
  if (boutique == null) {
    return create();
  }
  return update(boutique);  
}
    
por 11.03.2013 / 14:33
fonte
23

Embora isso claramente não seja um bom argumento para o código comentado, há uma situação que eu acho que justifica:

// The following code is obvious but does not work because of <x>
// <offending code>
<uglier answer that actually does work>

É um aviso para quem vê mais tarde que a melhoria óbvia não é.

Edit: estou falando de algo pequeno. Se é grande, explique em vez disso.

    
por 12.03.2013 / 04:43
fonte
13

Neste exemplo específico, considero o código com comentários muito ambíguo, em grande parte pelas razões descritas em Resposta do Dibkke . Outros sugeriram maneiras que você poderia refatorar o código para evitar até mesmo a tentação de fazer isso, se isso não for possível por algum motivo (por exemplo, as linhas são semelhantes, mas não perto o suficiente), eu apreciaria um comentário como:

// No need to unselect this boutique, because [WHATEVER]

No entanto, acho que há algumas situações em que deixar (ou até adicionar comentários comentados) código não é repreensível. Ao usar algo como MATLAB ou NumPY, pode-se freqüentemente escrever um código equivalente que 1) itera em um array, processa um elemento por vez ou 2) opera o array inteiro de uma só vez. Em alguns casos, o último é muito mais rápido, mas também muito mais difícil de ler. Se eu substituir algum código por seu equivalente vetorizado, eu incluo o código original em um comentário próximo, assim:

%% The vectorized code below does this:

% for ii in 1:N
%    for jj in 1:N
%      etc.

% but the matrix version runs ~15x faster on typical input (MK, 03/10/2013)

Obviamente, é preciso tomar cuidado para que as duas versões realmente façam a mesma coisa e que o comentário permaneça em sincronia com o código real ou seja removido se o código mudar. Obviamente, as advertências habituais sobre otimização prematura também se aplicam ...

    
por 11.03.2013 / 17:53
fonte
9

A única vez que vi o código comentado foi útil em arquivos de configuração, onde o código para cada opção é fornecido, com muitas opções comentadas. Isso facilita a ativação e a desativação de recursos apenas removendo os marcadores de comentários.

## import this list of modules
# config.imports = ['os', 'sys']
    
por 13.03.2013 / 00:09
fonte
6

De um modo geral, o código é apenas auto-documentado para a pessoa que escreveu o código. Se a documentação for necessária, escreva a documentação. É inaceitável esperar que um desenvolvedor novo em uma base de código fonte possa ler milhares de linhas de código para tentar descobrir, a partir de um alto nível, o que está acontecendo.

Neste caso, a finalidade da linha de código comentada é mostrar a diferença entre duas instâncias de código duplicado. Em vez de tentar documentar a diferença com um comentário, reescreva o código para que ele faça sentido. Então, se você ainda acha necessário comentar o código, escreva um comentário apropriado.

    
por 11.03.2013 / 15:53
fonte
4

Não, o código comentado fica obsoleto e, em pouco tempo, é pior do que inútil, muitas vezes é prejudicial, pois consolida algum aspecto da implementação, juntamente com todas as suposições atuais.

Os comentários devem incluir detalhes da interface e função pretendida; "função pretendida": pode incluir, primeiro tentamos isso, então tentamos isso, então falhamos dessa maneira.

Os programadores que vi tentam deixar as coisas nos comentários são apenas apaixonados pelo que escreveram, não querem perdê-lo, mesmo que não esteja adicionando nada ao produto final.

    
por 11.03.2013 / 19:05
fonte
2

Pode ser em casos muito raros, mas não como você fez. As outras respostas têm muito bem explicado as razões para isso.

Um dos casos raros é um modelo Especificação de RPM que usamos em minha loja como ponto de partida para todos os novos pacotes, em grande parte para garantir que nada importante seja deixado de fora. A maioria, mas nem todos os nossos pacotes têm um tarball contendo fontes que possuem um nome padrão e são especificados com uma tag:

Name:           foomatic
Version:        3.14
 ...
Source0:        %{name}-%{version}.tar.gz

Para pacotes sem fontes, comentamos a tag e colocamos outro comentário acima para manter o formato padrão e indicar que alguém parou e pensou no problema como parte do processo de desenvolvimento:

Name:           barmatic
Version:        2.71
 ...
# This package has no sources.
# Source0:        %{name}-%{version}.tar.gz

Você não adiciona o código que você sabe que não será usado porque, como os outros cobriram, pode ser confundido com algo que pertence a ele. Pode. no entanto, seja útil adicionar um comentário explicando por que o código que se espera estar ausente:

if ( condition ) {
  foo();
  // Under most other circumstances, we would do a bar() here, but
  // we can't because the quux isn't activated yet.  We might call
  // bletch() later to rectify the situation.
  baz();
}
    
por 11.03.2013 / 16:05
fonte
0

O código com comentários não é usado pelo aplicativo, por isso ele precisa ser acompanhado por comentários adicionais que indiquem por que ele não está sendo usado. Mas nesse contexto, Existem situações em que o código comentado pode ser útil.

O que me vem à mente é um caso em que você resolve um problema usando uma abordagem comum e atraente, mas acontece que os requisitos do seu problema real são ligeiramente diferentes daquele problema. Especialmente se suas necessidades acabarem exigindo muito mais código, a tentação dos mantenedores de "otimizar" o código usando a abordagem antiga provavelmente será strong, mas isso só trará o bug de volta. Manter a implementação "errada" nos comentários ajudará a dissipar isso, porque você pode usá-la para ilustrar exatamente por que essa abordagem está errada nessa situação.

Esta não é uma situação que eu possa imaginar ocorrendo com muita frequência. Geralmente, isso deve ser suficiente para explicar as coisas sem incluir uma amostra de implementação "errada". Mas eu posso imaginar um caso em que isso não seja suficiente, então, uma vez que a questão é sobre se pode ser útil, sim, pode. Apenas não na maior parte do tempo.

    
por 12.02.2014 / 17:07
fonte
-2

Isso não parece bom amigo.

O código comentado é ... apenas não é código. Código é para implementação de lógica. Tornar um código mais legível por si só é uma arte. Como @CodesInChaos já sugeriram que linhas repetitivas de código não são muito boas implementações de lógica .

Você realmente acha que um verdadeiro programador preferirá a legibilidade à implementação lógica? (a propósito, temos comentários e 'complementos' para colocar em nossa representação lógica).

No que me diz respeito, deve-se escrever um código para o compilador e isso é bom - se 'entender' esse código. Para a legibilidade humana Os comentários são bons para os desenvolvedores (a longo prazo), para pessoas que reutilizam esse código (por exemplo, testadores).

Caso contrário, você pode tentar algo mais flexível aqui, algo como

boutique.setSite (site) pode ser substituído por

setsiteof.boutique (site). Existem diferentes aspectos e perspectivas da POO através dos quais você pode aumentar a legibilidade.

Embora este código pareça ser muito atraente no início e pode-se pensar que ele encontrou um caminho para a legibilidade humana, enquanto o compilador também faz o seu trabalho perfeitamente, e todos nós começamos a seguir esta prática que levará a um arquivo fuzzy tornar-se menos legível no tempo e mais complexo à medida que se expande.

    
por 11.03.2013 / 13:36
fonte