Executando verificação de segurança...
3

O princípio DRY - conceitos e exemplos

Você conhece o princípio DRY?

O princípio DRY ou "Don't Repeat Yourself", tem como objetivo evitar a repetição de código em seu projeto. Isso possibilita que seu projeto seja mais limpo e de maior qualidade, matém seu código mais fácil de realizar manutenções, aproveitando lógicas e muitas vezes evitando o retrabalho.

  • Exemplo:

function sum(firstNumber, secondNumber){
    const firstNumberTimesTwo = firstNumber * 2;
    return firstNumberTimesTwo + secondNumber;
}

function subtract(firstNumber, secondNumber){
    const firstNumberTimesTwo = firstNumber * 2;
    return firstNumberTimesTwo - secondNumber;
}

console.log(sum(5,5));
//Result 15

console.log(subtract(5,5));
//Result 5
  • Perceba que no código acima eu tenho duas funções, uma que soma 2 números e outra que subtrai. Perceba que em ambos os casos o "firstNumberTimesTwo" é multiplicado por 2. veja agora como isso ficaria um pouco melhor:

function sum(firstNumber, secondNumber){
    return firstNumberTimesTwo + secondNumber;
}

function subtract(firstNumber, secondNumber){
    return firstNumberTimesTwo - secondNumber;
}

const numberOne = 5;
const numberTwo = 5;
const numberToBeMultiplied = 2;

const firstNumberTimesTwo = numberOne * numberToBeMultiplied;



console.log(sum(firstNumberTimesTwo,numberTwo));
//Result 15 

console.log(subtract(firstNumberTimesTwo,numberTwo));
//Result 5
  • Agora nesse código podemos perceber duas melhorias:
  1. O "firstNumberTimesTwo" agora está sendo feito fora das funções, e caso eu precise alterar a multiplicação por 3, por exemplo, eu não preciso mexer nas funções apenas alterar o valor em um único lugar e as funções terão os parâmetros corretamente.

  2. Percebam que foram criadas as constantes numberOne, numberTwo e numberToBeMultiplied, com isso sempre que eu precisar alterar os valores que quero testar nas minhas funções, eu altero apenas o valor das constantes e a funções vão receber os valores desejados, inclusive o "firstNumberTimesTwo".

Com pequenas funcionalidades pode parecer não fazer diferença, mas isso em grande escala começa a se tornar péssimo. Imagine que você tenha que implementar as funções de multiplicação e divisão recebendo os mesmos valores. Se fosse utilizando o primeiro exemplo, você teria mais linhas de códigos e sempre que testasse valores diferentes, teria que substituí-los em todas as chamadas de funções.

Utilizando o DRY, sem dúvidas terá grande aliado do clean code e facilitará muito a legibilidade do seu código.

Espero que tenha contribuído! Valeus galera até a próxima :)

Carregando publicação patrocinada...
3

Ótimo post, porém, se posso acrescentar algo, diria que as pessoas deveriam tomar cuidado com DRY, porque? porque ele molda o pensamento das pessoas que todo código duplicado é ruim e deve ser abstraido, sendo que a verdade é que nós devemos primeiro pensar se aquela abstração faz sentido, se ela cobre o caso certinho, porque se não, abstraimos o código duplicado e a medida que nossa base de código cresce, precisamos atender mais um caso, e aí? você cria mais um parametro para atender esse caso? e se surgirem mais? acaba que uma abstração pode ser muito perigosa no sentido de gerar mais complexidade no código, pode ser que sua função no futuro vire algo como um Frankenstein e outra pessoa que for ler mais a frente não saiba nem qual o próposito daquela função ou o que ela resolve de fato.

Por isso é comumente difundido que "Um código duplicado custa mais barato que uma abstração mal feita".

Isso porque uma abstração mal feita gera uma complexidade muito MAIOR do que um código duplicado.

Lembrando que não estou aqui dizendo pra não fazer hein, eu mesmo faço muitas, muitas mesmo, acredite. Porém eu só estou dizendo para pensar certinho em cada caso, em cada contexto.

Deixo aqui um artigo em inglês(Desculpe, não consegui achar um artigo relacionado em PT-BR) como recomendação de leitura sobre este caso, abraços.
https://alexkondov.com/the-cost-of-wrong-abstractions/

2

Legal o post, SrKim!

Uma observação sobre a forma que você resolver o problema da lógica duplicada(lógica de dobrar um valor). Você soluciona desta forma: remove a lógica duplicada e exige que quem usa as funções sum e subtract dobrem a entrada, isso me parece algo ruin, pois sempre que usar uma das duas funções eu irei ter que dobrar o valor. Acredito que a seguinte forma resolve melhor o problema:

function duble(n) {
    return n * 2;
}

function sum(firstNumber, secondNumber){
    return duble(firstNumber) + secondNumber;
}

function subtract(firstNumber, secondNumber){
    return duble(firstNumber) - secondNumber;
}

console.log(sum(5,5));
//Result 15

console.log(subtract(5,5));
//Result 5

Com essa alteração, usamos as funções da mesma forma, sem necessidade de antes de usá-la duplicar a entrada e sem código duplicado.

1

DRY é um conceito muito importante, mas é o que mais confunde iniciantes. É ótimo nao se repetir muito, mas muitas vezes é mais simples se repetir mesmo, pois se for tentar aplicar DRY a complexidade do código aumenta. Eu costumo ver esse conceito mais como um conceito de refatoracao e não de escrita de codigo.

Ótimo conteúdo, continue sempre contribuindo para a nossa comunidade se tornar cada vez mais completa.

1

Já eu vejo como escrita de código. Basicamente faço um código que funciona, o que inclui repetições. Depois faço a refatoração, e percebo que começo a pensar de forma refatorada com o tempo.

A vantagem que o código fica com mais cara profissional, porém fica mais dificil de entender pra quem está olhando de fora.

1

Sobre DRY, entendo que não é à qualquer custo, existem situações de duplicação que são convenientes simplesmente porque coisas inicialmente semelhantes são alteradas por motivos diferentes e passam ter sua própria trajetória.

Para criarmos abstrações que façam sentido, primeiro precisamos conhecer bem o problema, coisa que muitas vezes chegamos ao "pleno" conhecimento após uma boa vivência influenciados pelo contexto de negócio e mantendo a base de código. Algumas regiões do código começam a se estabilizar, revelar padrões e, outras continuam em constante mudança tendo ligação direta com demandas latentes que geram valor para a empresa.

Uma vez assisti uma apresentação na qual o palestrante fazia analogia entre código quente, com um campo que precisa de fertilizante para potencializar a produção e prosperar o plantio. O fertilizante poderia ser entendido como código que é alterado a todo momento, com soluções potencialmente não definitivas, mas que faz o resultado ser alcançado. É nele que tudo está acontecendo. Em outras palavras, "onde há MERD*, há grana".

As "zonas quentes" do código precisam se provar, há um nível de incerteza altíssimo sobre elas, até mesmo qualidade comprometida em favor de uma entrega de valor, dado prazo, custo, etc. Desenvolvedores não são artesãos porque precisam empoderar o negócio para que a empresa tenha sucesso.

Códigos já consolidados com pouca alteração tende a ser bons cadidatos à abstração, otimização, etc.

Dito tudo isso, bom senso é algo que deve ser praticado, código deve trazer consigo boas práticas para se manter saudável ao longo do tempo, então o extremismo em qualquer direção deve ser evitado.

Quanto ao código exemplo, podemos dizer que refatoração é algo que "tende ao infinito" (você decide quando parar). Se separarmos responsabilidades e fizermos uso de composição, teríamos:

const sum = (a, b) => a + b

const subtract = (a, b) => a - b

const multiply = (n, m) => n * m

const multiplyBy = m => n => multiply(n, m)

const double = multiplyBy(2)

const sum2ab = (a, b) => sum(double(a), b)

const sub2ab = (a, b) => subtract(double(a), b)