---
title: Escreva Código Para Ser Lido
teaser: 'Técnicas e razões para otimizar seu código para as pessoas, não para métricas.

  '
tags: good code,programming,refactoring,stories
author: Edward Loveall
published_on: 2022-03-18
---

O código é lido mais vezes que escrito. Nós o escrevemos uma vez e depois o lemos novamente.
Ele passa por revisão, se estamos em uma equipe, e é lido novamente quando outra pessoa
precisa entender, adicionar ou modificar esse código. Isso inclui nós mesmos, semanas
ou meses depois.

Apesar disso, tendemos a focar na escrita como a principal "ação". [A escrita _é_ muito importante][storytellers],
mas antes de escrever, precisamos entender o contexto. Devemos ler antes de escrever. É muito mais fácil
entender o código se ele for bem escrito. Mesmo em situações em que escrevemos muito código, como uma nova
_codebase_, eventualmente precisamos voltar e ler nossos primeiros passos. Devemos otimizar o código para
ser lido.

## Nomes

[Nomes][name-it] descrevem o que variáveis, métodos e classes são ou o que fazem.
Eles esboçam o sistema com o qual estamos trabalhando. É mais fácil escrever nomes concisos.
Eles mantêm nossas linhas pequenas e facilitam a digitação desses nomes repetidamente.
Por exemplo, `cc = CreditCard.find` em vez de `primary_card`, ou `def set_attr`
em vez de `set_user_profile_attribute`.

O problema é que nomes não descritivos como `cc` ou `set_attr` requerem
mais investigação para descobrir o que são e como devem ser usados.
Esses exemplos favorecem a escrita fácil, não a leitura.

Considere os conceitos que você aprendeu para escrever código e tente utilizar isso
nos nomes. Considere o _porquê_ ou _como_ algo é usado em vez do que ele
_é_. `initial_sign_up_profile` diz muito mais do que `profile`, e
`lock_stats_table_for_data_export` diz mais do que `lock_db`.

A legibilidade é o objetivo, não o tamanho do nome. Você pode criar
código ilegível com nomes longos, especialmente muitos nomes longos bastante
semelhantes. Favoreça a legibilidade, não alguma métrica de comprimento arbitrária.

## Abstraindo Lógica Procedural

O código que escrevemos para o funcionamento de um sistema é diferente da maneira
como descrevemos seu funcionamento. Imagine o processo de "mostrar _dialog modal_". É assim
que o descreveríamos, mesmo para colegas proficientes em código. Não costumamos descrever
isso como "encontrar o elemento DOM relacionado apropriado e definir as classes CSS para que ele
seja visível", mas é nesse nível de abstração que o código funciona. É nosso trabalho traduzir
entre esses [níveis de abstração][single-abstraction-level].

Quando você tem um [método longo][long-method-smell], a correção clássica é o
[_Extract Method_][extract-method-fix]. O _Extract Method_ funciona dividindo nosso código não otimizado
em abstrações nomeadas que representam a lógica subjacente. Novamente, estamos
voltando aos nomes, mas com um objetivo um pouco diferente. Um bom nome permite que você
descreva a funcionalidade de uma forma que não exija que o usuário conheça cada
parte interna do sistema. Isso permite que eles aprendam (ou reaprendam) os detalhes mais complexos conforme necessário.

Aqui está um exemplo de como mostrar um modal com JavaScript:

```js
function async showModal(event) {
  const target = event.target;
  const modal = document.querySelector(
    event.target.dataset.relatedModalSelector
  );
  if (!modal || !modal.classList.contains("modal")) {
    return;
  }

  for (const element of document.querySelectorAll("modal")) {
    element.classList.add("hidden");
  }

  const data = modal.dataset;
  const modalTitle = JSON.parse(data.display)["title"];
  const modalContent = await fetchModalData(data.remoteUrl);
  modal.innerHtml = modalContent;
  modal.classList.remove("hidden");
}
```

Se você já está familiarizado com o funcionamento do sistema de modais, ler o código apresentado não será um problema.
No entanto, é importante lembrar que a maioria das pessoas não possui essas informações sempre em mente.
Abstrair a lógica procedural ajudará qualquer pessoa que esteja visualizando esse código pela primeira vez a entender
onde precisará fazer alterações.

```js
function async showModal(event) {
  const modal = this.findPossibleModal(event);
  if (!this.isValidModal(modal)) {
    return;
  }

  await this.setModalContent(modal);
  this.hideEveryModal();
  this.revealModal(modal)
}
```

A refatoração faz com que os passos para exibir o modal sejam claros e facilmente
compreensíveis. Se precisarmos, podemos encontrar os detalhes da implementação em
métodos extraídos, e fica imediatamente claro o que cada método está fazendo.
Todos os metodos tem um nível de abstração semelhante; neste caso, manipulando
elementos DOM relacionados. O método `showModal` é tambem uma abstração,
que existe com abstrações em um nível similar. É fácil imaginar
outras possiveis interações como `submitForm`, `syncUserProgress` ou
`enableFocusMode`.

## Testes

Ao testar, é relativamente comum isolar a [fase de _setup_][four-phase-test] do restante do teste
usando abstrações como o [`let`][lets-not] ou `before`. Muitos testes no mesmo arquivo exigem contextos
semelhantes (ou iguais) para serem executados, então consolidar essa configuração parece ser
uma maneira natural de evitar repetições em um teste (DRY). Agrupar código relacionado também pode
se assemelhar a criar abstrações.

<aside class="info">
  <b>Nota do tradutor</b>
  <p>
    DRY, que significa 'não repita a si mesmo', é um princípio de desenvolvimento de software que visa
    reduzir a repetição de padrões e duplicação de código em prol de abstrações e evitar redundâncias.
  </p>
</aside>

No entanto, isso torna os testes mais difíceis de ler. O _setup_ do código define o estado do
sistema. Na maioria das vezes, não trabalhamos com esses testes recentemente ou talvez nunca
tenhamos trabalhado com eles antes. Essas partes do _setup_ são fundamentais para entender como corrigir
testes existentes ou adicionar mais. Um teste separado de seu contexto nos obriga a memorizar esse contexto,
o que distrai nossas habilidades de resolução de problemas. Um bom teste [conta uma
história][the-self-contained-test].

A maioria dos testes também testa um sistema em vários estados; nenhum _setup_ único pode representar
todos os cenários. Na melhor das hipóteses, o _setup_ compartilhado terá que ser redefinido para testes individuais,
espalhando esse contexto. Na pior das hipóteses, o _setup_ é totalmente desperdiçado, já que o _setup_ global não é utilizado.
Quando colocamos o _setup_ compartilhado no topo, estamos assumindo que todos os testes futuros precisarão
desse mesmo _setup_. Escreva mais alguns testes e essa suposição provavelmente será falsa, fazendo com que
tenhamos que reorganizar todo o arquivo ou simplesmente lidar com o desperdício.

Manter todo esse _setup_ no próprio teste torna-o muito mais legível, apesar de não obedecer ao
_DRY_, mas [_DRY_ não é muito útil nos testes][the-case-for-wet-tests]. Não precisamos que os testes sejam
baseados em abstrações reutilizáveis e tenham poucas linhas. Precisamos que os testes nos proporcionem confiança
previsível em nosso sistema e nos ajudem a refatorar.

## Objetivos mais amplos

Vale lembrar que métricas específicas como complexidade de código, cobertura de teste e _DRY_ não são
objetivos por si só. O objetivo é ter um código que possamos entender facilmente e alterar com confiança
para fornecer aos usuários o melhor software possível. Embora "legibilidade" seja mais [difícil de medir][wtf],
tê-la como um princípio orientador pode nos ajudar a saber quando flexibilizar ou quebrar essas regras
quantitativas e construir um software melhor.

[storytellers]: https://thoughtbot.com/blog/storytellers/
[name-it]: https://thoughtbot.com/blog/name-it/
[four-phase-test]: https://thoughtbot.com/blog/four-phase-test/
[lets-not]: https://thoughtbot.com/blog/lets-not/
[single-abstraction-level]: https://thoughtbot.com/blog/acceptance-tests-at-a-single-level-of-abstraction
[long-method-smell]: https://refactoring.guru/smells/long-method/
[extract-method-fix]: https://refactoring.guru/extract-method/
[the-self-contained-test]: https://thoughtbot.com/blog/the-self-contained-test-pt
[the-case-for-wet-tests]: https://thoughtbot.com/blog/the-case-for-wet-tests/
[wtf]: https://commadot.com/wtf-per-minute/
