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

63

Estou projetando um novo sistema e quero saber qual é a inversão de controle (IOC) e, mais importante, quando usá-lo.

Ele precisa ser implementado com interfaces ou pode ser feito com classes?

    
por Jedi Master Spooky 05.09.2008 / 05:32
fonte

4 respostas

61

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

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

void Iterator(void *list, Func* f)

Qual itera sobre list aplicando a função f a cada um de seus itens. A função Iterator não sabe como cada item será processado, você apenas fornece uma função como um argumento e os processa.

Como mostra o exemplo anterior, o IoC permite separar o seu programa em componentes separados que não se conhecem. Uma das versões mais comuns do IoC é Injeção de Dependentes .

Em 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 de Container IoC executa a vinculação entre esses componentes. Ele tenta fornecer valores para dependências de componente publicadas.

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

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

Neste exemplo, a classe Foo tem um construtor que requer o argumento do tipo Boo para executar alguma ação.

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

MyContainer.Create(typeof Foo)

MyContainer - é um Contêiner IoC , que cuida da obtenção da instância de Boo e passa para o construtor Foo .

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

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

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

Se você quiser ver um bom exemplo do uso real do IoC , dê uma olhada no Mircosoft Bloco de aplicativos da interface do usuário em bloco e CompositeWPF

Espero que minha explicação ajude você.

Cumprimentos,
aku

    
por 05.09.2008 / 05:44
fonte
18

Desde que eu me concentrei nisso recentemente e mantive todos os marcadores, os itens a seguir achei inestimável para aprender sobre o IOC / DI.

Artigo original de Martin Fowlers sobre IOC / DI

Alguns conceitos a conhecer primeiro

Uma excelente coleção de Tutoriais de IOC / DI

Livro sobre o COI / DI da Manning Press

Fonte e Explicação de como criar seu próprio IOC - Porque a leitura do código fonte é sempre a melhor maneira de entender um conceito.

    
por 05.09.2008 / 06:08
fonte
4

Oi JMS, basicamente IoC / DI, permite definir qual implementação você está usando uma vez e manter uma cópia estática do seu contêiner para fazer referência toda vez que você quiser referenciá-lo.

A Wikipedia provavelmente irá ajudá-lo, mas eu quis referenciar sua segunda parte - sim, injeção de dependência pode ser feita para classes (ou seja, toda vez que esse tipo de classe precisa ser passada para um método, use essa classe), mas é melhor usar interfaces, porque dessa forma 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 tenha uma implementação XMLStreamReader e SQLStreamReader. Então você pode passar a referência para a interface para os seus métodos e, em seguida, no seu contêiner IoC, informe qual deles usar.

Assim, você pode ter List ReadPeople pública (leitor IStreamReader) e, em sua configuração do contêiner IoC, dizer isso sempre que você espera que um IStreamReader use SQLStreamReader.

Então, se você mudar de idéia mais tarde, você só precisará alterá-lo em um único lugar (a configuração do seu contêiner) e não importará quantos métodos solicitarem um IStreamReader, ele sempre obterá o padrão informado. seu contêiner para servir.

    
por 05.09.2008 / 06:00
fonte
3

Digamos que você tenha um validador para verificar se uma empresa é 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 código externo (ou seja, o código addressValidator), então se você usou algum tipo de IoC / DI em sua estrutura, você pode facilmente "injetar" um endereço addressValidator em seu lugar e não ter que se preocupar com testes código fora do escopo da classe em teste.

    
por 05.09.2008 / 06:48
fonte