Reutilização de código: até onde vale a pena

Resumen

A reutilização de código é uma das práticas que mais impacta o design de software, porque reduz custos, acelera o lançamento de produtos e permite que tu redirecciones recursos para áreas como o marketing. Vamos ver até onde vale a pena reutilizar e quando essa decisão pode tornar o teu código mais frágil.

Por que a reutilização compensa no design de software?

Reutilizar não é só copiar funções: é apoiar-te em soluções já validadas pela comunidade para não reinventar a roda.

Quando aproveitas componentes que já funcionam, ganhas três coisas concretas:

  • Redução de custos e prazos de desenvolvimento.
  • Libertação de orçamento para tarefas críticas como publicidade ou validação de mercado.
  • Confiança em peças testadas, em vez de construir tudo de raiz.

A pergunta que deves fazer é simples: se já existe algo validado, por que vais gastar tempo a construir o mesmo? Esse é o espírito por detrás de boas decisões de arquitetura.

¿Que é o princípio Don't Repeat Yourself (DRY)? É uma regra que diz que, se um pedaço de código se repete mais do que uma vez, deves criar uma abstração que reúna essa funcionalidade comum num só lugar.

Quando a reutilização se torna prejudicial?

Aqui vem a parte interessante: nem tudo deve ser abstraído. Criar uma abstração da abstração da abstração pode transformar uma mudança simples num pesadelo de várias camadas.

O próprio princípio DRY tem limites. Se forçares a reutilização onde não faz sentido, o teu código fica desnecessariamente complexo e perdes legibilidade. A regra prática é recorrer à simplicidade e evitar riscos que não compensam.

Devo aplicar sempre o DRY? Não. Algumas duplicações são saudáveis. Abstrai apenas quando a repetição represente realmente a mesma regra de negócio, não quando o código simplesmente se parece.

Quais são os três níveis de reutilização segundo Erich Gamma?

Erich Gamma, um dos precursores no estudo dos padrões de design, define três níveis de reutilização. Para fixares a ideia, pensa numa lasanha.

Classes e funções: os ingredientes

O primeiro nível são as classes ou funções, dependendo do paradigma. Estes são os ingredientes: as peças mais pequenas, que fazem uma única coisa, mas fazem-na bem.

Podes construir estes ingredientes na linguagem que preferires: JavaScript, Python, Elixir, Ruby, Go ou Rust. O importante é a responsabilidade única, não a sintaxe.

Padrões de design: a receita

O segundo nível são os padrões de design, que funcionam como a receita da lasanha. Dizem-te como combinar os ingredientes, como ligar as funções e como organizar a interação entre classes.

E tal como numa receita, há flexibilidade. Onde a receita pede oito tomates, podes usar sete ou nove. O padrão guia-te, mas não te amarra.

Frameworks: a lasanha congelada

O terceiro nível são os frameworks, equivalentes a uma lasanha congelada pronta a aquecer. Ferramentas como Django, Next.js ou Rails privilegiam convenção sobre configuração.

Se escolhes Rails, já existe uma forma definida de organizar rotas, controladores, modelos e a relação com a base de dados. O mesmo acontece com Django ou Next.js para gerir rotas e solicitações. Tu apenas escolhes a convenção que mais te agrada.

Como aplicar uma abstração para evitar acoplamento?

Imagina uma classe UserService com um atributo URL e um método que faz uma solicitação usando um módulo HTTP, por exemplo o Axios. Neste cenário, o UserService depende diretamente do módulo.

O problema aparece quando escalas. Se tens 15 serviços a usar Axios diretamente e um dia o módulo muda, vais ter de modificar 15 ficheiros.

A solução é introduzir uma abstração intermédia, a que podemos chamar HTTPGateway:

  • O UserService passa a depender do gateway.
  • O gateway é o único que depende do módulo externo.
  • Se o módulo muda, alteras um único ficheiro.

javascript // Sem abstração class UserService { constructor() { this.url = '/users'; } getUsers() { return HTTP.get(this.url); } }

// Com abstração via gateway class UserService { constructor(gateway) { this.gateway = gateway; this.url = '/users'; } getUsers() { return this.gateway.get(this.url); } }

A pergunta-chave que deves interiorizar: o que muda mais frequentemente, o módulo externo ou a tua abstração? A resposta orienta a decisão de design para o teu caso específico.

Já usaste o Don't Repeat Yourself nos teus projetos? Em que momento sentiste que a reutilização passou a atrapalhar em vez de ajudar? Conta-me nos comentários.