Quando começamos a estudar arquitetura e bons princípios de código, um termo aparece o tempo todo e quase sempre assusta:
Composição de Dependências, também chamada de Dependency Injection. Mas a verdade é que a ideia é muito mais simples do que o nome sugere. Vamos por partes.
O problema que isso resolve
Imagine uma classe que faz tudo sozinha.
- Ela executa sua lógica principal
- Cria objetos
- Decide quais implementações usar
- Sabe detalhes que não deveria saber
Esse tipo de classe funciona no começo, mas rapidamente fica difícil de manter, testar e evoluir. Qualquer mudança pequena vira um efeito dominó.
A ideia central da composição de dependências
Composição de dependências significa que uma classe não cria aquilo de que ela precisa.
Ela recebe pronto.
Ou seja, a classe foca apenas no seu papel, outra parte do sistema se preocupa em montar tudo e entregar para ela.
A analogia do café ☕
Agora um exemplo do dia a dia.
Imagine uma cafeteira.
Ela faz café, essa é a responsabilidade dela. Mas ela não deveria decidir qual café comprar, nem ir ao mercado buscar água.
Se a cafeteira tivesse que fazer isso, ela ficaria cheia de responsabilidades.
O que acontece na composição de dependências alguém de fora entrega o café e a água para a cafeteira. A cafeteira só usa.
Tudo isso chega pronto.
No código é igual.
Sem composição de dependências
A classe cria tudo internamente.
- Ela escolhe a implementação
- Fica acoplada a detalhes
- Fica difícil trocar ou testar
Esse tipo de código costuma parecer simples no início, mas envelhece mal.
Com composição de dependências
A classe recebe suas dependências de fora.
- Ela não sabe como foram criadas
- Não se importa com detalhes
- Só sabe que pode usá-las
Isso deixa o código mais limpo e mais flexível.
Onde a composição acontece
Muita gente acha que Dependency Injection é coisa de framework, mas não é.
A composição pode acontecer
- No controller
- No use case
- Em uma factory
- No ponto mais externo da aplicação
- Até mesmo em um new simples
O importante não é a ferramenta. É a decisão de design.
Benefícios reais
- Código mais fácil de entender
- Menos acoplamento
- Troca de implementações sem dor
- Testes muito mais simples
- Evolução mais segura
Ligação direta com o SOLID
A composição de dependências é a base prática do D do SOLID.
Depender de abstrações e não de implementações fica natural quando a classe não cria suas próprias dependências.
Ela apenas recebe.
Uma frase para guardar
Composição de dependências é deixar a classe usar o que precisa, não criar o que precisa.