Inversão de controle (IoC) pode ser bastante confusa quando é encontrada pela primeira vez.
- O que é isso?
- Qual problema ele resolve?
- Quando é apropriado usar e quando não?
Inversão de controle (IoC) pode ser bastante confusa quando é encontrada pela primeira vez.
Respostas:
Os padrões Inversion of Control (IoC) e Injection Dependency Injection (DI) têm como objetivo remover dependências do seu código.
Por exemplo, diga que seu aplicativo possui um componente de editor de texto e você deseja fornecer a verificação ortográfica. Seu código padrão ficaria assim:
public class TextEditor {
private SpellChecker checker;
public TextEditor() {
this.checker = new SpellChecker();
}
}
O que fizemos aqui cria uma dependência entre o TextEditor
e o SpellChecker
. Em um cenário de IoC, faríamos algo assim:
public class TextEditor {
private IocSpellChecker checker;
public TextEditor(IocSpellChecker checker) {
this.checker = checker;
}
}
No primeiro exemplo de código, estamos instanciando SpellChecker
( this.checker = new SpellChecker();
), o que significa que a TextEditor
classe depende diretamente da SpellChecker
classe.
No segundo exemplo de código, estamos criando uma abstração tendo a SpellChecker
classe de dependência na TextEditor
assinatura do construtor (não inicializando a dependência na classe). Isso nos permite chamar a dependência e passá-la para a classe TextEditor da seguinte maneira:
SpellChecker sc = new SpellChecker; // dependency
TextEditor textEditor = new TextEditor(sc);
Agora, o cliente que cria a TextEditor
classe tem controle sobre qual SpellChecker
implementação usar, porque estamos injetando a dependência na TextEditor
assinatura.
Inversão de controle é o que você obtém quando o programa retorna, por exemplo, como um programa de GUI.
Por exemplo, em um menu da velha escola, você pode ter:
print "enter your name"
read name
print "enter your address"
read address
etc...
store in database
controlando assim o fluxo de interação do usuário.
Em um programa GUI ou algo assim, dizemos:
when the user types in field a, store it in NAME
when the user types in field b, store it in ADDRESS
when the user clicks the save button, call StoreInDatabase
Portanto, agora o controle é invertido ... em vez de o computador aceitar a entrada do usuário em uma ordem fixa, o usuário controla a ordem em que os dados são inseridos e quando os dados são salvos no banco de dados.
Basicamente, qualquer coisa com um loop de eventos, retornos de chamada ou gatilhos de execução se enquadra nessa categoria.
O que é inversão de controle?
Se você seguir estas duas etapas simples, terá feito inversão de controle:
Existem várias técnicas possíveis para cada uma dessas etapas com base na tecnologia / idioma que você está usando para sua implementação.
-
A inversão parte da inversão de controle (COI) é a coisa confundindo; porque inversão é o termo relativo. A melhor maneira de entender a IoC é esquecer essa palavra!
-
Exemplos
what-to-do
ewhen-to-do
Inversão de controles é sobre separar preocupações.
Sem IoC : você possui um laptop e acidentalmente interrompe a tela. E, caramba, você encontra o mesmo modelo de tela do laptop em nenhum lugar do mercado. Então você está preso.
Com IoC : você tem uma área de trabalho computador e acidentalmente interrompe a tela. Você descobre que pode pegar praticamente qualquer monitor de mesa do mercado e funciona bem com sua área de trabalho.
Sua área de trabalho implementa com êxito a IoC neste caso. Ele aceita vários tipos de monitores, enquanto o laptop não, ele precisa de uma tela específica para ser consertada.
Inversão de controle (ou IoC) é sobre obter liberdade (você se casa, você perdeu a liberdade e está sendo controlado. Você se divorciou, acabou de implementar a Inversão de controle. Era isso que chamamos de "desacoplado". Bom sistema de computador desencoraja um relacionamento muito próximo.) mais flexibilidade (a cozinha do seu escritório serve apenas água da torneira, que é a sua única opção quando você deseja beber. Seu chefe implementou a Inversão de Controle instalando uma nova máquina de café. Agora você obtém o flexibilidade de escolher água da torneira ou café.) e menos dependência (seu parceiro tem um emprego, você não tem um emprego, depende financeiramente do seu parceiro, por isso é controlado. Você encontra um emprego, implementou a Inversão de Controle. Bom computador sistema incentiva a dependência.)
Ao usar um computador de mesa, você escrava (ou diz, controla). Você tem que sentar diante de uma tela e olhar para ela. Usando o teclado para digitar e usando o mouse para navegar. E um software mal escrito pode escravizar você ainda mais. Se você substituir sua área de trabalho por um laptop, terá um controle um pouco invertido. Você pode facilmente pegá-lo e se movimentar. Então agora você pode controlar onde está com seu computador, em vez de controlá-lo.
Ao implementar a Inversão de controle, um consumidor de software / objeto obtém mais controles / opções sobre o software / objetos, em vez de ser controlado ou ter menos opções.
Com as idéias acima em mente. Ainda sentimos falta de uma parte essencial da IoC. No cenário de IoC, o consumidor de software / objeto é uma estrutura sofisticada. Isso significa que o código que você criou não é chamado por você. Agora vamos explicar por que dessa maneira funciona melhor para um aplicativo da web.
Suponha que seu código seja um grupo de trabalhadores. Eles precisam construir um carro. Esses trabalhadores precisam de um local e ferramentas (uma estrutura de software) para construir o carro. Uma estrutura de software tradicional será como uma garagem com muitas ferramentas. Portanto, os trabalhadores precisam fazer um plano e usar as ferramentas para construir o carro. Construir um carro não é um negócio fácil, será muito difícil para os trabalhadores planejar e cooperar adequadamente. UMA modernoA estrutura de software será como uma fábrica de carros moderna, com todas as instalações e gerentes instalados. Os trabalhadores não precisam fazer nenhum plano, os gerentes (parte da estrutura, eles são as pessoas mais inteligentes e o plano mais sofisticado) ajudarão a coordenar para que os trabalhadores saibam quando fazer seu trabalho (a estrutura chama seu código). Os funcionários só precisam ser flexíveis o suficiente para usar as ferramentas que os gerentes lhes fornecem (usando a Injeção de Dependência).
Embora os trabalhadores dêem o controle do gerenciamento do projeto no nível superior aos gerentes (a estrutura). Mas é bom ter alguns profissionais ajudando. Este é o conceito de IoC realmente provém.
Os aplicativos modernos da Web com uma arquitetura MVC dependem da estrutura para fazer o roteamento de URL e colocar os controladores no lugar para a estrutura chamar.
Injeção de Dependência e Inversão de Controle estão relacionadas. A injeção de dependência está no nível micro e a inversão de controle está no nível macro . Você deve comer todas as mordidas (implementar DI) para terminar uma refeição (implementar IoC).
Antes de usar a Inversão de controle, você deve estar ciente do fato de que ela possui seus prós e contras e deve saber por que usá-la se o fizer.
Prós:
Contras:
Pessoalmente, vejo os pontos fortes da IoC e realmente gosto deles, mas tendem a evitá-la sempre que possível, porque transforma seu software em uma coleção de classes que não constituem mais um programa "real", mas apenas algo que precisa ser reunido por Os metadados de configuração ou anotação XML e desmoronariam (e desmoronariam) sem ele.
Artigo da Wikipedia . Para mim, a inversão de controle está transformando seu código gravado seqüencialmente e transformando-o em uma estrutura de delegação. Em vez de seu programa controlar explicitamente tudo, ele cria uma classe ou biblioteca com determinadas funções a serem chamadas quando certas coisas acontecem.
Resolve a duplicação de código. Por exemplo, antigamente, você escrevia manualmente seu próprio loop de eventos, pesquisando as bibliotecas do sistema para novos eventos. Hoje em dia, nas APIs mais modernas, você simplesmente diz às bibliotecas do sistema em quais eventos você está interessado, e ele será informado quando eles acontecerem.
A inversão do controle é uma maneira prática de reduzir a duplicação de código e, se você copiar um método inteiro e alterar apenas um pequeno pedaço do código, considere enfrentá-lo com inversão de controle. A inversão do controle é facilitada em muitos idiomas através do conceito de delegados, interfaces ou até mesmo ponteiros de funções brutas.
Não é apropriado usar em todos os casos, porque o fluxo de um programa pode ser mais difícil de seguir quando escrito dessa maneira. É uma maneira útil de projetar métodos ao escrever uma biblioteca que será reutilizada, mas deve ser usada com moderação no núcleo do seu próprio programa, a menos que realmente resolva um problema de duplicação de código.
Mas acho que você precisa ter muito cuidado com isso. Se você usar demais esse padrão, criará um design muito complicado e um código ainda mais complicado.
Como neste exemplo com o TextEditor: se você tiver apenas um SpellChecker, talvez não seja realmente necessário usar a IoC? A menos que você precise escrever testes de unidade ou algo assim ...
De qualquer forma: seja razoável. Padrão de design são boas práticas, mas não a Bíblia a ser pregada. Não cole em todos os lugares.
IoC / DI para mim está enviando dependências para os objetos que estão chamando. Super simples.
A resposta não-techy é ser capaz de trocar um motor em um carro antes de ligá-lo. Se tudo estiver certo (a interface), você estará bem.
Suponha que você seja um objeto. E você vai a um restaurante:
Sem IoC : você pede "maçã" e sempre recebe maçã quando pede mais.
Com IoC : você pode pedir "fruta". Você pode obter frutas diferentes cada vez que for servido. por exemplo, maçã, laranja ou melancia.
Portanto, obviamente, a IoC é preferida quando você gosta das variedades.
Inversão de controle é um padrão usado para desacoplar componentes e camadas no sistema. O padrão é implementado através da injeção de dependências em um componente quando ele é construído. Essas dependências geralmente são fornecidas como interfaces para dissociação adicional e para suportar a testabilidade. Os contêineres IoC / DI, como Castle Windsor, Unity, são ferramentas (bibliotecas) que podem ser usadas para fornecer IoC. Essas ferramentas fornecem recursos estendidos acima e além do simples gerenciamento de dependências, incluindo vida útil, AOP / interceptação, política etc.
uma. Evita que um componente seja responsável por gerenciar suas dependências.
b. Fornece a capacidade de trocar implementações de dependência em diferentes ambientes.
c. Permite que um componente seja testado através da simulação de dependências.
d. Fornece um mecanismo para compartilhar recursos em um aplicativo.
uma. Crítico ao fazer desenvolvimento orientado a teste. Sem a IoC, pode ser difícil testar, porque os componentes em teste são altamente acoplados ao restante do sistema.
b. Crítico ao desenvolver sistemas modulares. Um sistema modular é um sistema cujos componentes podem ser substituídos sem a necessidade de recompilação.
c. Crítico se houver muitas preocupações transversais que precisam ser abordadas, compartilhadas em um aplicativo corporativo.
Respondendo apenas a primeira parte. O que é isso?
Inversão de controle (IoC) significa criar instâncias de dependências primeira e última instância de uma classe (opcionalmente injetando-as por meio do construtor), em vez de criar uma instância da classe primeiro e depois a instância da classe criando instâncias de dependências. Assim, a inversão de controle inverte o fluxo de controle do programa. Em vez de o receptor controlar o fluxo de controle (enquanto cria dependências), o chamador controla o fluxo de controle do programa .
Escreverei minha compreensão simples desses dois termos:
For quick understanding just read examples*
Injeção de Dependência (DI):
injeção de dependência geralmente significa passar um objeto do qual o método depende, como parâmetro para um método, em vez de fazer com que o método crie o objeto dependente .
O que isso significa na prática é que o método não depende diretamente de uma implementação específica; qualquer implementação que atenda aos requisitos pode ser passada como parâmetro.
Com isso, conte suas dependências. E a primavera a disponibiliza.
Isso leva ao desenvolvimento de aplicativos fracamente acoplados.
Quick Example:EMPLOYEE OBJECT WHEN CREATED,
IT WILL AUTOMATICALLY CREATE ADDRESS OBJECT
(if address is defines as dependency by Employee object)
Contêiner de Inversão de Controle (IoC):
Essa é uma característica comum das estruturas, o IOC gerencia objetos java
- da instanciação à destruição através de seu BeanFactory.
-Os componentes Java instanciados pelo contêiner de IoC são chamados de beans, e o contêiner de IoC gerencia o escopo de um bean, eventos de ciclo de vida e quaisquer recursos de AOP para os quais foi configurado e codificado.
QUICK EXAMPLE:Inversion of Control is about getting freedom, more flexibility, and less dependency. When you are using a desktop computer, you are slaved (or say, controlled). You have to sit before a screen and look at it. Using keyboard to type and using mouse to navigate. And a bad written software can slave you even more. If you replaced your desktop with a laptop, then you somewhat inverted control. You can easily take it and move around. So now you can control where you are with your computer, instead of computer controlling it
.
Ao implementar a Inversão de controle, um consumidor de software / objeto obtém mais controles / opções sobre o software / objetos, em vez de ser controlado ou ter menos opções.
A inversão do controle como uma diretriz de design serve aos seguintes propósitos:
Há um desacoplamento da execução de uma determinada tarefa da implementação.
Cada módulo pode se concentrar no que foi projetado.
Os módulos não fazem suposições sobre o que outros sistemas fazem, mas dependem de seus contratos.
Substituir módulos não tem efeito colateral em outros módulos.
Vou manter as coisas abstratas aqui. Você pode visitar os links a seguir para entender detalhes do tópico.
Uma boa leitura com exemplo
Eu concordo com o NilObject , mas gostaria de acrescentar a isso:
se você estiver copiando um método inteiro e alterando apenas um pequeno pedaço do código, considere enfrentá-lo com inversão de controle
Se você está copiando e colando códigos, quase sempre está fazendo algo errado. Codificado como o princípio do design Uma vez e Apenas uma vez .
Por exemplo, a tarefa 1 é criar objeto. Sem o conceito de COI, a tarefa 1 deve ser executada pelo programador, mas com o conceito de COI, a tarefa 1 será feita por contêiner.
Em resumo, o controle é invertido do programador para o contêiner. Então, isso é chamado de inversão de controle.
Encontrei um bom exemplo aqui .
Digamos que nos reunimos em algum hotel.
Muitas pessoas, muitas garrafas de água, muitos copos de plástico.
Quando alguém quer beber, ela enche a xícara, bebe e joga a xícara no chão.
Depois de uma hora ou algo assim, temos um piso coberto de copos de plástico e água.
Deixe o controle invertido.
A mesma reunião no mesmo lugar, mas em vez de copos de plástico, temos um garçom com um copo de vidro (Singleton)
e ela sempre oferece aos convidados que bebem.
Quando alguém quer beber, ela pega o copo de garçom, bebe e devolve ao garçom.
Deixando de lado a questão da última forma higiênica de controle do processo de beber é muito mais eficaz e econômica.
E é exatamente isso que o Spring (outro contêiner de IoC, por exemplo: Guice) faz. Em vez de permitir que o aplicativo crie o que é necessário usando a nova palavra-chave (copo de plástico), o contêiner Spring IoC oferece sempre o aplicativo da mesma instância (singleton) do objeto necessário (copo de água).
Pense em si mesmo como organizador dessa reunião. Você precisa enviar uma mensagem à administração do hotel que
os membros da reunião precisarão de um copo de água, mas não de um pedaço de bolo.
Exemplo:-
public class MeetingMember {
private GlassOfWater glassOfWater;
...
public void setGlassOfWater(GlassOfWater glassOfWater){
this.glassOfWater = glassOfWater;
}
//your glassOfWater object initialized and ready to use...
//spring IoC called setGlassOfWater method itself in order to
//offer to meetingMember glassOfWater instance
}
Links Úteis:-
Parece que a coisa mais confusa em "IoC", o acrônimo e o nome pelo qual ele representa, é que é um nome muito glamouroso - quase um nome barulhento.
Nós realmente precisamos de um nome para descrever a diferença entre programação procedural e orientada a eventos? OK, se precisarmos, mas precisamos escolher um novo nome "maior que a vida" que confunda mais do que resolve?
Inversão de controle é quando você vai ao supermercado e sua esposa fornece a lista de produtos a serem comprados.
Em termos de programação, ela passou uma função de retorno de chamada getProductList()
para a função que você está executando - doShopping()
.
Ele permite que o usuário da função defina algumas partes dela, tornando-a mais flexível.
getProductList()
você precisa encontrar a fonte do dinheiro, significa que o controle está ao seu lado. No caso de inversão, ela controlará, significa também o dinheiro que fornecerá para comprar.
Encontrei um exemplo muito claro aqui que explica como o 'controle é invertido'.
Código clássico (sem injeção de dependência)
Aqui está como um código que não usa DI funcionará aproximadamente:
Usando injeção de dependência
Aqui está como um código usando DI funcionará aproximadamente:
O controle das dependências é invertido de um que está sendo chamado para aquele que está chamando.
Que problemas ele resolve?
A injeção de dependência facilita a troca com a implementação diferente das classes injetadas. Durante o teste de unidade, você pode injetar uma implementação fictícia, o que facilita muito o teste.
Ex: suponha que seu aplicativo armazene o arquivo enviado pelo usuário no Google Drive; com o DI, o código do seu controlador pode ficar assim:
class SomeController
{
private $storage;
function __construct(StorageServiceInterface $storage)
{
$this->storage = $storage;
}
public function myFunction ()
{
return $this->storage->getFile($fileName);
}
}
class GoogleDriveService implements StorageServiceInterface
{
public function authenticate($user) {}
public function putFile($file) {}
public function getFile($file) {}
}
Quando seus requisitos mudam, digamos, em vez do GoogleDrive, você é solicitado a usar o Dropbox. Você só precisa escrever uma implementação de caixa de depósito para o StorageServiceInterface. Você não faz nenhuma alteração no controlador, desde que a implementação do Dropbox siga o StorageServiceInterface.
Durante o teste, você pode criar a simulação para o StorageServiceInterface com a implementação fictícia em que todos os métodos retornam nulos (ou qualquer valor predefinido conforme o requisito de teste).
Em vez disso, se você tivesse a classe controller para construir o objeto de armazenamento com a new
palavra - chave desta forma:
class SomeController
{
private $storage;
function __construct()
{
$this->storage = new GoogleDriveService();
}
public function myFunction ()
{
return $this->storage->getFile($fileName);
}
}
Quando você deseja alterar a implementação do Dropbox, substitua todas as linhas em que new
objeto GoogleDriveService é construído e use o DropboxService. Além disso, ao testar a classe SomeController, o construtor sempre espera a classe GoogleDriveService e os métodos reais dessa classe são acionados.
Quando é apropriado e quando não? Na minha opinião, você usa DI quando pensa que há (ou pode haver) implementações alternativas de uma classe.
Uma explicação escrita muito simples pode ser encontrada aqui
http://binstock.blogspot.in/2008/01/excellent-explanation-of-dependency.html
Diz -
"Qualquer aplicativo não trivial é composto de duas ou mais classes que colaboram entre si para executar alguma lógica de negócios. Tradicionalmente, cada objeto é responsável por obter suas próprias referências aos objetos com os quais colabora (suas dependências). Ao aplicar o DI, o objetos recebem suas dependências no momento da criação por alguma entidade externa que coordena cada objeto no sistema. Em outras palavras, as dependências são injetadas nos objetos ".
Inversão de controle é um princípio genérico, enquanto a injeção de dependência realiza esse princípio como um padrão de design para a construção de gráficos de objetos (ou seja, a configuração controla como os objetos se referenciam uns aos outros, em vez de o próprio objeto controlar como obter a referência para outro objeto).
Olhando Inversão de Controle como um padrão de design, precisamos olhar para o que estamos invertendo. A injeção de dependência inverte o controle da construção de um gráfico de objetos. Se contada no termo leigo, a inversão de controle implica mudança no fluxo de controle no programa. Por exemplo. No aplicativo independente tradicional, temos o método principal, de onde o controle é passado para outras bibliotecas de terceiros (no caso, usamos a função de biblioteca de terceiros), mas, através da inversão do controle, o controle é transferido do código da biblioteca de terceiros para o nosso código , como estamos recebendo o serviço de uma biblioteca de terceiros. Mas há outros aspectos que precisam ser invertidos dentro de um programa - por exemplo, invocação de métodos e threads para executar o código.
Para os interessados em mais detalhes sobre a Inversão de controle, foi publicado um artigo descrevendo uma imagem mais completa da Inversão de controle como padrão de design (OfficeFloor: usando padrões de escritório para melhorar o design de software http://doi.acm.org/10.1145/ 2739011.2739013 com uma cópia gratuita disponível para download em http://www.officefloor.net/about.html ).
O que é identificado é o seguinte relacionamento:
Inversão de controle (para métodos) = Injeção de dependência (estado) + Injeção de continuação + Injeção de rosca
Resumo do relacionamento acima para Inversão de controle disponível - http://dzone.com/articles/inversion-of-coupling-control
IoC trata-se de inverter o relacionamento entre seu código e o código de terceiros (biblioteca / estrutura):
DI (Injection Dependency) é sobre como o controle flui no aplicativo. O aplicativo de área de trabalho tradicional tinha fluxo de controle do seu aplicativo (método main ()) para outras chamadas de método de biblioteca, mas com o fluxo de controle de DI invertido, a estrutura cuida de iniciar seu aplicativo, inicializando-o e invocando seus métodos sempre que necessário.
No final, você sempre vence :)
Eu gosto desta explicação: http://joelabrahamsson.com/inversion-of-control-an-introduction-with-examples-in-net/
Começa simples e mostra exemplos de código também.
O consumidor, X, precisa da classe consumida, Y, para realizar alguma coisa. Tudo isso é bom e natural, mas X realmente precisa saber que usa Y?
Não basta que X saiba que usa algo que possui o comportamento, os métodos, as propriedades etc. de Y sem saber quem realmente implementa o comportamento?
Ao extrair uma definição abstrata do comportamento usado por X em Y, ilustrado como abaixo, e permitir que o consumidor X use uma instância disso em vez de Y, ele pode continuar fazendo o que faz sem precisar conhecer as especificidades sobre Y.
Na ilustração acima, Y implementa I e X usa uma instância de I. Embora seja bem possível que X ainda use Y, o interessante é que X não sabe disso. Só sabe que usa algo que implementa I.
Leia o artigo para obter mais informações e descrição de benefícios, como:
...
Entendo que a resposta já foi dada aqui. Mas ainda penso que algumas noções básicas sobre a inversão de controle precisam ser discutidas aqui em detalhes para futuros leitores.
A Inversão de Controle (IoC) foi construída com base em um princípio muito simples chamado Princípio de Hollywood . E diz isso,
Não ligue para nós, nós ligaremos para você
O que isso significa é que não vá a Hollywood para realizar seu sonho; se você é digno, Hollywood o encontrará e fará com que seu sonho se torne realidade. Quase invertido, não é?
Agora, quando discutimos sobre o princípio da IoC, costumamos esquecer o Hollywood. Para a IoC, tem que haver três elementos: um Hollywood, você e uma tarefa como realizar o seu sonho.
No nosso mundo da programação, Hollywood representa uma estrutura genérica (pode ser escrita por você ou outra pessoa), você representa o código do usuário que você escreveu e a tarefa representa o que você deseja realizar com o seu código. Agora você nunca inicia sua tarefa sozinho, não na IoC! Em vez disso, você projetou tudo para que sua estrutura inicie sua tarefa. Assim, você construiu uma estrutura reutilizável que pode transformar alguém em herói ou outro em vilão. Mas essa estrutura está sempre no comando, sabe quando escolher alguém e que alguém sabe apenas o que quer ser.
Um exemplo da vida real seria dado aqui. Suponha que você deseje desenvolver um aplicativo da web. Portanto, você cria uma estrutura que lida com todas as coisas comuns que um aplicativo Web deve lidar, como lidar com solicitações http, criar menu de aplicativos, exibir páginas, gerenciar cookies, acionar eventos etc.
E então você deixa alguns ganchos em sua estrutura, onde pode colocar mais códigos para gerar menus personalizados, páginas, cookies ou registrar alguns eventos do usuário etc. para o navegador.
Então, a ideia é bastante simples. Em vez de criar um aplicativo de usuário que controla tudo, primeiro você cria uma estrutura reutilizável que controla tudo e depois escreve seus códigos personalizados e conecta-os à estrutura para executá-los a tempo.
Laravel e EJB são exemplos de tais estruturas.
Referência:
Falando de programação
IoC em termos fáceis: é o uso da Interface como uma maneira específica de algo (como um campo ou parâmetro) como um curinga que pode ser usado por algumas classes. Permite a reutilização do código.
Por exemplo, digamos que temos duas classes: Cão e Gato . Ambos compartilham as mesmas qualidades / estados: idade, tamanho, peso. Portanto, em vez de criar uma classe de serviço chamada DogService e CatService , posso criar uma única chamada AnimalService que permita o uso de Dog and Cat somente se eles usarem a interface IAnimal .
No entanto, pragmaticamente falando, tem alguns retrocessos.
a) A maioria dos desenvolvedores não sabe como usá-lo . Por exemplo, eu posso criar uma classe chamada Customer e posso criar automaticamente (usando as ferramentas do IDE) uma interface chamada ICustomer . Portanto, não é raro encontrar uma pasta cheia de classes e interfaces, independentemente de as interfaces serem reutilizadas ou não. É chamado FLUTUADO. Algumas pessoas podem argumentar que "pode ser que no futuro possamos usá-lo". : - |
b) Tem alguns limites. Por exemplo, vamos falar sobre o caso de Dog and Cat e eu quero adicionar um novo serviço (funcionalidade) apenas para cães. Digamos que eu quero calcular o número de dias que preciso para treinar um cachorro ( trainDays()
), pois gato é inútil, gatos não podem ser treinados (estou brincando).
b.1) Se eu adicionar trainDays()
ao Service AnimalService , ele também funciona com gatos e não é válido.
b.2) Posso adicionar uma condição em trainDays()
que avalia qual classe é usada. Mas isso quebrará completamente a IoC.
b.3) Posso criar uma nova classe de serviço chamada DogService apenas para a nova funcionalidade. Porém, aumentará a capacidade de manutenção do código, pois teremos duas classes de serviço (com funcionalidade semelhante) para o Dog e isso é ruim.
Eu já li muitas respostas para isso, mas se alguém ainda está confuso e precisa de um termo "ultra-leigo" para explicar a IoC, aqui está minha opinião:
Imagine pais e filhos conversando entre si.
Sem IoC:
* Pai : Você só pode falar quando eu fizer perguntas e você só pode agir quando eu der permissão.
Pai : Isso significa que você não pode me perguntar se pode comer, brincar, ir ao banheiro ou até dormir se eu não perguntar.
Pai : Você quer comer?
Criança : Não.
Pai : Ok, eu volto. Espere por mim.
Criança : (Quer brincar, mas como não há perguntas dos pais, a criança não pode fazer nada).
Após 1 hora...
Pai : estou de volta. Você quer jogar?
Criança : Sim.
Pai : Permissão concedida.
Criança : (finalmente é capaz de brincar).
Este cenário simples explica que o controle está centralizado no pai. A liberdade da criança é restrita e depende muito da pergunta dos pais. A criança SOMENTE pode falar quando for solicitada a falar e SOMENTE pode agir quando tiver permissão.
Com IoC:
A criança agora tem a capacidade de fazer perguntas e os pais podem responder com respostas e permissões. Simplesmente significa que o controle está invertido! A criança agora está livre para fazer perguntas a qualquer momento e, embora ainda exista dependência dos pais em relação às permissões, ela não depende dos meios de falar / fazer perguntas.
De uma maneira tecnológica de explicar, isso é muito semelhante à interação console / shell / cmd x GUI. (Qual é a resposta de Mark Harrison acima da resposta superior no.2). No console, você depende do que está sendo solicitado / exibido e não pode pular para outros menus e recursos sem responder à pergunta primeiro; seguindo um fluxo seqüencial estrito. (programaticamente, isso é como um loop de método / função). No entanto, com a GUI, os menus e os recursos são definidos e o usuário pode selecionar o que for necessário, tendo mais controle e menos restrições. (programaticamente, os menus têm retorno de chamada quando selecionados e uma ação ocorre).
Inversão de controle é sobre a transferência de controle da biblioteca para o cliente. Faz mais sentido quando falamos de um cliente que injeta (passa) um valor de função (expressão lambda) em uma função de ordem superior (função de biblioteca) que controla (altera) o comportamento da função de biblioteca. Um cliente ou estrutura que injeta dependências de bibliotecas (que carregam comportamento) nas bibliotecas também pode ser considerado IoC
Como já existem muitas respostas para a pergunta, mas nenhuma delas mostra o detalhamento do termo Controle de Inversão, vejo uma oportunidade de fornecer uma resposta mais concisa e útil.
Inversão de controle é um padrão que implementa o princípio de inversão de dependência (DIP). O DIP declara o seguinte: 1. Os módulos de alto nível não devem depender dos módulos de baixo nível. Ambos devem depender de abstrações (por exemplo, interfaces). 2. As abstrações não devem depender de detalhes. Detalhes (implementações concretas) devem depender de abstrações.
Existem três tipos de inversão de controle:
Provedores de inversão de interface não devem definir uma interface. Em vez disso, o consumidor deve definir a interface e os fornecedores devem implementá-la. A Inversão da interface permite eliminar a necessidade de modificar o consumidor sempre que um novo provedor é adicionado.
Inversão do fluxo Altera o controle do fluxo. Por exemplo, você tem um aplicativo de console no qual solicitou a inserção de vários parâmetros e, após cada parâmetro inserido, é forçado a pressionar Enter. Você pode aplicar o Flow Inversion aqui e implementar um aplicativo de desktop em que o usuário possa escolher a sequência de entrada dos parâmetros, editar os parâmetros e, na etapa final, o usuário precisará pressionar Enter apenas uma vez.
Inversão de criação Pode ser implementado pelos seguintes padrões: Padrão de fábrica, Localizador de serviço e Injeção de dependência. Inversão de criação ajuda a eliminar dependências entre tipos, movendo o processo de criação de objetos de dependência para fora do tipo que usa esses objetos de dependência. Por que dependências são ruins? Aqui estão alguns exemplos: a criação direta de um novo objeto no seu código torna o teste mais difícil; é impossível alterar referências em assembléias sem recompilação (violação do princípio da OCP); você não pode substituir facilmente uma interface do usuário da área de trabalho por uma interface da web.
Então, número 1 acima . O que é inversão de controle?
Manutenção é a primeira coisa que resolve para mim. Garante que estou usando interfaces para que duas classes não sejam íntimas uma da outra.
Ao usar um contêiner como o Castle Windsor, ele resolve os problemas de manutenção ainda melhor. Ser capaz de trocar um componente que vai para um banco de dados por outro que usa persistência baseada em arquivo sem alterar uma linha de código é impressionante (alteração de configuração, pronto).
E quando você entra em genéricos, fica ainda melhor. Imagine ter um editor de mensagens que recebe registros e publica mensagens. Ele não se importa com o que publica, mas precisa de um mapeador para levar algo de um registro para uma mensagem.
public class MessagePublisher<RECORD,MESSAGE>
{
public MessagePublisher(IMapper<RECORD,MESSAGE> mapper,IRemoteEndpoint endPointToSendTo)
{
//setup
}
}
Escrevi uma vez, mas agora posso injetar muitos tipos nesse conjunto de códigos se publicar diferentes tipos de mensagens. Também posso escrever mapeadores que registram o mesmo tipo e os mapeiam para mensagens diferentes. O uso do DI com genéricos me deu a capacidade de escrever muito pouco código para realizar muitas tarefas.
Ah, sim, existem preocupações com a testabilidade, mas são secundárias aos benefícios da IoC / DI.
Definitivamente, estou amando IoC / DI.
3) Torna-se mais apropriado no minuto em que você tem um projeto de tamanho médio com um pouco mais de complexidade. Eu diria que isso se torna apropriado no minuto em que você começa a sentir dor.
Criar um objeto dentro da classe é chamado de acoplamento rígido, o Spring remove essa dependência seguindo um padrão de design (DI / IOC). Em qual objeto da classe passou no construtor em vez de criar na classe. Além disso, damos uma variável de referência de superclasse no construtor para definir uma estrutura mais geral.