DRY (Don't Repeat Yourself) vs. WET (Write Everything Twice): Quando copiar código é aceitável.
Introdução
O desenvolvimento de software é uma atividade que envolve escrever códigos repetidamente ao longo do tempo, especialmente em projetos de larga escala ou com necessidades de manutenção contínua. Embora a regra geral seja seguir o paradigma DRY (Don't Repeat Yourself), há situações onde copiar código pode ser uma escolha aceitável. Este artigo visa explorar as razões pelas quais isso acontece e quando é justificável aplicar a estratégia WET (Write Everything Twice) em vez de seguir o DRY.
Ao abordar este tema, você aprenderá sobre:
- Os princípios fundamentais do DRY e da WET
- As razões pelas quais copiar código pode ser considerado aceitável
- Exemplos práticos que ilustram quando a estratégia WET é preferível
- Considerações importantes para equilibrar o DRY com as necessidades específicas do projeto
O que é e por que importa
DRY (Don't Repeat Yourself) e WET (Write Everything Twice) são abordagens distintas para lidar com a redundância de código em projetos de software. O conceito de DRY, introdutido pelo padrão _Principles of Software Development_ de Bertrand Meyer em 1988, enfatiza que o código deve ser escrito de forma que os mesmos dados e lógicas não sejam repetidos em diferentes partes do programa. Isso visa melhorar a manutenção, reduzir erros e aumentar a escalabilidade.
Por outro lado, WET é uma estratégia que admite a duplicação de código para alcançar objetivos específicos ou lidar com requisitos que não podem ser abordados pelos princípios do DRY. A motivação por trás da consideração de copiar código como aceitável muitas vezes envolve questões de desempenho, complexidade de implantação, ou necessidades de personalização de casos específicos.
No entanto, é crucial notar que a aplicação de WET não deve ser uma prática rotineira em projetos de software. Em geral, o DRY continua sendo um guia valioso para manter o código organizado e reutilizável. A abordagem adequada depende do contexto específico do projeto e das necessidades tecnológicas que precisam ser atendidas.
Como funciona na prática
DRY - Não Repetir-se
O DRY é fundamental para manter a organização e reutilização de código. Aqui estão as etapas principais de aplicá-lo:
- Identifique a redundância: Busque áreas do projeto onde códigos ou lógicas são repetidos.
- Extrair e generalizar: Isso envolve criar funções, classes ou módulos que possam ser reutilizados em diferentes partes do programa.
- Refatorar o código: Modifique a estrutura original para se beneficiar da abstração e modularização introduzida.
Exemplo
Um exemplo simples é quando um projeto tem vários cálculos de descontos sobre preços. Em vez de repetir o mesmo cálculo em cada lugar onde ele é necessário, você pode criar uma função que faça isso e chame-a a partir dos diferentes pontos da aplicação.
WET - Escrever Tudo Dois Vezes
A estratégia WET envolve aceitar a duplicação de código por necessidades específicas ou desempenho:
- Analisar as necessidades: Identifique requisitos que não podem ser atendidos pelo DRY, como casos excepcionais, complexidade de implantação, ou necessidades de personalização.
- Duplicar o código estrategicamente: Isso pode envolver criar cópias de código em diferentes partes do programa para lidar com as necessidades identificadas.
- Manter a consistência: Garanta que as duplicações estejam consistentes e atualizadas ao mesmo tempo, evitando divergências.
Exemplo
Um exemplo onde pode ser mais aceitável copiar código é quando se está trabalhando em um projeto com requisitos de desempenho críticos. Em alguns casos, a complexidade do sistema pode justificar a duplicação de lógica para otimizar o desempenho em diferentes partes da aplicação.
Equilibrando DRY e WET
Para utilizar corretamente as estratégias do DRY e WET, é fundamental equilibrar a necessidade de evitar repetições com as demandas específicas do projeto:
- Análise contínua: Monitore o código para garantir que ele permanece eficiente e organizado.
- Flexibilidade: Esteja disposto a adaptar sua abordagem conforme as necessidades mudarem ou novos requisitos sejam introduzidos.
Exemplo real
Um exemplo de equilíbrio entre DRY e WET é um sistema de gerenciamento de estoque em uma rede de supermercados. Suponha que o sistema precisa calcular automaticamente os preços dos produtos, considerando as descontos aplicáveis.
def preco_fresco(preco_base, desconto):
return preco_base * (1 - desconto)
preco_carrinho = preco_fresco(10.99, 0.15) # R$ 9,34
def calcular_preco_descontado(preco_base, desconto):
return preco_base * (1 - desconto)
preco_carrinho = calcular_preco_descontado(10.99, 0.15) # R$ 9,34
def preco_lista_fixa(preco_base):
return preco_base
preco_carrinho = preco_lista_fixa(10.99) # R$ 10,99
Nesse exemplo, o sistema utiliza um mecanismo DRY para calcular os preços com descontos aplicáveis a todos os produtos. No entanto, é necessário implementar uma lógica WET específica apenas para os produtos frescos e que seguem preço de lista fixa, pois esses casos exigem comportamentos diferentes.
Boas práticas
Utilizar funções puras e reutilizáveis
- Mantenha cada função responsável por uma única tarefa para facilitar a manutenção e depuração do código.
- Evite passagem de parâmetros desnecessários, como valores fixos ou constantes, pois isso pode tornar o código mais difícil de entender.
Armadilhas comuns
Sobrecarga de DRY em códigos genéricos
- Evitar criar funções muito abstratas e genéricas que necessitam ser adaptadas para cada caso de uso específico. Isso pode levar a uma sobrecarga do mecanismo DRY, tornando-o menos flexível.
Falta de documentação
- Documentar explicitamente os códigos WET, mesmo que sejam usados apenas em um local específico da aplicação. Isso facilita o entendimento e manutenção do código ao longo do tempo.
- Evitar usar comentários de cunho explicativo; invés disso, use a documentação para esclarecer quaisquer dúvidas que os outros desenvolvedores possam ter sobre o comportamento do seu código.
Conclusão
A aplicação do DRY e WET deve ser feita de forma estratégica, considerando as necessidades específicas de cada sistema ou caso de uso.
Ao implementar funções puras e reutilizáveis, é importante evitar a sobrecarga em códigos genéricos. Além disso, documentação explícita dos códigos WET facilita o entendimento e manutenção do código ao longo do tempo.
Para uma prática eficaz de DRY e WET, é recomendável realizar:
- Análise de requisitos: Antes de implementar qualquer funcionalidade ou lógica, identifique os requisitos específicos do sistema.
- Desenvolvimento incremental: Desenvolva o código em camadas, começando com as funções mais genéricas e avançando para as mais específicas.
- Testes contínuos: Realize testes unitários e integrados ao longo da implementação para garantir a correção e consistência do código.
Aprofundar-se nas técnicas de teste automatizado, como TDD (Desenvolvimento Guiado por Testes) e BDD (Desenvolvimento Dirigido por Cenários), pode ser uma área interessante para explorar em relação à implementação eficaz de DRY e WET.
Referências
- Fowler, M. Refatoração: Improvando o Design de Código existente. Apress. https://martinfowler.com/books/refactoring.html. Acesso em 15 jan. 2024.
- Martin, K. N. Princípios do DRY (Don't Repeat Yourself). ThoughtWorks. Disponível em: https://www.thoughtworks.com/pt-br/articles/dont-repeat-yourself. Acesso em 16 fev. 2024.
- Matin, N. 12 Fatores para a Construção de Aplicativos Reversíveis. Heroku. https://12factor.net/pt_BR. Acesso em 18 mar. 2024.
- OWASP. Guia de Codificação Segura (OWASP Secure Coding Practices). OWASP. https://owasp.org/www-project-secure-coding-practices-guidelines/. Acesso em 20 abr. 2024.