Eu sou novo na injeção de dependência e tenho algumas perguntas sobre qual estilo devo usar em meus aplicativos. Acabei de ler Inversão de controle de contêineres e o padrão de injeção de dependência de Martin Fowler, mas não consigo obter a diferença prática entre construtor, setter e injeção de interface.
Parece-me que os motivos para usar um sobre o outro são apenas uma questão de limpeza e / ou clareza do código. Qual é a diferença? Existem fortes vantagens ou desvantagens em usar um sobre o outro, ou é exatamente o que afirmei antes?
Na minha opinião, a injeção de construtor é a mais intuitiva de todas, assim como a injeção de interface é a menor. Por outro lado, a injeção de setter é um termo intermediário, mas você deve poder alterar a instância do objeto de dependência que você injetou inicialmente? Esse estilo de injeção garante que o objeto que precisa da dependência sempre o injete? Eu acredito que não, mas por favor me corrija se eu estiver errado.
Respostas:
A injeção de construtor tem a vantagem de explicitar a dependência e forçar o cliente a fornecer uma instância. Também pode garantir que o cliente não possa alterar a instância posteriormente. Uma (possível) desvantagem é que você precisa adicionar um parâmetro ao seu construtor.
A Injeção de Setter tem a vantagem de não exigir a adição de um parâmetro ao construtor. Também não requer que o cliente defina a instância. Isso é útil para dependências opcionais. Isso também pode ser útil se você desejar que a classe crie, por exemplo, um repositório de dados real por padrão e, em um teste, você pode usar o configurador para substituí-lo por uma instância de teste.
A injeção de interface , até onde eu sei, não é muito diferente da injeção de incubadora. Nos dois casos, você está (opcionalmente) configurando uma dependência que pode ser alterada posteriormente.
Em última análise, é uma questão de preferência e se é necessária ou não uma dependência . Pessoalmente, uso quase exclusivamente a injeção de construtores. Eu gosto que ele explique as dependências de uma classe, forçando o cliente a fornecer uma instância no construtor. Também gosto que o cliente não possa alterar a instância após o fato.
Muitas vezes, minha única razão para passar em duas implementações separadas é para testar. Na produção, posso passar em a
DataRepository
, mas nos testes, emFakeDataRepository
. Nesse caso, geralmente fornecerei dois construtores: um sem parâmetros e outro que aceita aIDataRepository
. Então, no construtor sem parâmetros, encadeará uma chamada para o segundo construtor e passarei anew DataRepository()
.Aqui está um exemplo em c #:
Isso é conhecido como Injeção de Dependência do Pobre Homem. Gosto porque, no código do cliente de produção, não preciso me repetir tendo várias instruções repetidas que parecem
No entanto, ainda posso passar em uma implementação alternativa para teste. Percebo que, com o DI do Poor Man, estou codificando minha dependência, mas isso é aceitável para mim, pois eu o uso principalmente para testes.fonte
As diferenças entre a injeção do construtor e da incubadora já estão descritas adequadamente acima, então não vou detalhar mais sobre elas.
A injeção de interface é uma forma mais avançada de injeção, útil porque permite que a dependência seja decidida no momento em que é usada, e não durante a inicialização do objeto que a usará. Isso permite várias opções úteis:
A dependência pode ter um escopo diferente do objeto no qual ele é injetado; por exemplo, você pode usar a injeção de interface para fornecer um objeto para o qual existe por sessão do usuário ou por thread para um singleton global. Sempre que o objeto precisar da dependência, ele chamará o método getter fornecido pela estrutura, e isso poderá retornar resultados diferentes, dependendo da situação em que for chamado.
Permite uma inicialização lenta - não é necessário inicializar a dependência até que esteja prestes a ser usada
Ele permite que as dependências sejam carregadas de uma cópia em cache quando elas existem ou reinicializadas quando não existem (por exemplo, usando uma
SoftReference
em Java).Obviamente, técnicas avançadas como essa têm desvantagens; Nesse caso, o principal problema é que o código se torna menos claro (as classes usadas em seu código se tornam abstratas e não há uma implementação concreta óbvia delas, o que pode ser confuso se você não estiver acostumado) e se torna mais dependente na estrutura de injeção de dependência (ainda é possível instanciar seus objetos manualmente, é claro, mas é mais difícil do que com outros estilos de injeção).
fonte