Eu tenho usado injeção de dependência (DI) por um tempo, injetando em um construtor, propriedade ou método. Eu nunca senti a necessidade de usar um contêiner de Inversão de Controle (IoC). No entanto, quanto mais leio, mais pressão sinto da comunidade para usar um contêiner de IoC.
Eu brinquei com contêineres .NET como StructureMap , NInject , Unity e Funq . Ainda não consigo ver como um contêiner de IoC irá beneficiar / melhorar meu código.
Também tenho medo de começar a usar um contêiner no trabalho, porque muitos dos meus colegas de trabalho verão código que eles não entendem. Muitos deles podem estar relutantes em aprender novas tecnologias.
Por favor, me convença de que preciso usar um contêiner de IoC. Vou usar esses argumentos quando conversar com meus colegas desenvolvedores no trabalho.
Respostas:
Uau, não acredito que Joel seria a favor disso:
por cima disto:
Muitas pessoas não percebem que sua cadeia de dependências pode ficar aninhada e rapidamente se torna difícil ligá-las manualmente. Mesmo com fábricas, a duplicação do seu código simplesmente não vale a pena.
Os contêineres de IoC podem ser complexos, sim. Mas neste caso simples, mostrei que é incrivelmente fácil.
Ok, vamos justificar isso ainda mais. Digamos que você tenha algumas entidades ou objetos de modelo que deseja vincular a uma interface inteligente. Essa interface inteligente (que chamaremos de Shindows Morms) deseja que você implemente INotifyPropertyChanged para que ele possa fazer o rastreamento de alterações e atualizar a interface de acordo.
"OK, isso não parece tão difícil", então você começa a escrever.
Você começa com isso:
..e acabar com isso :
Esse é um código de canalização nojento, e eu mantenho que, se você está escrevendo um código como esse manualmente, está roubando seu cliente . Há uma maneira melhor e mais inteligente de trabalhar.
Já ouviu esse termo, trabalha de maneira mais inteligente, não mais?
Bem, imagine que um cara inteligente da sua equipe apareceu e disse: "Aqui está uma maneira mais fácil"
Se você tornar suas propriedades virtuais (acalme-se, não é nada demais), poderemos incorporar esse comportamento automaticamente. (Isso se chama AOP, mas não se preocupe com o nome, concentre-se no que ele fará por você)
Dependendo da ferramenta de IoC que você estiver usando, você pode fazer algo parecido com isto:
Poof! Todo esse manual INotifyPropertyChanged BS agora é gerado automaticamente para você, em todos os configuradores de propriedades virtuais do objeto em questão.
Isso é mágico? SIM ! Se você pode confiar no fato de que esse código faz seu trabalho, pode ignorar com segurança toda essa propriedade que envolve o mumbo-jumbo. Você tem problemas de negócios para resolver.
Alguns outros usos interessantes de uma ferramenta de IoC para fazer AOP:
fonte
Estou com você, Vadim. Os contêineres de IoC adotam um conceito simples, elegante e útil e transformam-o em algo que você deve estudar por dois dias com um manual de 200 páginas.
Pessoalmente, estou perplexo com a maneira como a comunidade de IoC pegou um artigo bonito e elegante de Martin Fowler e o transformou em várias estruturas complexas, tipicamente com manuais de 200 a 300 páginas.
Tento não julgar (HAHA!), Mas acho que as pessoas que usam contêineres de IoC são (A) muito inteligentes e (B) carecem de empatia por pessoas que não são tão inteligentes quanto são. Tudo faz sentido para eles, portanto eles têm problemas para entender que muitos programadores comuns acharão os conceitos confusos. É a maldição do conhecimento . As pessoas que entendem os contêineres de IoC têm dificuldade em acreditar que existem pessoas que não entendem isso.
O benefício mais valioso do uso de um contêiner de IoC é que você pode ter um comutador de configuração em um único local que permite alternar entre, digamos, modo de teste e modo de produção. Por exemplo, suponha que você tenha duas versões de suas classes de acesso ao banco de dados ... uma versão que registrou agressivamente e executou muita validação, que você usou durante o desenvolvimento, e outra versão sem log ou validação que foi extremamente rápida para produção. É bom poder alternar entre eles em um só lugar. Por outro lado, esse é um problema bastante trivial, fácil de lidar de maneira mais simples, sem a complexidade dos contêineres de IoC.
Acredito que se você usar contêineres IoC, seu código se tornará, francamente, muito mais difícil de ler. O número de lugares que você deve procurar para descobrir o que o código está tentando fazer aumenta em pelo menos um. E em algum lugar no céu um anjo clama.
fonte
Presumivelmente, ninguém está forçando você a usar uma estrutura de contêiner de DI. Você já está usando o DI para desacoplar suas classes e melhorar a testabilidade, por isso está obtendo muitos dos benefícios. Em resumo, você está favorecendo a simplicidade, o que geralmente é uma coisa boa.
Se o seu sistema atingir um nível de complexidade em que a DI manual se torna uma tarefa (ou seja, aumenta a manutenção), avalie-a na curva de aprendizado da equipe de uma estrutura de contêiner de DI.
Se você precisar de mais controle sobre o gerenciamento do tempo de vida da dependência (ou seja, se sentir a necessidade de implementar o padrão Singleton), consulte os contêineres DI.
Se você usar um contêiner de DI, use apenas os recursos necessários. Pule o arquivo de configuração XML e configure-o no código, se isso for suficiente. Atenha-se à injeção do construtor. Os princípios básicos do Unity ou do StructureMap podem ser resumidos em algumas páginas.
Há um ótimo post de Mark Seemann sobre o assunto: Quando usar um DI Container
fonte
Na minha opinião, o principal benefício de uma IoC é a capacidade de centralizar a configuração de suas dependências.
Se você estiver usando a injeção de dependência no momento, seu código pode ser assim
Se você usou uma classe IoC estática, ao contrário dos arquivos de configuração IMHO, mais confusos, pode ter algo como isto:
Então, sua classe Static IoC ficaria assim: estou usando o Unity aqui.
fonte
Os contêineres IoC também são bons para carregar dependências de classe profundamente aninhadas. Por exemplo, se você tivesse o seguinte código usando a Injeção de Depedência.
Se todas essas dependências fossem carregadas no contêiner de IoC, você poderia resolver o CustomerService e todas as dependências filhas serão resolvidas automaticamente.
Por exemplo:
fonte
Sou fã de programação declarativa (veja quantas perguntas SQL respondo), mas os contêineres de IoC que olhei parecem muito misteriosos para seu próprio bem.
... ou talvez os desenvolvedores de contêineres IoC sejam incapazes de escrever documentação clara.
... ou então ambos são verdadeiros em um grau ou outro.
Não acho que o conceito de um contêiner de IoC seja ruim. Mas a implementação deve ser poderosa (ou seja, flexível) o suficiente para ser útil em uma ampla variedade de aplicativos, mas simples e fácil de entender.
Provavelmente são seis de uma e meia dúzia da outra. Um aplicativo real (não um brinquedo ou demonstração) é obrigado a ser complexo, respondendo por muitos casos extremos e exceções às regras. Você encapsula essa complexidade no código imperativo ou no código declarativo. Mas você tem que representá-lo em algum lugar.
fonte
O uso de um contêiner é principalmente sobre a mudança de um estilo imperativo / com script de inicialização e configuração para um declarativo . Isso pode ter alguns efeitos benéficos diferentes:
Obviamente, pode haver dificuldades:
fonte
Parece-me que você já construiu seu próprio contêiner de IoC (usando os vários padrões descritos por Martin Fowler) e está perguntando por que a implementação de outra pessoa é melhor que a sua.
Então, você tem um monte de código que já funciona. E está se perguntando por que você deseja substituí-lo pela implementação de outra pessoa.
Prós por considerar um contêiner de IoC de terceiros
Contras
Portanto, avalie seus profissionais contra seus contras e tome uma decisão.
fonte
Eu acho que a maior parte do valor de uma IoC é obtida usando DI. Como você já está fazendo isso, o restante do benefício é incremental.
O valor que você obtém dependerá do tipo de aplicativo em que você está trabalhando:
Para multilocação, o contêiner de IoC pode cuidar de parte do código de infraestrutura para carregar diferentes recursos do cliente. Quando você precisar de um componente específico do cliente, use um seletor personalizado para lidar com a lógica e não se preocupe com isso no código do cliente. Certamente você pode criar isso sozinho, mas aqui está um exemplo de como uma IoC pode ajudar.
Com muitos pontos de extensibilidade, o IoC pode ser usado para carregar componentes da configuração. Isso é algo comum de construir, mas as ferramentas são fornecidas pelo contêiner.
Se você deseja usar o AOP para algumas questões transversais, o IoC fornece ganchos para interceptar invocações de métodos. Isso é menos comum em projetos ad-hoc, mas a IoC facilita.
Eu escrevi uma funcionalidade como essa antes, mas se precisar de algum desses recursos agora, prefiro usar uma ferramenta pré-criada e testada, se ela se encaixar na minha arquitetura.
Conforme mencionado por outras pessoas, você também pode configurar centralmente quais classes deseja usar. Embora isso possa ser uma coisa boa, tem um custo de desorientação e complicação. Os principais componentes da maioria dos aplicativos não são substituídos muito, portanto, a troca é um pouco mais difícil de fazer.
Eu uso um contêiner de IoC e aprecio a funcionalidade, mas tenho que admitir que notei o trade-off: Meu código se torna mais claro no nível da classe e menos claro no nível do aplicativo (ou seja, visualizando o fluxo de controle).
fonte
Sou um viciado em recuperação do COI. Estou achando difícil justificar o uso do COI para DI na maioria dos casos atualmente. Os contêineres do IOC sacrificam a verificação do tempo de compilação e, em troca, oferecem uma configuração "fácil", gerenciamento complexo da vida útil e descoberta dinâmica de dependências em tempo de execução. Acho que a perda da verificação do tempo de compilação e as exceções / mágicas resultantes do tempo de execução não valem nada na maioria dos casos. Em aplicativos corporativos de grande porte, eles podem dificultar o acompanhamento do que está acontecendo.
Eu não compro o argumento de centralização porque você pode centralizar a configuração estática com muita facilidade, usando uma fábrica abstrata para seu aplicativo e adiando religiosamente a criação de objetos para a fábrica abstrata, ou seja, faça o DI adequado.
Por que não fazer o DI estático sem magia como este:
Sua configuração de contêiner é sua implementação abstrata de fábrica, seus registros são implementações de membros abstratos. Se você precisar de uma nova dependência de singleton, basta adicionar outra propriedade abstrata à fábrica abstrata. Se você precisar de uma dependência transitória, basta adicionar outro método e injetar como um Func <>.
Vantagens:
Eu recomendo os céticos para dar um próximo projeto de campo verde e honestamente se perguntar em que momento você precisa do contêiner. É fácil levar em consideração um contêiner IOC mais tarde, pois você está substituindo uma implementação de fábrica por um módulo de configuração IOC Container.
fonte
O maior benefício do uso de contêineres IoC para mim (pessoalmente, eu uso o Ninject) foi eliminar o repasse de configurações e outros tipos de objetos de estado global.
Eu não programo para a web, o meu é um aplicativo de console e, em muitos lugares da árvore de objetos, preciso ter acesso às configurações ou metadados especificados pelo usuário, criados em uma ramificação completamente separada da árvore de objetos. Com o IoC, eu simplesmente digo ao Ninject para tratar as configurações como um singleton (porque sempre há apenas uma instância delas), solicito as configurações ou o dicionário no construtor e pronto ... elas aparecem magicamente quando eu precisar delas!
Sem usar um contêiner de IoC, eu teria que passar as configurações e / ou metadados para 2, 3, ..., n objetos antes de ser realmente usado pelo objeto que precisava dele.
Existem muitos outros benefícios para os contêineres de DI / IoC, já que outras pessoas detalharam aqui, e passar da ideia de criar objetos para solicitar objetos pode ser alucinante, mas usar o DI foi muito útil para mim e minha equipe, então talvez você possa adicioná-lo para o seu arsenal!
fonte
As estruturas de IoC são excelentes se você quiser ...
... jogue fora a segurança do tipo. Muitas estruturas de IoC (todas?) Obrigam você a executar o código se quiser ter certeza de que tudo está conectado corretamente. "Ei! Espero que eu tenha configurado tudo para que minhas inicializações dessas 100 classes não falhem na produção, lançando exceções de ponteiro nulo!"
... ninhada seu código com globals (quadros IoC são todos sobre a mudança de estados globais).
... escreva códigos ruins com dependências pouco claras que são difíceis de refatorar, pois você nunca saberá o que depende de quê.
O problema com a IoC é que as pessoas que as usam costumam escrever código como este
o que é obviamente falho, uma vez que a dependência entre Foo e Bar é muito forte. Então eles perceberam que seria melhor escrever código como
que também é falho, mas menos obviamente. Em Haskell, o tipo de
Foo()
seria,IO Foo
mas você realmente não quer aIO
parte e deve ser um sinal de aviso de que algo está errado com o seu design, se você o conseguiu.Para se livrar dele (a parte IO), obtenha todas as vantagens das estruturas de IoC e nenhuma de suas desvantagens, você poderia usar uma fábrica abstrata.
A solução correta seria algo como
ou talvez
e injetar (mas eu não chamaria de injetar).
Também: veja este vídeo com Erik Meijer (inventor do LINQ), onde ele diz que o DI é para pessoas que não sabem matemática (e eu não poderia concordar mais): http://www.youtube.com/watch?v = 8Mttjyf-8P4
Ao contrário do Sr. Spolsky, não acredito que as pessoas que usam estruturas de IoC sejam muito inteligentes - simplesmente acredito que não sabem matemática.
fonte
IBar
, é de fatoIO IBar
) .. E sim, no exemplo de Haskell Não consigo obter uma referência nula.Descobri que implementar corretamente a Injeção de Dependências tende a forçar os programadores a usar uma variedade de outras práticas de programação que ajudam a melhorar a testabilidade, flexibilidade, manutenibilidade e escalabilidade do código: práticas como o Princípio de Responsabilidade Única, Separações de Preocupações e codificação contra APIs. Parece que estou sendo obrigado a escrever classes e métodos mais modulares, do tamanho de uma mordida, o que facilita a leitura do código, porque pode ser usado em pedaços de mordida.
Mas também tende a criar árvores de dependência bastante grandes, que são gerenciadas com muito mais facilidade por meio de uma estrutura (especialmente se você usar convenções) do que manualmente. Hoje eu queria testar algo muito rapidamente no LINQPad, e achei que seria muito complicado criar um kernel e carregar meus módulos, e acabei escrevendo isso manualmente:
Em retrospecto, seria mais rápido usar a estrutura de IoC, uma vez que os módulos definem praticamente todas essas coisas por convenção.
Depois de passar algum tempo estudando as respostas e os comentários sobre essa pergunta, estou convencido de que as pessoas que se opõem ao uso de um contêiner de IoC não estão praticando a injeção de dependência verdadeira. Os exemplos que eu vi são de práticas que geralmente são confundidas com injeção de dependência. Algumas pessoas estão reclamando de dificuldade em "ler" o código. Se feito corretamente, a grande maioria do seu código deve ser idêntica ao usar o DI manualmente, como ao usar um contêiner de IoC. A diferença deve residir inteiramente em alguns "pontos de inicialização" dentro do aplicativo.
Em outras palavras, se você não gosta de contêineres IoC, provavelmente não está fazendo a Injeção de Dependência da maneira que deveria ser feita.
Outro ponto: a injeção de dependência realmente não pode ser feita manualmente, se você usar a reflexão em qualquer lugar. Embora eu odeie o que a reflexão faz para codificar a navegação, você precisa reconhecer que há certas áreas em que ela realmente não pode ser evitada. O ASP.NET MVC, por exemplo, tenta instanciar o controlador via reflexão em cada solicitação. Para fazer a injeção de dependência manualmente, você teria que tornar todos os controladores uma "raiz de contexto", assim:
Agora compare isso com permitir que uma estrutura DI faça isso por você:
Usando uma estrutura DI, observe que:
ISimpleWorkflowInstanceMerger
, posso testar se ele é usado da maneira que antecipo, sem a necessidade de uma conexão com o banco de dados ou qualquer coisa.ISimpleWorkflowInstanceMerger
interface. Isso me permite dividir o aplicativo em módulos separados e manter uma verdadeira arquitetura multicamada, o que, por sua vez, torna as coisas muito mais flexíveis.Um aplicativo Web típico terá muitos controladores. Toda a dor de fazer DI manualmente em cada controlador realmente aumentará à medida que o aplicativo crescer. Se você tiver um aplicativo com apenas uma raiz de contexto, que nunca tenta instanciar um serviço por reflexão, isso não é um problema tão grande. No entanto, qualquer aplicativo que use Injeção de Dependência se tornará extremamente caro para gerenciar quando atingir um determinado tamanho, a menos que você use algum tipo de estrutura para gerenciar o gráfico de dependência.
fonte
Sempre que você usa a palavra-chave "new", está criando uma dependência de classe concreta e um pequeno alarme deve soar na sua cabeça. Torna-se mais difícil testar esse objeto isoladamente. A solução é programar para interfaces e injetar a dependência para que o objeto possa ser testado em unidade com qualquer coisa que implemente essa interface (por exemplo, zombarias).
O problema é que você precisa construir objetos em algum lugar. Um padrão de fábrica é uma maneira de mudar o acoplamento de seus POXOs (Plain Old "insira sua linguagem OO aqui" Objetos). Se você e seus colegas de trabalho estão escrevendo código como esse, um contêiner de IoC é a próxima "Melhoria Incremental" que você pode fazer na sua base de código. Isso mudará todo esse código desagradável do padrão da Fábrica para fora de seus objetos limpos e da lógica de negócios. Eles vão entender e amar. Caramba, fale para a empresa sobre o motivo de você adorar e deixe todo mundo entusiasmado.
Se seus colegas de trabalho ainda não estão trabalhando com DI, sugiro que você se concentre nisso primeiro. Divulgue como escrever um código limpo que seja facilmente testável. O código DI limpo é a parte mais difícil, quando você estiver lá, mudar a lógica de fiação de objetos das classes Factory para um contêiner de IoC deve ser relativamente trivial.
fonte
Como todas as dependências são claramente visíveis, promove a criação de componentes que são fracamente acoplados e ao mesmo tempo facilmente acessíveis e reutilizáveis em todo o aplicativo.
fonte
Você não precisa de um contêiner de IoC.
Mas se você seguir rigorosamente um padrão de DI, verá que ter um deles removerá uma tonelada de código redundante e chato.
De qualquer maneira, esse é o melhor momento para usar uma biblioteca / estrutura - quando você entende o que está fazendo e pode fazê-lo sem a biblioteca.
fonte
Por acaso, eu estou no processo de obter código DI desenvolvido em casa e substituí-lo por um COI. Provavelmente removi bem mais de 200 linhas de código e substituí-o por cerca de 10. Sim, tive que aprender um pouco sobre como usar o contêiner (Winsor), mas sou um engenheiro que trabalha em tecnologias da Internet no Século 21, então estou acostumado a isso. Eu provavelmente gastei cerca de 20 minutos examinando os procedimentos. Valeu a pena o meu tempo.
fonte
À medida que você continua a dissociar suas classes e inverter suas dependências, as classes continuam pequenas e o "gráfico de dependências" continua aumentando de tamanho. (Isso não é ruim.) O uso de recursos básicos de um contêiner de IoC torna a conexão de todos esses objetos trivial, mas fazê-lo manualmente pode ser muito oneroso. Por exemplo, e se eu quiser criar uma nova instância de "Foo", mas precisar de uma "Barra". E um "Bar" precisa de um "A", "B" e "C". E cada um deles precisa de 3 outras coisas, etc etc. (sim, não consigo criar bons nomes falsos :)).
O uso de um contêiner de IoC para criar seu gráfico de objetos reduz a complexidade em uma tonelada e a coloca na configuração única. Eu simplesmente digo "crie-me um 'Foo'" e descobre o que é necessário para criar um.
Algumas pessoas usam os contêineres IoC para muito mais infraestrutura, o que é bom para cenários avançados, mas nesses casos eu concordo que ele pode ofuscar e dificultar a leitura e depuração de códigos para novos desenvolvedores.
fonte
Dittos sobre Unity. Ficar grande demais e você pode ouvir o rangido nas vigas.
Isso nunca me surpreende quando as pessoas começam a falar sobre a aparência do código IoC limpo. São os mesmos tipos de pessoas que falaram sobre como os modelos em C ++ eram a maneira elegante de voltar nos anos 90, mas hoje em dia os consideram misteriosos. . Bah!
fonte
No mundo .NET, o AOP não é muito popular; portanto, para o DI, uma estrutura é sua única opção real, seja você mesmo escrevendo uma ou usando outra estrutura.
Se você usou o AOP, pode injetar ao compilar seu aplicativo, o que é mais comum em Java.
Existem muitos benefícios para o DI, como o acoplamento reduzido, para facilitar o teste de unidade, mas como você o implementará? Deseja usar a reflexão para fazer isso sozinho?
fonte
Então, já faz quase 3 anos, não é?
50% dos que comentaram a favor das estruturas de IoC não entendem a diferença entre as estruturas de IoC e IoC. Duvido que eles saibam que você pode escrever código sem ser implantado em um servidor de aplicativos
Se usarmos a estrutura Java Spring mais popular, é a configuração da IoC movida do XMl para o código e agora parece com isso
`@Configuration public class AppConfig {
} `E precisamos de uma estrutura para fazer isso, por que exatamente?
fonte
Honestamente, não acho que existam muitos casos em que os contêineres IoC são necessários e, na maioria das vezes, eles apenas adicionam complexidade desnecessária.
Se você o estiver usando apenas para simplificar a construção de um objeto, eu teria que perguntar: você está instanciando esse objeto em mais de um local? Um singleton não atenderia às suas necessidades? Você está alterando a configuração em tempo de execução? (Alternando tipos de fonte de dados, etc).
Se sim, você pode precisar de um contêiner de IoC. Caso contrário, você está apenas afastando a inicialização de onde o desenvolvedor pode vê-la facilmente.
Quem disse que uma interface é melhor que herança, afinal? Digamos que você esteja testando um serviço. Por que não usar o construtor DI e criar zombarias das dependências usando herança? A maioria dos serviços que utilizo possui apenas algumas dependências. Fazer testes de unidade dessa maneira impede a manutenção de inúmeras interfaces inúteis e significa que você não precisa usar o Resharper para encontrar rapidamente a declaração de um método.
Acredito que, na maioria das implementações, dizer que os contêineres IoC removem códigos desnecessários é um mito.
Primeiro, é necessário configurar o contêiner. Então você ainda precisa definir cada objeto que precisa ser inicializado. Para não salvar o código na inicialização, você o move (a menos que seu objeto seja usado mais de uma vez. É melhor como um Singleton?). Então, para cada objeto que você inicializou dessa maneira, você deve criar e manter uma interface.
Alguém tem alguma opinião sobre isso?
fonte
ShippingCostCalculator
ouProductUIPresentation
, ou qualquer outra estratégia / implementação, dentro de exatamente a mesma base de código , através da implantação de apenas um arquivo XML alterado.Você precisaria de um contêiner de IoC se precisasse centralizar a configuração de suas dependências para que elas possam ser facilmente trocadas em massa. Isso faz mais sentido no TDD, onde muitas dependências são trocadas, mas onde há pouca interdependência entre as dependências. Isso é feito com o custo de ofuscar o fluxo de controle da construção de objetos em algum grau, portanto, é importante ter uma configuração bem organizada e razoavelmente documentada. Também é bom ter uma razão para fazer isso, caso contrário, é mera abstração . Vi isso tão mal que foi arrastado para ser o equivalente a uma declaração goto para construtores.
fonte
Aqui está o porquê. O projeto é chamado de COI com Ninject. Você pode baixar e executá-lo com o Visual Studio. Este exemplo usa o Ninject, mas TODAS as instruções 'new' estão em um local e você pode alterar completamente como o aplicativo é executado, alterando o módulo de ligação a ser usado. O exemplo é configurado para que você possa vincular a uma versão simulada dos serviços ou à versão real. Em pequenos projetos que podem não importar, mas em grandes projetos é um grande negócio.
Só para deixar claro, vantagens como as vejo: 1) TODAS as novas instruções em um local na raiz do código. 2) Re-fatore totalmente o código com uma alteração. 3) Pontos extras para 'fator legal' porque é ... bem: legal. : p
fonte
Vou tentar descobrir por que o COI pode não ser bom da minha perspectiva.
Como em todo o resto, o contêiner do IOC (ou como Einstein o colocaria I = OC ^ 2) é um conceito que você deve decidir por si mesmo se precisa ou não no seu código. Os protestos recentes sobre o COI são apenas isso, moda. Não caia na moda, isso é o primeiro. Existem inúmeros conceitos por aí que você pode implementar em seu código. Antes de tudo, estou usando a injeção de dependência desde que comecei a programar e aprendi o próprio termo quando foi popularizado com esse nome. O controle de dependência é um assunto muito antigo e foi abordado até agora em trilhões de maneiras, dependendo do que estava se dissociando do que. Separar tudo de tudo é um absurdo. O problema com o contêiner IOC é que ele tenta ser tão útil quanto o Entity Framework ou o NHibernate. Embora escrever um mapeador objeto-relacional seja simplesmente necessário, assim que você tiver que acoplar qualquer banco de dados ao seu sistema, o contêiner IOC nem sempre é necessário. Portanto, quando o contêiner IOC é útil:
1: Não é tão frequente que você tenha tantas dependências em seu código ou que esteja ciente delas no início do design. O pensamento abstrato é útil quando o pensamento abstrato é devido.
2: Acoplar seu código a um código de terceiros é um problema do HuGe. Eu estava trabalhando com código com mais de 10 anos de idade e que seguia os conceitos sofisticados e avançados ATL, COM, COM + e assim por diante. Não há nada que você possa fazer com esse código agora. O que estou dizendo é que um conceito avançado oferece uma vantagem aparente, mas isso é cancelado a longo prazo com a vantagem desatualizada. Isso havia tornado tudo mais caro.
3: O desenvolvimento de software é bastante difícil. Você pode estendê-lo a níveis irreconhecíveis se permitir que algum conceito avançado seja cortado em seu código. Há um problema com o IOC2. Embora esteja dissociando dependências, está dissociando também o fluxo lógico. Imagine que você encontrou um bug e precisa fazer uma pausa para examinar a situação. O COI2, como qualquer outro conceito avançado, está tornando isso mais difícil. Corrigir um bug dentro de um conceito é mais difícil do que corrigir um bug em um código mais simples, porque quando você corrige um bug, um conceito deve ser obedecido novamente. (Apenas para dar um exemplo, o C ++ .NET está constantemente alterando a sintaxe tanto que você precisa pensar bastante antes de refatorar uma versão mais antiga do .NET.) Então, qual é o problema com o IOC? O problema está na resolução de dependências. A lógica para resolver geralmente está oculta no IOC2, escrito talvez de maneira incomum que você precise aprender e manter. O seu produto de terceiros estará lá em 5 anos? Microsoft não era.
A síndrome "nós sabemos como" está escrita em todo o lugar em relação à IOC2. Isso é semelhante ao teste de automação. Termo extravagante e solução perfeita à primeira vista, basta colocar todos os seus testes para executar durante a noite e ver os resultados pela manhã. É realmente doloroso explicar empresa após empresa o que realmente significa testes automatizados. O teste automatizado definitivamente não é uma maneira rápida de reduzir o número de bugs que você pode introduzir durante a noite para aumentar a qualidade do seu produto. Mas, a moda está tornando essa noção irritantemente dominante. IOC2 sofre a mesma síndrome. Acredita-se que você precise implementá-lo para que seu software seja bom. Toda entrevista recente me perguntaram se estou implementando o IOC2 e a automação. Isso é um sinal de moda: a empresa tinha uma parte do código escrita no MFC que não abandonaria.
Você precisa aprender IOC2 como qualquer outro conceito em software. A decisão se o IOC2 precisar ser usado é da equipe e da empresa. No entanto, pelo menos TODOS os argumentos acima devem ser mencionados antes que a decisão seja tomada. Somente se você vir que o lado positivo supera o lado negativo, poderá tomar uma decisão positiva.
Não há nada de errado com o IOC2, exceto que ele resolve apenas os problemas que resolve e apresenta os problemas que apresenta. Nada mais. No entanto, ir contra a moda é muito difícil, eles têm boca suada, os seguidores de qualquer coisa. É estranho como nenhum deles existe quando o problema com sua fantasia se torna aparente. Muitos conceitos na indústria de software foram defendidos porque geram lucro, livros são escritos, conferências são realizadas, novos produtos são feitos. Isso é moda, geralmente de curta duração. Assim que as pessoas encontram outra coisa, elas a abandonam completamente. O IOC2 é útil, mas mostra os mesmos sinais que muitos outros conceitos desaparecidos que já vi. Não sei se vai sobreviver. Não há regra para isso. Você acha que se for útil, sobreviverá. Não, não é assim. Uma grande empresa rica é suficiente e o conceito pode morrer dentro de algumas semanas. Veremos. O NHibernate sobreviveu, a EF ficou em segundo lugar. Talvez o IOC2 também sobreviva. Não esqueça que a maioria dos conceitos em desenvolvimento de software não tem nada de especial, é muito lógica, simples e óbvia e, às vezes, é mais difícil lembrar a convenção de nomenclatura atual do que entender o próprio conceito. O conhecimento do IOC2 torna um desenvolvedor um desenvolvedor melhor? Não, porque se um desenvolvedor não conseguiu criar um conceito de natureza semelhante ao IOC2, será difícil para ele entender qual problema o IOC2 está resolvendo, usá-lo parecerá artificial e ele poderá começar a usá-lo. por uma questão de ser algum tipo de politicamente correto. Não esqueça que a maioria dos conceitos em desenvolvimento de software não tem nada de especial, é muito lógica, simples e óbvia e, às vezes, é mais difícil lembrar a convenção de nomenclatura atual do que entender o próprio conceito. O conhecimento do IOC2 torna um desenvolvedor um desenvolvedor melhor? Não, porque se um desenvolvedor não conseguiu criar um conceito de natureza semelhante ao IOC2, será difícil para ele entender qual problema o IOC2 está resolvendo, usá-lo parecerá artificial e ele poderá começar a usá-lo. por uma questão de ser algum tipo de politicamente correto. Não esqueça que a maioria dos conceitos em desenvolvimento de software não tem nada de especial, é muito lógica, simples e óbvia e, às vezes, é mais difícil lembrar a convenção de nomenclatura atual do que entender o próprio conceito. O conhecimento do IOC2 torna um desenvolvedor um desenvolvedor melhor? Não, porque se um desenvolvedor não conseguiu criar um conceito de natureza semelhante ao IOC2, será difícil para ele entender qual problema o IOC2 está resolvendo, usá-lo parecerá artificial e ele poderá começar a usá-lo. por uma questão de ser algum tipo de politicamente correto. O conhecimento do IOC2 torna um desenvolvedor um desenvolvedor melhor? Não, porque se um desenvolvedor não conseguiu criar um conceito de natureza semelhante ao IOC2, será difícil para ele entender qual problema o IOC2 está resolvendo, usá-lo parecerá artificial e ele poderá começar a usá-lo. por uma questão de ser algum tipo de politicamente correto. O conhecimento do IOC2 torna um desenvolvedor um desenvolvedor melhor? Não, porque se um desenvolvedor não conseguiu criar um conceito de natureza semelhante ao IOC2, será difícil para ele entender qual problema o IOC2 está resolvendo, usá-lo parecerá artificial e ele poderá começar a usá-lo. por uma questão de ser algum tipo de politicamente correto.
fonte
Pessoalmente, eu uso a IoC como algum tipo de mapa de estrutura do meu aplicativo (Sim, eu também prefiro StructureMap;)). Isso facilita a substituição de minhas implementações de interface usual pelas implementações de Moq durante os testes. Criar uma configuração de teste pode ser tão fácil quanto fazer uma nova chamada de inicialização para minha estrutura de IoC, substituindo qualquer classe que seja minha fronteira de teste por uma simulação.
Provavelmente não é para isso que a IoC existe, mas é para isso que eu me uso mais.
fonte
O contêiner do COI resolve um problema que você talvez não tenha, mas é um bom problema
http://kozmic.net/2012/10/23/ioc-container-solves-a-problem-you-might-not-have-but-its-a-nice-problem-to-have/
fonte
você não precisa de uma estrutura para obter injeção de dependência. Você também pode fazer isso usando os principais conceitos do Java. http://en.wikipedia.org/wiki/Dependency_injection#Code_illustration_using_Java
fonte
Percebo que este é um post bastante antigo, mas parece estar razoavelmente ativo, e pensei em contribuir com alguns pontos que ainda não foram mencionados em outras respostas.
Eu direi que concordo com os benefícios da injeção de dependência, mas prefiro construir e gerenciar os objetos pessoalmente, usando um padrão não muito diferente do descrito por Maxm007 em sua resposta. Encontrei dois problemas principais ao usar contêineres de terceiros:
1) Ter uma biblioteca de terceiros gerenciando o tempo de vida de seus objetos "automagicamente" pode se prestar a resultados inesperados. Descobrimos que, especialmente em grandes projetos, é possível ter muito mais cópias de um objeto do que o esperado e mais do que você teria se estivesse gerenciando manualmente os ciclos de vida. Tenho certeza de que isso varia dependendo da estrutura usada, mas o problema existe. Isso também pode ser problemático se o objeto contiver recursos, conexões de dados etc., pois o objeto pode durar mais do que o esperado. Tão inevitavelmente, os contêineres de IoC tendem a aumentar a utilização de recursos e a pegada de memória de um aplicativo.
2) Os contêineres IoC, na minha opinião, são uma forma de "programação de caixa preta". Eu descobri que, em particular, nossos desenvolvedores menos experientes tendem a abusar deles. Ele permite que o programador não precise pensar em como os objetos devem se relacionar ou como desacoplar, porque fornece a eles um mecanismo no qual eles podem simplesmente pegar qualquer objeto que quiserem do nada. Por exemplo, pode haver um bom motivo de design para que o ObjectA nunca deva saber diretamente sobre o ObjectB, mas, em vez de criar uma fábrica, ponte ou localizador de serviço, um programador inexperiente simplesmente dirá "sem problemas, eu apenas pegarei o ObjectB no contêiner IoC " Na verdade, isso pode levar ao aumento do acoplamento de objetos, que é o que a IoC deve ajudar a impedir.
fonte
A injeção de dependência em um projeto ASP.NET pode ser realizada com algumas linhas de código. Suponho que haja alguma vantagem em usar um contêiner quando você tiver um aplicativo que use vários front-ends e precise de testes de unidade.
fonte