Anotações Capítulo 4: Comments
Tags: books, codequality
Published: 2021-05-18 20:36:31

- **“Não insira comentários num código ruim, reescreva-o”**.

- Nada pode ser tão útil quanto um comentário bem colocado. Nada consegue amontoar um módulo mais do que comentários dogmáticos e supérfluos. Nada pode ser tão prejudicial quanto um velho comentário mal feito que dissemina mentiras e informações incorretas.

- Comentários são, no máximo, um mal necessário.

- “O uso adequado de comentários é para compensar nosso fracasso em nos expressar no código”.
Quando precisar “criar um comentário, pense bem e veja se não há como se expressar através do código em si”.

- **Comentários geralmente são mentirosos, principalmente aqueles antigos, isso porque os programadores não conseguem manter eles atualizados**.

- Códigos mudam e evoluem, e nem sempre os comentários os acompanham. E geralmente ficam longe do código o qual descrevem.

- Comentários imprecisos são muito piores do que nenhum. Eles enganam e iludem.

- **“Só se pode encontrar a verdade em um lugar: no código”**.

## Comentários Compensam um Código Ruim

- Uma das motivações mais comuns para criar comentários é um código ruim.

- Quando estamos cientes da bagunça, pensamos que é melhor inserir um comentário. **Não! É melhor limpá-lo**.

- Ao invés de criar comentários para explicar a bagunça, você deve limpar a zona.

## Explique-se no código

- Há vezes em que não é possível se expressar direito no código;

- Mais em vez de termos:
```
// Check to see if the employee is eligible for full benefits
if ((employee.flags & HOURLY_FLAG) && (employee.age > 65))
```
- Seria melhor criar uma função cujo o nome diga a mesma coisa que você deseja colocar no comentário:
```
if (employee.isEligibleForFullBenefits())
```

## Comentários Bons
- Certos comentários são necessários ou benéficos.
- Tenha em mente, que o único comentário bom é aquele em que você encontrou uma forma para não escrevê-lo.

### Comentários Legais
- Às vezes somos forçados a escrever comentários;
- Frases sobre direitos autorais e autoria são necessárias e lógicas para se colocar no início de um arquivo fonte.

### Comentários Informativos

- Às vezes é prático fornecer informações básicas em um comentário. Por exemplo:
```
// Returns an instance of the Responder being tested.
protected abstract Responder responderInstance();
```
É um comentário útil, mas sempre que possível é melhor usar o nome da função para transmitir a informação.

- Outro exemplo:
```
// format matched kk:mm:ss EEE, MMM dd, yyyy
Pattern timeMatcher = Pattern.compile("\\d*:\\d*:\\d* \\w*, \\w* \\d*, \\d*");
```
Esse comentário nos permite saber que a expressão regular deve combinar com uma hora e data formatadas com a função `SimpleDateFormat.format` usando a string específica com o formato.

### Explicação da intenção
- Às vezes, um comentário vai além de ser apenas informações úteis sobre a implementação e fornece a intenção por trás de uma decisão.
- Exemplo:
```
public void testConcurrentAddWidgets() throws Exception {
    WidgetBuilder widgetBuilder = new WidgetBuilder(new Class[ {BoldWidget.class});
    String text = "'''bold text'''";
    ParentWidget parent = new BoldWidget(new MockWidgetRoot(), "'''bold text'''");
    AtomicBoolean failFlag = new AtomicBoolean();
    failFlag.set(false);

    // Essa é a nossa melhor tentativa para conseguir uma condição de corrida.
    // Para isso criamos um grande número de threads.
    for (int i = 0; i < 25000; i++) {
        WidgetBuilderThread widgetBuilderThread = new  WidgetBuilderThread(widgetBuilder, text, parent, failFlag);
        Thread thread = new Thread(widgetBuilderThread);
        thread.start();
    }
    assertEquals(false, failFlag.get());
}
```
### Esclarecimento

- Às vezes é bom traduzir o significado de alguns parâmetros ou valores obscuros para algo inteligível. Exemplo:
```
public void testCompareTo() throws Exception {
    WikiPagePath a = PathParser.parse("PageA");
    WikiPagePath ab = PathParser.parse("PageA.PageB");
    WikiPagePath b = PathParser.parse("PageB");
    WikiPagePath aa = PathParser.parse("PageA.PageA");
    WikiPagePath bb = PathParser.parse("PageB.PageB");
    WikiPagePath ba = PathParser.parse("PageB.PageA");

    assertTrue(a.compareTo(a) == 0); // a == a
    assertTrue(a.compareTo(b) != 0); // a != b
    assertTrue(ab.compareTo(ab) == 0); // ab == ab
    assertTrue(a.compareTo(b) == -1); // a < b
    assertTrue(aa.compareTo(ab) == -1); // aa < ab
    assertTrue(ba.compareTo(bb) == -1); // ba < bb
    assertTrue(b.compareTo(a) == 1); //  b > a
    assertTrue(ab.compareTo(aa) == 1); // ab > aa
    assertTrue(bb.compareTo(ba) == 1); // bb > ba
}
```
Há um risco de um comentário esclarecedor possa estar incorreto. 

### Alerta Sobre Consequências
- Às vezes é útil alertar sobre certas consequências. Por exemplo:
```
// **Não execute a menos que você tenha tempo disponível.**
public void _testWithReallyBigFile() {
    writeLinesToFile(10000000);

    response.setBody(testFile);
    response.readyToSend(this);
    String responseString = output.toString();
    assertSubString("Content-Length: 1000000000", responseString);
    assertTrue(bytesSent > 1000000000);
}
```
O comentário acima explica por que um caso de teste em particular está desabilitado.

- Porém atualmente desabilitamos o teste deste caso através do atributo `@Ignore` com uma string explanatória adequada: `@Ignore(“Leva muito tempo para executar”)`.

- Outro exemplo:
```
public static SimpleDateFormat makeStandardHttpDateFormat() {
    //SimpleDateFormat não é uma thread segura,
    //é preciso criar cada instância independentemente.
    SimpleDateFormat df = new SimpleDateFormat("EEE, dd MMM yyyy HH:mm:ss z");
    df.setTimeZone(TimeZone.getTimeZone("GMT"));
    return df;
}
```

### Comentário TODO
- Às vezes é cabível deixar notas “To Do” (“Fazer”) em comentários no formato `//TODO`. Exemplo:
```
// TODO-MdM essas não são necessárias
// Esperamos que isso não esteja mais aqui quando verificarmos o modelo
protected VersionInfo makeVersion() throws Exception {
    return null;
}
```

- `TODOs` são tarefas que os programadores acham que devem ser efetuadas, mas, por alguma razão, não podem no momento. Pode ser um lembrete para excluir uma instrução desnecessária ou um apelo para que alguém olhe o problema.
- Seja qual for o `TODO`, ele não justifica deixar um código ruim no sistema.
- Procure-os regularmente e elimine os que puder.

## Destaque
- Pode-se usar um comentário para destacar a importância de algo que talvez pareça irrelevante:
```
String listItemContent = match.group(3).trim();
// a função trim é muito importante. Ela remove os espaços
// iniciais que poderiam fazer com o item fosse
// reconhecido como outra lista
new ListItemWidget(this, listItemContent, this.level + 1);
return buildList(text.substring(match.end()));
```

### Javadocs em APIs Públicas
Não há nada de tão prático e satisfatório como uma API pública descrita. Como os javadocs, seria difícil escrever programas Java sem eles. 
Mas esses comentários também podem ser enganadores e desonestos como qualquer outro tipo de comentário.

## Comentários Ruins
A maioria dos comentários cai nesta categoria. Geralmente eles são suportes ou desculpas para um código de baixa qualidade.

### Murmúrio
- Usar um comentário só porque você sente que deve ou porque o processo o requer é besteira. Se for criar um comentário, crie um bom comentário.
- Exemplo:
```
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.
    }
}
```
Não conseguimos entender o que o autor quis dizer. Podemos entender que se cairmos no `catch`, todos os padrões estão carregados. Mas quem carrega os padrões? Como foi esse processo? Será que o autor adicionou apenas para não deixar o bloco `catch` vazio? Ou ele estava dizendo para ele mesmo para voltar depois e escrever o código que carregaria os padrões?
A alternativa para entender o código seria ver outras partes do sistema para entender. 

- **Assim, qualquer comentário que lhe obrigue a analisar outro módulo em busca de significado não vale os bits que consome**.

### Comentários Redundantes

- Um comentário redundante provavelmente podemos  levar mais tempo para lê-lo do que o código em si. Exemplo:
```
// Método utilitário que retorna quando this.closed é verdadeiro. 
// Lança uma exceção se o tempo limite for atingido.
public synchronized void waitForClose(final long timeoutMillis) throws Exception {
    if(!closed) {
        wait(timeoutMillis);
        if(!closed) 
            throw new Exception("MockResponseSender could not be closed");
    }
}
```
Esse comentário não tem propósito, certamente não é mais informativo do que o código. Não segue nenhum dos tópicos abordados anteriormente.

### Comentários Enganadores
No exemplo anterior, o comentário indica que o método retornava quando `this.closed` **virava** `true`, mas só se o `this.closed` **já fosse** `true`, caso contrário, ele esperava por um tempo limite e então lançava uma exceção, caso o `this.closed` **não fosse** `true`.
Além de redundante, o comentário ainda estava incorreto com o que realmente acontecia no método.

### Comentários Imperativos
É tolice ter uma regra dizendo que toda função deva ter um Javadoc, ou toda variável um comentário. Só serão prejudiciais ao código, gerando mentiras e desorganização. Exemplo:
```
/**
*
* @param title The title of the CD
* @param author The author of the CD
* @param tracks The number of tracks on the CD
* @param durationInMinutes The duration of the CD in minutes
*/
public void addCD(String title, String author, int tracks, int durationInMinutes) {
    CD cd = new CD();
    cd.title = title;
    cd.author = author;
    cd.tracks = tracks;
    cd.duration = duration;
    cdList.add(cd);
}
```
### Comentários Longos

Às vezes, as pessoas, toda vez que editam um código, adicionam um comentário, e após várias alterações, a quantidade de comentários acumulada parece mais uma redação ou um diário.

Antes era necessário esses comentários, porém hoje com os sistemas de controle de código se encarregam dessa função.

### Comentários Ruidosos
Às vezes você vê comentários que nada são além de “chiados”. Eles dizem o óbvio e não fornecem novas informações.
```
/**
* Default constructor.
*/
protected AnnualDateRule() {
}
```
Ou:
```
/** The day of the month. */
private int dayOfMonth;
```
São totalmente irrelevantes que ignoramos. No final eles passam a “mentir” 
conforme o código muda.

- “Troque a tentação para criar ruídos pela determinação para limpar seu código”.

### Ruídos assustadores
Os javadocs também podem ser vistos como ruídos. Qual o objetivo dos Javadocs de uma biblioteca de código livre bem conhecida?

Geralmente, podem conter erros de cópia já que os programadores não prestam atenção na hora de escrevê-los.

### Evite o comentário se é possível usar uma função ou uma variável

Veja o código:
```
// o módulo da lista global <mod> depende do
// subsistema do qual fazemos parte?
if (smodule.getDependSubsystems().contains(subSysMod.getSubSy tem()))
```
Poderíamos evitar o comentário da seguinte forma:
```
ArrayList moduleDependees = smodule.getDependSubsystems();
String ourSubSystem = subSysMod.getSubSystem();
if (moduleDependees.contains(ourSubSystem))
```
Nesse caso o autor pode ter escrito o comentário primeiro e depois o código, o correto seria ele refatorar o código e deixamos como nossa segunda forma.

### Marcadores de Posição

Algumas vezes os programadores gostam de marcar uma posição determinada no arquivo fonte. Exemplo:
```
// Actions //////////////////////////////////
```
Só use indicadores quando gerarem benefícios significativos. Se usar excessivamente, eles se tornarão ruídos e serão ignorados.

### Comentários ao lado de chaves de fechamento

Às vezes, os programadores colocam comentários ao lado de chaves de fechamento. Embora isso possa fazer sentido em funções longas com estruturas muito aninhadas. Nesse caso é melhor reduzir as funções. Exemplo:
```
public class wc {
    public static void main(String[] args) {
        BufferedReader in = new BufferedReader(new InputStreamReader(System.in));
        String line;
        int lineCount = 0;
        int charCount = 0;
        int wordCount = 0;
        try {
            <códigos aqui>
        } // try
        catch (IOException e) {
            System.err.println("Error:" + e.getMessage());
        } //catch
    } //main
}
```

### Créditos e autoria
```
/* Adicionado por Rick */
```
Os sistemas de controle de versão já fazem essa função, portanto não há necessidade de poluir o código com esses tipos de comentários.

### Explicação do código em comentários

- Poucas práticas são tão condenáveis quanto explicar o código nos comentários.
- **Não faça isso!**
- Podem fazer com que outros tenham medo de excluir os comentários por pensarem que são importantes.
- É uma grande sujeira!
- Não precisamos deixar código comentado para lembrar deles, exclua o código e os sistemas de controle de versão se lembraram desse código excluído e nunca o perderemos.

### Comentários HTML
- “Códigos HTML em comentários de código fonte são uma aberração”.
- Eles dificultam a leitura dos comentários que seriam fáceis de ler.
- Se precisar extrair comentários para uma página HTML a ferramenta que está utilizando deve ser responsável por isso e não o programador.

### Informações não locais
- Se precisar escrever um comentário, então coloque o mesmo perto do código que ele descreve.
- Não forneça informações gerais do sistema no contexto de um comentário local.
- No exemplo abaixo o comentário fala sobre porta, que nem é usada no método e também não há garantia dele ser atualizado quando o código for alterado:
```
/**
* Port on which fitnesse would run. Defaults to <b>8082</b>.
*
* @param fitnessePort
*/
public void setFitnessePort(int fitnessePort) {
    this.fitnessePort = fitnessePort;
}
```

### Informações excessivas

- “Não adicione discussões históricas interessantes ou descrições irrelevantes de detalhes em seus comentários”;
- Não precisamos dessas informações contidas no comentário.

### Conexões nada óbvias
- “A conexão entre um comentário e o código que ele descreve deve ser óbvia”;
- Um comentário deve estar conectado com o código, assim o leitor pode ler ambos e entender o que foi falado.
- **É péssimo quando um comentário também precisa ser explicado!**

### Cabeçalhos de funções
- **“Funções curtas não requerem muita explicação”**;
- Um nome bem selecionado para uma função pequena e que faz apenas uma coisa costuma ser melhor do que um comentário no cabeçalho.

### Javadocs em códigos não públicos
Javadocs para um código não voltado para distribuição ao público são uma maldição. Só gera entulho e distração no código.