O que é inversão de controle e quando devo usá-lo?

Respostas:

62

O IoC (consulte Inversão de controle na Wikipedia) é aplicável nos casos em que um componente não pode executar uma tarefa completamente porque não possui algumas informações ou funcionalidades necessárias.

O exemplo mais simples de um padrão de IoC seria funções de retorno de chamada em C. Por exemplo, você pode declarar a função:

void Iterator(void *list, Func* f)

Que itera sobre a listaplicação da ffunção em cada item. A Iteratorfunção não sabe como cada item será processado, você apenas fornece uma função como argumento e os processa.

Como mostra o exemplo anterior, a IoC permite desacoplar seu programa em componentes separados que não se conhecem. Uma das versões mais comuns do IoC é a Dependecy Injection .

Na Injeção de Dependência, cada componente deve declarar uma lista de dependências necessárias para executar sua tarefa. Em tempo de execução, um componente especial (geralmente) chamado IoC Container executa a ligação entre esses componentes. Ele tenta fornecer valores para dependências de componentes publicadas.

Aqui está um exemplo no pseudo-código:

class Foo 
{ 
   <Require Boo>Constructor(Boo boo){ boo.DoSomething } 
}

Neste exemplo, a classe Foopossui um construtor que requer argumento do tipo Boopara executar alguma ação.

Você pode criar uma instância da classe Foousando código semelhante a este:

MyContainer.Create(typeof Foo)

MyContainer- é um contêiner de IoC , que cuida de obter a instância Booe transmiti-la ao Fooconstrutor.

Em resumo, a IoC permite desacoplar seu programa em partes separadas. Isso é bom porque:

  • Os componentes podem ser facilmente testados independentemente.
  • A complexidade do programa pode ser reduzida.
  • Você pode alternar componentes para outra implementação.

No entanto, em alguns casos, a IoC pode dificultar a compreensão do código.

Se você quiser ver um bom exemplo do uso de IoC no mundo real , consulte o Mircosoft Composite UI Application Block e o CompositeWPF

Espero que minha explicação o ajude.

Atenciosamente,
aku


fonte
11
Cinco anos depois, mas ainda assim ... Essa foi uma excelente descrição. Obrigado.
Nick Hodges
4
Não é tão mencionado em nenhum lugar sobre IoC o fato de que o código se torna mais difícil de ler. A legibilidade é a prioridade número um, se você deseja escrever um ótimo software. Até supera a testabilidade. Você pode separar o código muito além de sua utilidade.
Arne Evertsson
Então, um código que usa solução baseada em interface para todas as suas dependências também é baseado no design de IoC?
Nikel
18

Desde que me dediquei a isso recentemente e guardei todos os indicadores, achei a seguir inestimável para aprender sobre o COI / DI.

Artigo original do Martin Fowlers sobre IOC / DI

Alguns conceitos a conhecer primeiro

Uma excelente coleção de tutoriais do COI / DI

Livro sobre COI / DI da Manning Press

Origem e explicação de como criar seu próprio COI - porque a leitura do código fonte é sempre a melhor maneira de entender um conceito.

Kris Erickson
fonte
4

Ei, JMS, basicamente o IoC / DI permitirá que você defina qual implementação você está usando uma vez e mantenha uma cópia estática do seu contêiner para fazer referência sempre que desejar fazer referência a ele.

A Wikipedia provavelmente o ajudará, mas eu queria referenciar sua segunda parte - sim, a injeção de dependência pode ser feita para classes (ou seja, toda vez que esse tipo de classe precisar ser passado para um método, use essa classe), mas é melhor use interfaces, porque dessa maneira você pode alterar qual versão de um provedor, repositório, etc., você está usando apenas referenciando-o novamente em sua configuração.

IE, digamos que você tenha uma interface para ler um fluxo e que tenha uma implementação XMLStreamReader e SQLStreamReader. Em seguida, você pode passar a referência à interface para seus métodos e, em seu contêiner de IoC, dizer qual usar.

Portanto, você pode ter o List ReadPeople público (leitor IStreamReader) e, na sua configuração do seu contêiner de IoC, sempre que você espera que um IStreamReader use SQLStreamReader.

Então, se você mudar de idéia posteriormente, precisará alterá-lo apenas em um único local (a configuração do seu contêiner) e não importa quantos métodos solicitem um IStreamReader, ele sempre obterá o padrão que você solicitou ao seu contêiner. servir.


fonte
3

Digamos que você tenha um validador para verificar se uma empresa é ou não válida em seu sistema. Seu "BusinessValidator" pode ter um campo do tipo AddressValidator que valida a parte do endereço da empresa. Se você quiser testar o BusinessValidator sem executar o código externo (ou seja, o código addressValidator), se tiver usado algum tipo de IoC / DI em sua estrutura, poderá "injetar" facilmente um addressValidator falso no local e não precisar se preocupar em testar código fora do escopo da classe em teste.

codeLes
fonte