Inversão de Controle vs Injeção de Dependência

De acordo com o artigo escrito por Martin Fowler , a inversão de controle é o princípio em que o stream de controle de um programa é invertido: em vez de o programador controlar o stream de um programa, as fonts externas (estrutura, serviços, outros componentes) assumem o controle. isto. É como se nós colocássemos algo em outra coisa. Ele mencionou um exemplo sobre o EJB 2.0:

Por exemplo, a interface do Session Bean define ejbRemove, ejbPassivate (armazenado no armazenamento secundário) e ejbActivate (restaurado do estado passivo). Você não consegue controlar quando esses methods são chamados, apenas o que eles fazem. O contêiner nos chama, nós não o chamamos.

Isso leva à diferença entre o framework e a biblioteca:

A inversão de controle é uma parte fundamental do que torna um framework diferente de uma biblioteca. Uma biblioteca é essencialmente um conjunto de funções que você pode chamar, geralmente organizadas em classs. Cada chamada faz algum trabalho e devolve o controle ao cliente.

Eu acho que o ponto de vista de que DI é COI significa que a dependência de um object é invertida: em vez disso, ele controla suas próprias dependencies, ciclo de vida … outra coisa faz isso por você. Mas, como você me falou sobre DI por mãos, DI não é necessariamente COI. Ainda podemos ter DI e nenhum COI.

No entanto, neste artigo (da pococapsule, outro IOC Framework para C / C ++), ele sugere que, devido ao IOC e DI, os contêineres do IOC e as estruturas DI são muito superiores ao J2EE, já que o J2EE mistura o código da estrutura nos componentes , assim não o tornando Objeto Java / C ++ Plain Old (POJO / POCO).

Inversão de Contêineres de Controle que não o padrão de Injeção de Dependência (link de Arquivo)

Leitura adicional para entender qual é o problema com a antiga Estrutura de Desenvolvimento Baseada em Componente, que leva ao segundo artigo acima: Por que e o que é Inversão de Controle ?

Minha pergunta : o que exatamente é IOC e DI? Estou confuso. Baseado na pococapsule, o IOC é algo mais significativo do que simplesmente inverter o controle entre objects ou programadores e frameworks.

IoC é um termo genérico que significa, em vez de ter o aplicativo, chamar os methods em um framework, o framework chama implementações fornecidas pelo aplicativo.

DI é uma forma de IoC, onde as implementações são passadas para um object por meio de pesquisas de construtores / setters / service, das quais o object dependerá para se comportar corretamente.

IoC sem usar DI , por exemplo, seria o padrão de modelo porque a implementação só pode ser alterada por meio de subsorting.

As estruturas de DI são projetadas para fazer uso da DI e podem definir interfaces (ou Anotações em Java) para facilitar a transmissão das implementações.

Contêineres IoC são estruturas de DI que podem funcionar fora da linguagem de programação. Em alguns você pode configurar quais implementações usar em arquivos de metadados (por exemplo, XML) que são menos invasivos. Com alguns você pode fazer o IoC que normalmente seria impossível, como injetar uma implementação nos pontos de corte .

Veja também este artigo de Martin Fowler .

Em suma, IoC é um termo muito mais amplo que inclui, mas não está limitado a, DI

O termo Inversion of Control (IoC) originalmente significava qualquer tipo de estilo de programação em que uma estrutura geral ou tempo de execução controlasse o stream do programa.

Antes de DI ter um nome, as pessoas começaram a se referir a frameworks que gerenciavam Dependências como Inversão de Contêineres de Controle, e logo, o significado de IoC gradualmente se direcionou para esse significado particular: Inversão do Controle sobre Dependências.

Inversão de Controle (IoC) significa que os objects não criam outros objects nos quais eles confiam para fazer seu trabalho. Em vez disso, eles obtêm os objects de que precisam de uma fonte externa (por exemplo, um arquivo de configuração xml).

dependency injection (DI) significa que isso é feito sem a intervenção do object, geralmente por um componente de estrutura que passa parâmetros de construtor e propriedades de conjunto.

DI é um subconjunto do IoC

  • IoC significa que os objects não criam outros objects nos quais eles dependem para fazer seu trabalho. Em vez disso, eles obtêm os objects de que precisam de um serviço externo (por exemplo, arquivo xml ou serviço de aplicativo único). 2 implementações de IoC, eu uso, são DI e ServiceLocator.
  • DI significa que o princípio IoC de obter objects dependentes é feito sem usar objects concretos, mas abstrações (interfaces). Isso torna todos os componentes da cadeia testáveis, pois componentes de nível mais alto não dependem do componente de nível inferior, apenas da interface. Mocks implementam essas interfaces.

Aqui estão algumas outras técnicas para alcançar o IoC .

IOC (Inversion Of Controller) : Dar controle ao contêiner para obter uma instância do object é chamado Inversion of Control., Significa que, em vez de você estar criando um object usando o novo operador, deixe o contêiner fazer isso para você.

DI (Injeção de Dependência) : O modo de injeção de propriedades em um object é chamado de injeção de dependência.

We have three types of Dependency injection 1) Constructor Injection 2) Setter/Getter Injection 3) Interface Injection 

O Spring suportará apenas Injeção de Construtor e Injeção de Setter / Getter.

insira a descrição da imagem aqui
fonte

IoC ( I nversão de C ontrol): – É um termo genérico e implementado de várias formas (events, delegates, etc.).

DI ( D ependency I njection): – DI é um sub-tipo de IoC e é implementado por injeção de construtor, injeção de setter ou injeção de interface .

Mas, o Spring suporta apenas os dois tipos a seguir:

  • Injeção Setter
    • A DI baseada em setter é realizada chamando methods setter nos beans do usuário depois de chamar um construtor sem argumento ou um método de fábrica estático sem argumento para instanciar seu bean.
  • Injeção de Construtor
    • A DI baseada em construtor é realizada invocando um construtor com vários argumentos, cada um representando um colaborador. Usando isso, podemos validar que os beans injetados não são nulos e falham rapidamente (tempo de compilation), portanto, ao iniciar o aplicativo, obtemos NullPointerException: bean does not exist . A injeção de construtor é a melhor prática para injetar dependencies.

Mas a documentação da primavera diz que eles são iguais.

http://docs.spring.io/spring/docs/current/spring-framework-reference/htmlsingle/#beans-introduction

Na primeira linha, ” IoC também é conhecido como injeção de dependência (DI) “.

IoC – Inversão de controle é termo genérico, independente da linguagem, na verdade não é criar os objects, mas descrever em qual object de moda está sendo criado.

DI – Dependency Injection é um termo concreto, no qual nós fornecemos dependencies do object em tempo de execução usando diferentes técnicas de injeção, viz. Injeção de Setter, Injeção de Construtor ou por Injeção de Interface.

Inversão de controle é um paradigma de design com o objective de dar mais controle aos componentes-alvo de sua aplicação, aqueles que estão realizando o trabalho.
dependency injection é um padrão usado para criar instâncias de objects nos quais outros objects dependem sem saber em tempo de compilation qual class será usada para fornecer essa funcionalidade.

Existem várias técnicas básicas para implementar a inversão de controle. Esses são:

  • Usando um padrão de fábrica
  • Usando um padrão de localizador de serviço
  • Usando uma injeção de dependência de qualquer tipo abaixo:

    1). Uma injeção de construtor
    2). Uma injeção setter
    3). Uma injeção de interface

Como todas as respostas enfatizam a teoria, gostaria de demonstrar com um exemplo a primeira abordagem:

Suponha que estamos construindo um aplicativo que contém um recurso para enviar mensagens de confirmação SMS assim que o pedido for enviado. Nós teremos duas classs, uma é responsável por enviar o SMS (SMSService), e outro responsável por capturar as inputs do usuário (UIHandler), nosso código terá a seguinte aparência:

 public class SMSService { public void SendSMS(string mobileNumber, string body) { SendSMSUsingGateway(mobileNumber, body); } private void SendSMSUsingGateway(string mobileNumber, string body) { /*implementation for sending SMS using gateway*/ } } public class UIHandler { public void SendConfirmationMsg(string mobileNumber) { SMSService _SMSService = new SMSService(); _SMSService.SendSMS(mobileNumber, "Your order has been shipped successfully!"); } } 

A implementação acima não está errada, mas há poucos problemas:
-) Suponha que, no ambiente de desenvolvimento, você queira salvar os SMSs enviados para um arquivo de texto em vez de usar o gateway SMS, para conseguir isso; vamos acabar mudando a implementação concreta de (SMSService) com outra implementação, estamos perdendo a flexibilidade e forçados a rewrite o código neste caso.
-) Vamos acabar misturando as responsabilidades das classs, o nosso (UIHandler) nunca deve saber sobre a implementação concreta do (SMSService), isso deve ser feito fora das classs usando “Interfaces”. Quando isso for implementado, ele nos dará a capacidade de alterar o comportamento do sistema, trocando o (SMSService) usado com outro serviço simulado que implementa a mesma interface, esse serviço salvará SMSs em um arquivo de texto em vez de enviar para o mobileNumber.

Para corrigir os problemas acima utilizamos Interfaces que serão implementadas pelo nosso (SMSService) e o novo (MockSMSService), basicamente a nova Interface (ISMSService) irá expor os mesmos comportamentos de ambos os serviços conforme o código abaixo:

 public interface ISMSService { void SendSMS(string phoneNumber, string body); } 

Em seguida, alteraremos nossa implementação (SMSService) para implementar a interface (ISMSService):

 public class SMSService : ISMSService { public void SendSMS(string mobileNumber, string body) { SendSMSUsingGateway(mobileNumber, body); } private void SendSMSUsingGateway(string mobileNumber, string body) { /*implementation for sending SMS using gateway*/ Console.WriteLine("Sending SMS using gateway to mobile: {0}. SMS body: {1}", mobileNumber, body); } } 

Agora poderemos criar um novo serviço de simulação (MockSMSService) com implementação totalmente diferente usando a mesma interface:

 public class MockSMSService :ISMSService { public void SendSMS(string phoneNumber, string body) { SaveSMSToFile(phoneNumber,body); } private void SaveSMSToFile(string mobileNumber, string body) { /*implementation for saving SMS to a file*/ Console.WriteLine("Mocking SMS using file to mobile: {0}. SMS body: {1}", mobileNumber, body); } } 

Neste ponto, podemos alterar o código em (UIHandler) para usar a implementação concreta do serviço (MockSMSService) facilmente como abaixo:

 public class UIHandler { public void SendConfirmationMsg(string mobileNumber) { ISMSService _SMSService = new MockSMSService(); _SMSService.SendSMS(mobileNumber, "Your order has been shipped successfully!"); } } 

Conseguimos muita flexibilidade e implementamos a separação de interesses em nosso código, mas ainda precisamos fazer uma alteração na base de código para alternar entre os dois Serviços do SMS. Então, precisamos implementar a Injeção de Dependência .

Para conseguir isso, precisamos implementar uma mudança em nosso construtor de class (UIHandler) para passar a dependência através dele, fazendo isso, o código que usa o (UIHandler) pode determinar qual implementação concreta de (ISMSService) usar:

 public class UIHandler { private readonly ISMSService _SMSService; public UIHandler(ISMSService SMSService) { _SMSService = SMSService; } public void SendConfirmationMsg(string mobileNumber) { _SMSService.SendSMS(mobileNumber, "Your order has been shipped successfully!"); } } 

Agora o formulário da interface do usuário que irá falar com a class (UIHandler) é responsável por passar qual implementação da interface (ISMSService) consumir. Isso significa que invertemos o controle, o (UIHandler) não é mais responsável por decidir qual implementação usar, o código de chamada faz. Nós implementamos o princípio de Inversão de Controle , no qual DI é um tipo dele.

O código do formulário da interface do usuário será o seguinte:

 class Program { static void Main(string[] args) { ISMSService _SMSService = new MockSMSService(); // dependency UIHandler _UIHandler = new UIHandler(_SMSService); _UIHandler.SendConfirmationMsg("96279544480"); Console.ReadLine(); } } 

O IOC indica que uma class externa gerenciando as classs de um aplicativo e classs externas significa que um contêiner gerencia a dependência entre a class de aplicativo. O conceito básico do IOC é que o programador não precisa criar seus objects, mas descreve como eles devem ser criados.

As principais tarefas executadas pelo contêiner IoC são: instanciar a class do aplicativo. para configurar o object. para montar as dependencies entre os objects.

DI é o processo de fornecer as dependencies de um object em tempo de execução usando injeção de setter ou injeção de construtor.

IOC (Inversion Of Controller): Dar controle ao contêiner para obter a instância de object chama-se Inversion of Control., Significa que, em vez de você estar criando o object usando new operator , deixe o contêiner fazer isso por você.

DI (Injeção de Dependência): Passar os parâmetros necessários (propriedades) do XML para um object (no POJO CLASS) é chamado de injeção de dependência.

O IOC (Inversion of Control) é basicamente o conceito de padrão de projeto de remover dependencies e desacoplá-las para tornar o stream não-linear e permitir que o contêiner / ou outra entidade gerencie o provisionamento de dependencies. Na verdade, segue o diretor de Hollywood: “Não ligue para nós, ligaremos para você”. Então resumindo as diferenças.

Inversão de controle: – É um termo genérico para dissociar as dependencies e delegar seu provisionamento, e isso pode ser implementado de várias maneiras (events, delegates, etc).

dependency injection: – DI é um subtipo de IOC e é implementado por injeção de construtor, injeção de setter ou injeção de método.

O seguinte artigo descreve isso muito bem.

https://www.codeproject.com/Articles/592372/Dependency-Injection-DI-vs-Inversion-of-Control-IO

DI e IOC são padrões de projeto que focalizam principalmente o fornecimento de acoplamentos frouxos entre componentes, ou simplesmente uma maneira em que nós dissociamos as relações de dependência convencionais entre objects de forma que os objects não sejam apertados um ao outro.

Com os exemplos a seguir, estou tentando explicar esses dois conceitos.

Anteriormente estamos escrevendo código como este

 Public MyClass{ DependentClass dependentObject /* At somewhere in our code we need to instantiate the object with new operator inorder to use it or perform some method. */ dependentObject= new DependentClass(); dependentObject.someMethod(); } 

Com injeção de dependência, o injetor de dependência cuidará da instanciação de objects

 Public MyClass{ /* Dependency injector will instantiate object*/ DependentClass dependentObject /* At somewhere in our code we perform some method. The process of instantiation will be handled by the dependency injector */ dependentObject.someMethod(); } 

O processo acima de dar o controle a algum outro (por exemplo, o contêiner) para instanciação e injeção pode ser denominado como Inversão de Controle e o processo no qual o contêiner IOC injetar a dependência para nós pode ser denominado como injeção de dependência.

IOC é o princípio em que o stream de controle de um programa é invertido: em vez de o programador controlar o stream de um programa, o programa controla o stream reduzindo a sobrecarga para o programador. E o processo usado pelo programa para injetar dependência é denominado como DI

Os dois conceitos trabalham juntos, fornecendo-nos uma maneira de escrever código muito mais flexível, reutilizável e encapsulado, o que os torna conceitos importantes na criação de soluções orientadas a objects.

Também recomendo ler.

O que é injeção de dependência?

Inversão de Controle é um princípio de design genérico da arquitetura de software que auxilia na criação de estruturas de software modulares e reutilizáveis ​​que são fáceis de manter.

É um princípio de design no qual o Fluxo de Controle é “recebido” da biblioteca genérica ou código reutilizável.

Para entender melhor, vamos ver como usamos o código em nossos primeiros dias de codificação. Em linguagens procedurais / tradicionais, a lógica de negócios geralmente controla o stream do aplicativo e “chama” o código / funções genérico ou reutilizável. Por exemplo, em um aplicativo de console simples, meu stream de controle é controlado pelas instruções do meu programa, que podem include as chamadas para algumas funções gerais reutilizáveis.

 print ("Please enter your name:"); scan (&name); print ("Please enter your DOB:"); scan (&dob); //More print and scan statements  //Call a Library function to find the age (common code) print Age 

Em contraste, com o IoC, os Frameworks são o código reutilizável que “chama” a lógica de negócios.

Por exemplo, em um sistema baseado em Windows, uma estrutura já estará disponível para criar elementos da interface do usuário, como botões, menus, janelas e checkboxs de diálogo. Quando escrevo a lógica de negócios do meu aplicativo, os events do framework chamam o código de lógica de negócios (quando um evento é acionado) e NÃO o contrário.

Embora o código da estrutura não esteja ciente da minha lógica de negócios, ela ainda saberá como chamar meu código. Isto é conseguido usando events / delegates, retornos de chamada, etc. Aqui o Controle de stream é “Invertido”.

Portanto, em vez de depender do stream de controle em objects estaticamente vinculados, o stream depende do gráfico geral do object e das relações entre objects diferentes.

dependency injection é um padrão de design que implementa o princípio IoC para resolver dependencies de objects.

Em palavras mais simples, quando você está tentando escrever código, você estará criando e usando classs diferentes. Uma class (Classe A) pode usar outras classs (Classe B e / ou D). Assim, as classs B e D são dependencies da class A.

Uma analogia simples será uma class Car. Um carro pode depender de outras classs como Engine, Tires e mais.

A Injeção de Dependência sugere que, em vez das classs Dependentes (Classe Carro aqui), criando suas dependencies (Mecanismo de Classe e Classe de Pneu), a class deve ser injetada com a instância concreta da dependência.

Vamos entender com um exemplo mais prático. Considere que você está escrevendo seu próprio TextEditor. Entre outras coisas, você pode ter um corretor ortográfico que fornece ao usuário uma facilidade para verificar os erros de digitação em seu texto. Uma implementação simples de tal código pode ser:

 Class TextEditor { //Lot of rocket science to create the Editor goes here EnglishSpellChecker objSpellCheck; String text; public void TextEditor() { objSpellCheck = new EnglishSpellChecker(); } public ArrayList  CheckSpellings() { //return Typos; } } 

À primeira vista, tudo parece rosado. O usuário irá escrever algum texto. O desenvolvedor irá capturar o texto e chamar a function CheckSpellings e encontrará uma lista de erros de digitação que ele mostrará ao usuário.

Tudo parece funcionar muito bem até um belo dia, quando um usuário começa a escrever francês no editor.

Para fornecer o suporte para mais idiomas, precisamos ter mais SpellCheckers. Provavelmente francês, alemão, espanhol etc.

Aqui, nós criamos um código fortemente acoplado com o SpellChecker “Inglês” sendo fortemente acoplado à nossa class TextEditor, o que significa que nossa class TextEditor depende do EnglishSpellChecker ou, em outras palavras, o EnglishSpellCheker é a dependência do TextEditor. Precisamos remover essa dependência. Além disso, nosso editor de texto precisa ter uma maneira de manter a referência concreta de qualquer verificador ortográfico com base na discrição do desenvolvedor em tempo de execução.

Então, como vimos na introdução da DI, sugere que a class deve ser injetada com suas dependencies. Portanto, deve ser responsabilidade do código de chamada injetar todas as dependencies na class / código chamada. Então, podemos reestruturar nosso código como

 interface ISpellChecker { Arraylist CheckSpelling(string Text); } Class EnglishSpellChecker : ISpellChecker { public override Arraylist CheckSpelling(string Text) { //All Magic goes here. } } Class FrenchSpellChecker : ISpellChecker { public override Arraylist CheckSpelling(string Text) { //All Magic goes here. } } 

Em nosso exemplo, a class TextEditor deve receber a instância concreta do tipo ISpellChecker.

Agora, a dependência pode ser injetada no construtor, uma propriedade pública ou um método.

Vamos tentar mudar nossa class usando o Construtor DI. A class TextEditor alterada será algo como:

 Class TextEditor { ISpellChecker objSpellChecker; string Text; public void TextEditor(ISpellChecker objSC) { objSpellChecker = objSC; } public ArrayList  CheckSpellings() { return objSpellChecker.CheckSpelling(); } } 

Para que o código de chamada, ao criar o editor de texto, possa injetar o SpellChecker Type apropriado na instância do TextEditor.

Você pode ler o artigo completo aqui

Vamos começar com D do SOLID e ver DI e IoC do livro de Scott Millett “Professional ASP.NET Design Patterns”:

Princípio de Inversão de Dependência (DIP)

O DIP trata de isolar suas classs de implementações concretas e fazer com que elas dependam de classs ou interfaces abstratas. Ele promove o mantra de codificação para uma interface, em vez de uma implementação, o que aumenta a flexibilidade dentro de um sistema, garantindo que você não esteja fortemente acoplado a uma implementação.

Injeção de Dependência (DI) e Inversão de Controle (IoC)

Intimamente ligados ao DIP estão o princípio DI e o princípio IoC. DI é o ato de fornecer uma class dependente ou de baixo nível através de um construtor, método ou propriedade. Usadas em conjunto com DI, essas classs dependentes podem ser invertidas para interfaces ou classs abstratas que levarão a sistemas fracamente acoplados que são altamente testáveis ​​e fáceis de alterar.

No IoC , o stream de controle de um sistema é invertido em comparação com a programação procedural. Um exemplo disso é um contêiner IoC , cuja finalidade é injetar serviços no código do cliente sem ter o código do cliente especificando a implementação concreta. O controle nesta instância que está sendo invertido é o ato do cliente obter o serviço.

Millett, C (2010). Padrões profissionais de design do ASP.NET. Publicação Wiley. 7-8.

// ICO, DI, 10 anos atrás, era assim:

 public class AuditDAOImpl implements Audit{ //dependency AuditDAO auditDAO = null; //Control of the AuditDAO is with AuditDAOImpl because its creating the object public AuditDAOImpl () { this.auditDAO = new AuditDAO (); } } 

Agora, com a spring 3,4 ou mais recente, como abaixo

 public class AuditDAOImpl implements Audit{ //dependency //Now control is shifted to Spring. Container find the object and provide it. @Autowired AuditDAO auditDAO = null; } 

Em geral, o controle é invertido do antigo conceito de código acoplado para os frameworks como Spring, o que torna o object disponível. Então isso é o COI até onde eu sei e injeção de dependência como você sabe quando nós injetamos o object dependente em outro object usando Construtor ou setters. Injetar basicamente significa passá-lo como um argumento. Na primavera, temos uma configuração baseada em XML e anotação, onde definimos o object bean e passamos o object dependente com o estilo de injeção Constructor ou setter.

Eu encontrei o melhor exemplo em Dzone.com, que é realmente útil para entender o real diferente entre IOC e DI

“IoC é quando você tem alguém para criar objects para você.” Então, em vez de escrever uma palavra-chave “new” (por exemplo, MyCode c = new MyCode ()) em seu código, o object é criado por outra pessoa. Essa ‘outra pessoa’ é normalmente referida como um contêiner IoC. Isso significa que nós entregamos a rrsponsibility (controle) para o container para obter a instância de object que é chamada Inversion of Control., Significa que em vez de você estar criando um object usando o novo operador, deixe o container fazer isso por você.

  DI(Dependency Injection): Way of injecting properties to an object is called Dependency injection. We have three types of Dependency injection 1) Constructor Injection 2) Setter/Getter Injection 3) Interface Injection Spring will support only Constructor Injection and Setter/Getter Injection. 

Leia o artigo completo IOC e leia o artigo completo DI

1) DI é Child-> obj depende de pai-obj. O verbo depende é importante. 2) IOC é Child-> obj executar sob uma plataforma. onde a plataforma poderia ser escola, faculdade, aula de dança. Aqui, executar é uma atividade com implicação diferente em qualquer provedor de plataforma.

exemplo prático: `

 //DI child.getSchool(); //IOC child.perform()// is a stub implemented by dance-school child.flourish()// is a stub implemented by dance-school/school/ 

`

-AB