/ Agile

Clean Code - Comentários

Olá pessoal, até aqui vimos recomendações do Robert C. Martin sobre Nomes Significativos e Funções. Neste artigo vamos abordar um assunto polêmico, comentários no código

Nada pode ser tão útil quanto um comentário bem colocado. Porém nada pode ser tão prejudicial quanto comentários desnecessários e supérfluos, no máximo os comentários são um mal necessário.

O uso adequado de comentários compensam nosso fracasso em nos expressar no código, comentários são utilizados quando não encontramos outra forma de nos expressar adequadamente. Portanto, quando você estiver numa situação na qual precise criar um comentário, pense bem e veja se não há uma maneira melhor de se expressar através do código.

Ao utilizar comentários lembre-se de que as tecnologias estão em constante evolução e seus comentários podem se tornar antiquados ou desatualizados. Muitas das vezes os comentários mentem, quanto mais antigo e mais longe do trecho que ele descreve, mais provável que esteja errado.

Comentários Compensam um Código Ruim

Uma das motivações mais comuns para criar comentários é um código ruim. Temos ciência da bagunça que criamos e adicionamos um comentário com o pensamento de que o código será melhor, quando na verdade ainda temos um código ruim sendo poluído com comentários ruins.

Códigos claros e expressivos com poucos comentários são de longe superiores a um amontoado e complexo com muitos comentários. Ao invés de perder seu tempo criando comentários utilize para limpar e melhorar o código.

Explique-se no Código

Há vezes em que não é possível se expressar direito no código. Infelizmente muitos programadores assumiram que o código é um bom meio para se explicar. Evidentemente isso é falso, o que você prefere ver em um código?
Isso:

//verifica se o funcionário é apto aos benefícios
if ((employee.flags & HOURLY_FLAG) &&
(employee.age > 65))

ou isso?

if (employee.isEligibleForFullBenefits())

Passe algum tempo pensando em como ter expressividade no seu código, com certeza não será um tempo perdido. Muitas das vezes a mudança é apenas nomear as funções com o que você tem em mente para um comentário.

Comentários bons

Certos comentários são necessários ou benéficos. Entretanto tenha em mente que o único comentário verdadeiramente bom é aquele em que você encontrou uma forma de não escrevê-lo.

Comentários Legais

Às vezes nossos padrões de programação corporativa nos forçam a escrever certos comentários por questões legais. Então devemos adicionar um comentário padrão no cabeçalho dos arquivos, contendo as informações sobre direitos autorais da aplicação.
Sempre que possível coloque estes comentários em arquivos externos.

Comentários Informativos

Às vezes precisamos fornecer informações básicas sobre uma funcionalidade, seja pelo valor ou pelo formato retornado pelas variáveis. caso o nome da função já informe o leitor, então deve-se ignorar o comentário, mas é aceitável criar um comentário informativo para esta situação.

Muitas vezes um comentário vai além de ser apenas informações úteis sobre a implementação, ele fornece a intenção por trás de uma decisão. O esclarecimento sobre a utilização de parâmetros também é aceitável.

Há um risco considerável de que um comentário esclarecedor possa estar incorreto, então também assuma os riscos e certifique-se de torná-los mais precisos.

Ruim:

function hashIt(data) {
  // A hash
  let hash = 0;

  // Tamanho da string
  const length = data.length;

  // Loop em cada caracter da informação
  for (let i = 0; i < length; i++) {
    // Pega o código do caracter.
    const char = data.charCodeAt(i);
    // Cria a hash
    hash = ((hash << 5) - hash) + char;
    // Converte para um integer 32-bit
    hash &= hash;
  }
}

Bom:

function hashIt(data) {
  let hash = 0;
  const length = data.length;

  for (let i = 0; i < length; i++) {
    const char = data.charCodeAt(i);
    hash = ((hash << 5) - hash) + char;

    // Converte para um integer 32-bit
    hash &= hash;
  }
}

Alerta Sobre consequências

As consequências da execução e manutenção de determinados trechos podem estar em comentários. O comentário pode auxiliar o leitor a identificar as consequências e permite uma ação prévia, como:

\\execute apenas se tiver tempo disponível
await browser.waitFor(1000000000);

Comentário TODO

Os comentários podem elencar os próximos passos a fazer. TODOs são tarefas que os programadores acham que devem ser efetuadas, mas por alguma razão não podem implementá-las no momento. Podem ser um lembrete sobre uma alteração que deve ser feita, um pedido para a verificação de outro membro.

Hoje em dia, a maioria das IDEs oferecem ferramentas e recursos para localizar os comentários TODO; portanto não é provável que fiquem perdidos no código. Revise regularmente seu código e elimine os comentários TODO.

Comentários Ruins

Quase todos os comentários caem nesta categoria, geralmente os comentários se tornam suporte ou desculpas para um código de baixa qualidade.

Murmúrio

Usar um comentário que não fará sentido ao leitor, simplesmente é um comentário sobre as frustrações na hora da codificação são tidos como murmúrios e não agregam valor ao projeto.

public void loadProperties(){
    try{
        String propertiesPath = propertiesLocation + “/” + PROPERTIES_FILE;
            FileInputStream propertiesStream = new FileInputStream(propertiesPath);
            loadedProperties.load(propertiesStream);
}
    catch(IOException e){
        //Nenhum arquivo de propriedades, significa que todos os padrões estão carregados
    }
}

O que o comentário no bloco catch significa? É um trecho que faz sentido para o autor mas não é bem transmitido. O autor estava limpando sua consciência por manter um bloco catch vazio ou tentou deixar um marcador para retornar e implementar o código que carrega os padrões.

Comentários Enganadores

Às vezes, mesmo com as melhores intenções, o programador faz uma afirmação não muito clara em seus comentários. Uma pequena desinformação expressada em comentário pode dificultar a leitura e provocar erros futuros.

// Utility method that returns when this.
closed is true. Throws an exception
// if the timeout is reached.
public synchronized void waitForClose(
final long timeoutMillis)
throws Exception{
    if(!closed){
        wait(timeoutMillis);
        if(!closed)
            throw new Exception("MockResponseSender 
            could not be closed");
    }
}

O comentário deste trecho indica que o método retorna quando a variável closed é verdadeira. O trecho apenas aguarda um tempo e após lança uma exceção. Imagine que um programador despreocupadamente chame essa função esperando que ela retorne o valor expressado no comentário e o valor retornado é outro, seria uma complicação e tanto para esse programador.

Comentários ruidosos

Por vezes os comentários não são nada além de chiados, que dizem obviedades e não fornecem novas informações sobre o código. Estes comentários levam ao leitor a ignorá-los, com o tempo os olhos passam direto por eles e conforme a manutenção do código estes comentários passam a mentir.

Marcadores de Posição

Alguns programadores gostam de marcar uma posição determinada no arquivo fonte, como:

for(var i in itens){
    /.../
}//for////

Raramente as junções por comentários fazem sentido em certas funções, mas de modo geral eles são aglomerações e devemos excluí-los. Tenha em mente que indicadores são chamativos no código, use-os esporadicamente para não se tornarem ruídos.

Código em comentários

Nunca, nunca mesmo, deixe código comentado no corpo de seu arquivo. Outros desenvolvedores que tiverem o contato com esse código não teriam coragem de excluir os comentários, pois passam a impressão de que estão lá por um motivo e são importantes demais para serem apagados. Essa prática tende a acumular comentários desnecessários e leva o leitor à uma confusão.

InputStreamResponse response = new InputStreamResponse();
response.setBody(formatter.getResultStream(), 
formatter.getByteCount());
//InputStream resultsStream = formatter.getResultStream();
//StreamReader reader = new StreamReader(resultsStream);
//response.setContent(reader.read(formatter.getByteCount()));

Informações não-locais

O comentário deve estar próximo ao código que ele descreve. Não forneça informações gerais do sistema no contexto de um comentário local. Considere por exemplo o comentário do Javadoc abaixo. Além de ser terrivelmente redundante, ele também fala sobre uma porta padrão que a função ainda não tem acesso.

/**
* Port on which fitnesse would run. Defaults to 8082.
*
* @param fitnessePort
*/
public void setFitnessePort(int fitnessePort){
    this.fitnessePort = fitnessePort;
}

Cabeçalhos de funções e fechamentos

É muito comum adicionarmos cabeçalhos em funções para passar alguma informação sobre a próxima função, porém funções curtas não requerem muita explicação. Um nome bem selecionado costuma ser melhor do que um comentário no cabeçalho.

Também são desnecessários os comentários de fechamento das ações e blocos, eles não contribuem em nenhum aspecto. Uma boa formatação substitui os comentários de fechamento.

Conclusão

Todos os comentários são ruins em nosso código, porém são necessários em algumas situações. Saiba analisar a situação e a necessidade de adicionar comentários, não há nada mais prejudicial que um comentário ruim. Sempre que possível se expresse por meio do código, isso evita a criação de comentários.

Referências

Robert C. Martin, Clean Code: A Handbook of Agile Software Craftsmanship.
Disponível em https://www.investigatii.md/uploads/resurse/Clean_Code.pdf.

Augusto, Felipe. Conceitos de Código Limpo.
Disponível em https://github.com/felipe-augusto/clean-code-javascript#Índice