Quais são os benefícios do uso de injeção de dependência e contêineres IoC?


62

Estou planejando fazer uma palestra sobre Injeção de Dependência e IoC Containers, e estou procurando alguns bons argumentos para usá-lo.

Quais são os benefícios mais importantes do uso dessa técnica e dessas ferramentas?


1
Veja aqui e aqui as respostas do StackOverflow e aqui um bom artigo completo sobre IoC. E se você quiser argumentos contra ele para comparação, acesse aqui o SO.
Jesse C. Slicer

14
para não ser um bumbum ... mas se você não sabe por que o DI / COI deve ser usado, por que está falando sobre isso? perder uma aposta? ;-)
Steven A. Lowe

2
@Steven, seu chefe pode ter pedido para ele fazer isso.

1
@ Steven, eu já uso DI o tempo todo (alguns diriam com muita frequência :-D), só estou procurando por bons argumentos para que outras pessoas o usem.
Andy Lowry

2
As pessoas raramente falam sobre o uso excessivo de DI. Se você adiar cada decisão, criará o equivalente de OO ao código de espaguete. Ter um design coerente requer que, em algum momento, seja tomada uma decisão real.
Macneil 15/12

Respostas:


47

O mais importante, para mim, é facilitar o cumprimento do Princípio da Responsabilidade Única .

O DI / IoC simplifica o gerenciamento de dependências entre objetos. Por sua vez, isso facilita a quebra de funcionalidade coerente em seu próprio contrato (interface). Como resultado, meu código foi muito mais modularizado desde que aprendi sobre DI / IoC.

Outro resultado disso é que eu posso ver muito mais facilmente o caminho para um design que suporta o Princípio Aberto-Fechado . Essa é uma das técnicas mais inspiradoras de confiança (perdendo apenas para testes automatizados). Duvido que eu pudesse adotar as virtudes do Princípio Aberto-Fechado o suficiente.

O DI / IoC é uma das poucas coisas na minha carreira de programador que tem mudado o jogo. Existe uma enorme lacuna na qualidade entre o código que escrevi antes e depois de aprender DI / IoC. Deixe-me enfatizar isso um pouco mais. ENORME melhoria na qualidade do código.


3
Por que o Princípio Aberto-Fechado é tão importante? Se você sente que precisa alterar uma API / interface, por que não deveria?
Arne Evertsson

@ArneEvertsson Ouça Robert C. Martin falando sobre o Princípio Aberto-Fechado. Você será iluminado.
Alternatex

O @AmeEvertsson Aberto-Fechado é muito importante quando seu código é fornecido (por exemplo, como um produto comercial) como um módulo para uso de outras pessoas, pois torna seu código mais adaptável em uso sem que eles revertam para você para alterá-lo
James Ellis-Jones

2
O DI não simplifica o gerenciamento de dependências, pois é consideravelmente mais complexo do que simplesmente criar uma dependência para uma classe concreta. No entanto, fornece flexibilidade, mas, a menos que você esteja realizando testes de unidade 'adequados', essa flexibilidade geralmente não será necessária. As duas principais vantagens descritas também se aplicam ao Service Locator, que é mais simples.
James Ellis-Jones

1
Eu diminuí a votação desta resposta anos atrás; aqui estão algumas observações: 1) Na prática, o uso extensivo de DI tende a funcionar contra o SRP, porque os programadores simplesmente continuam adicionando métodos aos seus "controladores", "serviços", "DAOs" etc. injetados, em vez de criar novas classes para nova funcionalidade. É o que você normalmente vê acontecendo em projetos Java e C # .NET que usa alguma estrutura ou contêiner de DI. 2) O princípio aberto-fechado era apenas a ilusão de Bertrand Meyer sobre a utilidade da herança de classe (implementação); se você pesquisar em seu livro de mais de 1400 páginas, verá o que quero dizer - é realmente bobo.
Rogério

9

Os exemplos que realmente abriram meus olhos foram ver como tornou possível testar com facilidade os objetos criados dessa maneira. Antes disso, tive problemas ao tentar isolar objetos para um teste de unidade. Eu costumava escrever testes para interagir com um sistema muito maior. Isso foi realmente difícil, porque o sistema como um todo era muito menos previsível e muito mais propenso a mudanças do que os componentes individuais.


3

As vantagens das injeções de dependência são:

  1. Seu código é limpo e mais legível.
  2. Os códigos são fracamente acoplados.
  3. Mais reutilizáveis, pois as implementações são configuradas no arquivo XML, e podem ser usadas em um contexto diferente.
  4. O código pode ser facilmente testável com diferentes implementações simuladas.

1

Eu acho que os benefícios reais são mais políticos do que técnicos. O DI é simplesmente uma alternativa ao padrão do Localizador de Serviço , nada mais. Por si só, não facilita seguir princípios como SRP ou OCP, nem dissociar camadas. Outros entrevistados aqui estão confundindo diferentes conceitos e técnicas, IMO.

Você pode atingir os mesmos objetivos com relação à alta coesão e baixo acoplamento usando Localizadores de Serviço ou simplesmente instanciando dependências diretamente sempre que aplicável (o que é na maioria das vezes).

Agora, eu sei que muitos vão discordar dessa opinião. Ficarei feliz em discutir exemplos concretos.


2
Mas invocar diretamente um localizador de serviço ou instanciar uma dependência concreta geralmente conecta suas dependências, ou pelo menos de onde elas vêm. Isso parece derrotar o objetivo da DI. Você ainda precisa injetar o localizador de serviço também.
Matt H

O uso de um localizador de serviço não liga nada, exceto o uso da própria classe localizador de serviço, que normalmente não é "injetada". Instanciar uma classe de implementação concreta é perfeitamente adequado nos casos em que você não precisa de configuração externa (por exemplo, programadores geralmente instanciam diretamente a classe ArrayList em vez de usar DI - o que seria um exagero).
Rogério

1
Você menciona "baixo acoplamento" e, mais tarde, diz que um localizador de serviço não afeta o nível de acoplamento de um aplicativo. O mesmo para instanciar colaboradores diretamente no código, não consigo pensar em uma maneira mais perfeita de associar um objeto a suas dependências. Como você faz testes de unidade nos dois cenários? Eu, respeitosamente, discordo completamente de tudo o que você disse.
Clint Eastwood

@ Jonathan Você deve ler o artigo que introduziu o DI ; o autor conclui dizendo que DI e ServiceLocator são "aproximadamente equivalentes", com uma "ligeira vantagem" para o último. O acoplamento que importa é entre um componente e outros componentes que podem ter várias implementações; um ServiceLocator é um serviço de infraestrutura com apenas uma implementação, então está tudo bem. Note que escrevi "instanciando dependências sempre que aplicável "; é claro, se você precisar separar a configuração do uso, não faria isso.
Rogério

1
@ Jonathan Com relação aos testes de unidade, é um mito que instanciar colaboradores impede a criação de tais testes; existem ferramentas de simulação conhecidas que fazem o trabalho de isolar uma classe das implementações de dependência, sejam elas injetadas ou não.
Rogério

-1

Quando o DI é usado para expor objetos internos para fins de teste, o padrão foi abusado.


1
o que você quer dizer com "objetos internos"? no OOP real (observe que provavelmente apenas 1% dos programadores sabem o que isso realmente significa), há objetos se comunicando entre si por meio do envio de mensagens (ou seja, invocações de métodos). Nesse sentido, cada objeto deve ter uma única responsabilidade, não há objetos "mais importantes" que outros ... cada um tem um único dever e eles cooperam para alcançar a funcionalidade fornecida por todo o sistema. É importante testar todos os objetos de maneira isolada, para que saibamos que não perdemos nenhum caso, é nisso que o DI é realmente bom.
Clint Eastwood

Eu esqueci.
thomas-peter
Ao utilizar nosso site, você reconhece que leu e compreendeu nossa Política de Cookies e nossa Política de Privacidade.
Licensed under cc by-sa 3.0 with attribution required.