Injeção de Dependência
Definição
A Injeção de Dependência (Dependency Injection) é um padrão que consiste em fornecer as dependências de um componente a partir de fora, em vez de deixá-lo criá-las internamente. Ou seja, o objeto recebe o que precisa para funcionar, em vez de construir tudo sozinho.
Esse padrão faz parte do conceito mais amplo de Inversão de Controle (IoC).
Por que é importante
Injetar dependência torna os componentes mais flexíveis, testáveis e desacoplados. A lógica principal de um serviço não precisa conhecer os detalhes de como suas dependências são criadas.
Isso facilita testes unitários, reutilização de código e substituição de implementações sem mudar o código principal.
Exemplo prático (em Python)
No exemplo abaixo, a classe ServicoDeUsuario
depende de um RepositorioDeUsuarios
para funcionar. Em vez de criar essa dependência internamente, ela a recebe de fora:
# Dependência
class RepositorioDeUsuarios:
def buscar(self, id):
return f"Usuário {id}"
# Serviço com dependência injetada
class ServicoDeUsuario:
def __init__(self, repositorio):
self.repositorio = repositorio
def obter_usuario(self, id):
return self.repositorio.buscar(id)
# Injeção de dependência
repo = RepositorioDeUsuarios()
servico = ServicoDeUsuario(repo)
print(servico.obter_usuario(1))
Agora, é fácil substituir o repositório por uma implementação de teste:
class RepositorioTeste:
def buscar(self, id):
return f"Usuário teste {id}"
servico_teste = ServicoDeUsuario(RepositorioTeste())
print(servico_teste.obter_usuario(1)) # saída: Usuário teste 1
Esse é um exemplo de injeção via construtor. Também existem outras formas, como injeção via método ou via atributo (em linguagens que suportam).
Outras formas de injeção
Além da injeção via construtor, existem outras formas comuns de aplicar Injeção de Dependência:
A dependência é fornecida por meio de um método específico, o que pode ser útil quando o objeto já foi criado ou precisa mudar dinamicamente de dependência.
class ServicoDeUsuario:
def configurar_repositorio(self, repositorio):
self.repositorio = repositorio
def obter_usuario(self, id):
return self.repositorio.buscar(id)
servico = ServicoDeUsuario()
servico.configurar_repositorio(RepositorioDeUsuarios())
print(servico.obter_usuario(1))
A dependência é atribuída diretamente em um atributo da classe. Esse modelo é comum em frameworks que automatizam a injeção por meio de anotações ou decorators.
class ServicoDeUsuario:
repositorio = None # Atribuído de fora
def obter_usuario(self, id):
return self.repositorio.buscar(id)
servico = ServicoDeUsuario()
servico.repositorio = RepositorioDeUsuarios()
print(servico.obter_usuario(1))