As estruturas de injeção de dependência representam um risco de dependência?

13

Venho refatorando um sistema existente para usar a injeção de dependência, e esse trabalho está ocorrendo sem problemas.

Depois de um tempo, notei que um grande número de bibliotecas internas se tornou dependente da estrutura de DI que eu usava. Como resultado, todo o projeto agora depende dessa estrutura de terceiros.

Vi uma ironia em separar todas as dependências, tornando-as dependentes de uma biblioteca compartilhada.

Minha primeira reação foi criar uma biblioteca de wrapper em torno da estrutura de dependência. Portanto, eu poderia substituir essa estrutura, se necessário. Depois de estimar o trabalho envolvido, percebi que a API resultante seria semelhante à estrutura existente e, portanto, tornaria a substituição mais difícil. Então eu abandonei a ideia.

Minha preocupação é que a estrutura de DI que estou usando se torne obsoleta ou precise ser substituída.

Existe um padrão de desenvolvimento ao trabalhar com o DI que reduz o acoplamento entre um projeto e a estrutura do DI?

Reactgular
fonte
4
O padrão "não use uma estrutura DI". Embora eu deva me perguntar se você está resolvendo um problema que realmente não tem - qual a probabilidade de alterar a estrutura de DI?
Oded
1
@Oded uma boa estrutura de DI deve poder trabalhar com código de forma transparente, mas há casos em que isso não é possível. Você precisa usar as APIs DI dentro de suas classes. Nesses casos, é difícil compartilhar ou alterar a estrutura de DI sem a necessidade de alterar essas classes. Uma vez que esta é minha primeira vez trabalhando com essa estrutura de DI. Não tenho certeza se vou precisar substituí-lo.
Reactgular
8
Seu sistema também depende de eletricidade. Eu sugiro que você dissocie isso primeiro.
Idan Arye
3
@MathewFoscarini Isso não é um antipadrão? Você pode fazer isso, mas não deve, pois ofusca a dependência.
maaartinus
2
@MathewFoscarini DIFramework.Get<IService>()não é realmente injeção de dependência; é um padrão relacionado chamado Service Locator. Muitas pessoas não gostam do Service Locator porque ele o une à estrutura e porque é muito facilmente abusado (como Singleton). Martin Fowler tem um artigo fantástico sobre estes padrões: martinfowler.com/articles/injection.html
Benjamin Hodgson

Respostas:

8

Você está totalmente correto - o uso de uma estrutura DI provavelmente tornará seu código dependente disso. Na verdade, isso é muito surpreendente, pois isso geralmente é verdadeiro para todas as outras bibliotecas de estrutura ou fundação, especialmente quando essa lib suporta seu projeto com alguns recursos genéricos usados ​​em qualquer parte do código. Por exemplo, quando você decide usar uma certa estrutura de interface do usuário ou estrutura da Web, é difícil mudar essa decisão depois que você cria uma certa quantidade de código com base nessa biblioteca. Quando você decide usar uma Stringclasse específica (talvez não padrão) , não pode mudar facilmente essa decisão posteriormente. Essa decisão é arquitetônica; é como escolher uma determinada linguagem de programação e tentar mudar essa decisão depois de escrever> 100K linhas de código.

Ter todo o seu código dependente de uma determinada estrutura pode não ser um problema, desde que faça o que você espera dele e desde que seja mantido adequadamente. Mas pode se tornar um problema, se não for esse o caso. Existem algumas estratégias para lidar com essa situação:

  • escolha uma estrutura de um fornecedor em que você acredita que ele poderá fornecer atualizações e novos lançamentos por vários anos a partir de agora

  • escolha uma estrutura de código aberto que tenha poucas linhas de código suficientes (e uma licença adequada), para que você possa fazer qualquer manutenção por conta própria, considerando que o fornecedor desaparece do mercado

  • escreva sua própria estrutura

  • conviva com a situação enquanto o fornecedor estiver disponível e, quando ele realmente desaparecer, escolha uma estrutura diferente e tente criar um adaptador que emule a estrutura antiga usando o novo

A idéia de criar uma biblioteca de wrapper antecipadamente não é nova, mas raramente vi isso funcionando, pois você teria que fazer suposições para uma situação futura para a qual você não sabe se ou quando ela o afetará e o que a "nova" estrutura será semelhante. Por outro lado, há alguns anos, trocamos com êxito uma estrutura de interface do usuário completa em um projeto C ++ com ~ 120K de linhas de código aplicando a estratégia de adaptador mencionada acima.

Doc Brown
fonte
19

A injeção comum de construtor não requer uma estrutura. A única coisa que você perde é a capacidade de centralizar suas dependências em um arquivo de configuração.

Os contêineres DI são um padrão de "software corporativo", usado quando o gráfico de objetos é muito grande e complexo. Suspeito que 95% dos aplicativos não o exijam.

Robert Harvey
fonte
5
Concordo que pequenos projetos não exigem , mas mais de 95% dos projetos podem lucrar com isso.
maaartinus
11
@maaartinus: complexidade adicionada desnecessária para benefício mínimo.
Robert Harvey
1
O que? Estas são minhas estatísticas por classe: anotação 0,5, linha de configuração 0,1. Então, que complexidade você quer dizer ???
maaartinus
2
@RobertHarvey: embora eu concorde 100% com suas declarações acima, o OP afirma que ele já introduziu uma estrutura de DI. Dizer a ele "é melhor não fazer" não é realmente uma resposta para sua pergunta.
Doc Brown
1
@maaartinus quanto mais o framework automatiza e mais coisas ele pode injetar, mais complexo. Existem arquivos de configuração XML, injeção de construtor, injeção de propriedades, zombaria automática de objetos, injeção lenta, etc. etc .. essas estruturas de DI podem se tornar muito complexas.
Reactgular
0

Eu não acho que as estruturas de DI possam realmente se tornar obsoletas tão cedo. O que deveria acontecer para torná-lo obsoleto?

  • Uma invenção de um padrão novo e mais inteligente, talvez? Seja como for, isso exigiria alterações muito maiores no código.
  • Uma mudança no idioma, talvez? Pior ainda.

Eu diria que o DI atual é maduro o suficiente e não estou ciente de muita coisa acontecendo lá. Você não especificou seu idioma; portanto, falando do Guice , ele é bastante discreto e funciona com anotações Java padrão (também usa o próprio para coisas não padronizadas, mas você raramente precisa disso). É de código aberto, amplamente utilizado e licenciado pela Apache. Qual poderia ser o problema?

Tenho certeza de que alterar a estrutura de DI seria muito mais fácil do que alterar qualquer outra biblioteca (por exemplo, uma alteração na interface do usuário significa muito mais trabalho).

maaartinus
fonte