Vamos falar um pouco sobre DRY e como escrever código mais limpo.

Este post é para quem está buscando melhorar suas habilidades como programador. Vamos falar sobre “DRY” ou “Don’t repeat yourself”. Vou explicar um pouco sobre o que é o DRY e como podemos aplicá-lo em nosso dia a dia.

Esse é o primeiro de uma série de posts que vai elevar suas habilidades como programador. Antes de tudo, se você gosta desse tipo de conteúdo aproveite para assinar nossa newsletter e ficar por dentro de todas as novidades do blog.

Afinal, o que é o DRY?

DRY é a sigla para “Don’t Repeat Yourself” que, em tradução livre, quer dizer “Não se Repita”. O conceito do DRY foi proposto por Andy Hunt e Dave Thomas em seu livro The Pragmatic Programmer.

A definição formal desse princípio diz :

“Cada parte do conhecimento deve ter uma representação única, não ambígua e definitiva dentro do sistema.”

Mas podemos entender como “Não repita código desnecessariamente”.

É muito fácil cometer esse tipo de erro quando usamos facilitadores, bem como geradores de códigos ou quando pulamos algumas etapas de planejamento e designer. Em muitos casos será mais fácil copiar e colar um código gerado automaticamente do que faze-lo de forma estratégica.

O mais interessante é que esse problema não depende de uma linguagem específica ou metodologia. Já passei por situações onde o estilo CSS de um componente se repetia diversas vezes, já vi funções que tratava datas ou preços espalhadas pelo back-end e objetos imensos de configurações de plugins sendo reescrito a cada instancia. (alguém usa lib de slide?)

O princípio do DRY é apresentado para resolver esse tipo de problema. A ideia é evitar a repetição de código em diversas partes do seu sistema. Isolando esses trechos repetitivos em funções ou classes.

Como resolver problemas de repetição?

A melhor forma de evitar esse tipo de situação é ter com clareza quais são as funcionalidades do sistema, quais sãos os componentes UI do sistema e planejar o que pode ser compartilhado e o que é específico de cada parte do sistema. Por exemplo: Não faz muito sentido externalizar uma função que manipula datas se você vai utilizar aquela função em um único lugar. Da mesma forma, não faz sentido copiar o conteúdo dessa mesa função e colocar em outro lugar para ser reutilizada.

O código a seguir apresenta o seguinte problema:

Quando btn1 for clicado ele deve verificar se a “div.card” está ativa. Caso ela esteja ativa, a classe “active” será removida, caso contrário a classe “active” será adicionada. O mesmo acontece no btn2, mas dessa vez verificação ocorre no evento de mouse hover.

(function () {
  const btn1 = document.getElementById("meu-btn-1");
  const btn2 = document.getElementById("meu-btn-2");

  btn1.addEventListener("click", function () {
    if (document.querySelector(".card").classList.contains("active")) {
      document.querySelector(".card").classList.remove("active");
    } else {
      document.querySelector(".card").classList.add("active");
    }
  });

  btn2.addEventListener("mouseover", function () {
    if (document.querySelector(".card").classList.contains("active")) {
      document.querySelector(".card").classList.remove("active");
    } else {
      document.querySelector(".card").classList.add("active");
    }
  });
  
})();

Essa repetição pode complicar a manutenção do seu código. Imagine que um outro desenvolvedor da sua equipe está atualizando algumas coisas e precisa passar pelo seu código. Esses 2 blocos podem está em arquivos diferentes e acabar passando despercebido pelo seu colega. Gerando bugs se ambos os eventos precisarem da alteração.

Para evitar esse e outros problemas, podemos isolar todo a lógica dos eventos em uma única função. Dessa forma seu código fica simples, mais legível e mais fácil dar manutenção.Veja!

(function () {
  const btn1 = document.getElementById("meu-btn-1");
  const btn2 = document.getElementById("meu-btn-2");

  function changeCard() {
    const card = document.querySelector(".card");
    if (card.classList.contains("active")) {
      card.classList.remove("active");
    } else {
      card.classList.add("active");
    }
  }

  btn1.addEventListener("click", function () {
    changeCard();
  });

  btn2.addEventListener("mouseover", function () {
    changeCard();
  });
})();

Um outro ponto é evitar a repetição de seletores. Perceba que no primeiro exemplo repetimos diversas vezes o seletor do card  document.querySelector(".card") e no segundo exemplo armazenamos o resultado dessa seleção na constante “card”. Essas pequenas mudanças melhoram a legibilidade do código pois fica claro o que cada variável recebe.

Utilizando o DRY no seu CSS.

Para a parte de UI/UX o ideal é ter um “design system” especificando todos os espaçamentos, componentes, tipografia, etc… Contudo, se isso não está ao seu alcance, você pode tentar identificar os principais componentes e otimiza-los. Geralmente são botões, cards, títulos. Enfim, componentes que tendem a se repetir por diversas telas.

No próximo exemplo de código vamos ver como esse problema aparece no CSS. É muito comum desenvolvedores copiar e colar código gerado por ferramentas de designer. O figma, por exemplo, disponibiliza código CSS completo de qualquer elemento desenhado na tela. Isso facilita muito o processo de desenvolvimento mas pode agravar esse tipo de problema, ainda mais quando as coisas está fora de controle.

O código abaixo mostra a estilização de um determinado botão. Veja:

<style>
  header > button {
    background-color: green;
    color: white;
    border-radius: 8px;
  }

  main > button {
    background-color: green;
    color: white;
    border-radius: 8px;
  }

  footer > button {
    background-color: green;
    color: white;
    border-radius: 8px;
  }
</style>

<!--- BODY --->

<header>
  <button>Botão 1</button>
</header>
<main>
  <button>Botão 2</button>
</main>
<footer>
  <button>Botão 2</button>
</foot>

Esse é um exemplo bem comum que acaba gerando muito esforço na hora dar manutenção. Ainda mais se você ou um colega precisar trocar a cor desses botões. Será necessário identificar todas as incidências de estilo e alterar uma a uma. Note que não será possível estilizar o elemento button de forma genérica, pois isso poderia alterar todos o buttons do sistema. Pode haver diversos estilos para botões fora do contexto apresentado. Contudo, a melhor solução é criar uma classe específica para esse botão.

<style>
  .primary-button {
    background-color: green;
    color: white;
    border-radius: 8px;
  } 
</style>

<!--- BODY --->

<header>
  <button class="primary-button">Botão 1</button>
</header>
<main>
  <button class="primary-button">Botão 2</button>
</main>
<footer>
  <button class="primary-button">Botão 2</button>
</foot>

Isso parece óbvio a primeiro momento mas por que estamos analisando e planejando como vamos manipular esses elementos. Sem essa etapa as coisas podem ficar obscuras e vai ser muito fácil só copiar o bloco de estilo no figma e colar no seu CSS.

DYR é tudo que eu preciso saber para ser um programador melhor?

De longe a resposta é não. Mas, mantendo esse princípio você alcança uma experiência muito positiva de programação. Perceba que aplicando o DRY seu código fica mais fácil de entender, menor e menos poluído. Como resultado, só existe vantagens em aplicar o DRY no seu dia a dia!

Me conta nos comentários se esse post te ajudou em alguma coisa ou se tem alguma coisa que você gostaria de acrescentar. Eu vou ficando por aqui e até a próxima.

 

Veja também

Outros links