Acho que meus construtores estão começando a ficar assim:
public MyClass(Container con, SomeClass1 obj1, SomeClass2, obj2.... )
com crescente lista de parâmetros. Como "Container" é meu container de injeção de dependência, por que não posso fazer isso:
public MyClass(Container con)
para todas as aulas? Quais são as desvantagens? Se eu fizer isso, parece que estou usando uma estática glorificada. Compartilhe seus pensamentos sobre a loucura de IoC e injeção de dependência.
c#
java
dependency-injection
inversion-of-control
ioc-container
JP Richardson
fonte
fonte
Respostas:
Você está certo que, se você usar o contêiner como um localizador de serviço, é mais ou menos uma fábrica estática glorificada. Por muitas razões , considero isso um antipadrão .
Um dos maravilhosos benefícios da Injeção de Construtor é que ela torna visivelmente óbvias as violações do Princípio de Responsabilidade Única .
Quando isso acontece, é hora de refatorar os Serviços de fachada . Em resumo, crie uma nova interface mais granular que oculte a interação entre algumas ou todas as dependências granulares que você precisa atualmente.
fonte
Não acho que seus construtores de classe devam ter uma referência ao seu período de contêiner do COI. Isso representa uma dependência desnecessária entre sua classe e o contêiner (o tipo de dependência que o COI está tentando evitar!).
fonte
MyClass myClass = new MyClass(IDependency1 interface1, IDependency2 interface2)
(parâmetros de interface). Isto não está relacionado com pós @ de derivação, que eu interpreto como dizendo que um container de injeção de dependência não deve injetar-se em seus objetos, ou seja,MyClass myClass = new MyClass(this)
A dificuldade de passar os parâmetros não é o problema. O problema é que sua turma está fazendo muito e deve ser dividida mais.
A Injeção de Dependências pode atuar como um aviso antecipado para as classes ficarem muito grandes, especificamente por causa da crescente dor de passar em todas as dependências.
fonte
Me deparei com uma pergunta semelhante sobre injeção de dependência baseada em construtor e quão complexo estava ficando passado em todas as dependências.
Uma das abordagens que usei no passado é usar o padrão de fachada do aplicativo usando uma camada de serviço. Isso teria uma API grosseira. Se esse serviço depender de repositórios, ele usaria uma injeção de setter das propriedades particulares. Isso requer a criação de uma fábrica abstrata e a mudança da lógica de criação dos repositórios para uma fábrica.
Código detalhado com explicação pode ser encontrado aqui
Práticas recomendadas para IoC na camada de serviço complexa
fonte
Li todo esse tópico duas vezes e acho que as pessoas estão respondendo pelo que sabem, não pelo que é solicitado.
A pergunta original do JP parece que ele está construindo objetos enviando um resolvedor e, em seguida, um monte de classes, mas estamos assumindo que essas classes / objetos são serviços, propensos a injeção. E se eles não forem?
JP, se você estiver buscando alavancar o DI e desejar a glória de misturar injeção com dados contextuais, nenhum desses padrões (ou supostos "antipadrões") trata especificamente disso. Na verdade, tudo se resume ao uso de um pacote que o apoiará nesse esforço.
... este formato raramente é suportado. Acredito que a dificuldade de programar esse suporte, somada ao desempenho miserável que seria associado à implementação, torna pouco atraente para os desenvolvedores de código aberto.
Mas isso deve ser feito, porque eu devo ser capaz de criar e registrar uma fábrica para o MyClass'es, e essa fábrica deve receber dados / entradas que não são levados a ser um "serviço" apenas para passar dados. Se "antipadrão" é sobre consequências negativas, forçar a existência de tipos de serviços artificiais para transmitir dados / modelos é certamente negativo (a par do seu sentimento de agrupar suas classes em um contêiner. O mesmo instinto se aplica).
Existem estruturas que podem ajudar, mesmo que pareçam um pouco feias. Por exemplo, Ninject:
Criando uma instância usando Ninject com parâmetros adicionais no construtor
Isso é para .NET, é popular e ainda não está tão limpo quanto deveria ser, mas tenho certeza de que há algo em qualquer idioma que você escolher empregar.
fonte
Injetar o contêiner é um atalho do qual você se arrependerá.
A injeção excessiva não é o problema, geralmente é um sintoma de outras falhas estruturais, principalmente a separação de preocupações. Esse não é um problema, mas pode ter muitas fontes e o que torna isso tão difícil de corrigir é que você terá que lidar com todos eles, às vezes ao mesmo tempo (pense em desembaraçar os espaguetes).
Aqui está uma lista incompleta das coisas a serem observadas
Design de domínio ruim (raiz agregada ... etc)
Má separação de preocupações (composição do serviço, comandos, consultas) Consulte CQRS e Event Sourcing.
OU Mapeadores (tenha cuidado, essas coisas podem causar problemas)
Exibir modelos e outros DTOs (nunca reutilize um e tente reduzi-lo ao mínimo !!!!)
fonte
Problema:
1) Construtor com crescente lista de parâmetros.
2) Se a classe for herdada (Ex .:)
RepositoryBase
, a alteração da assinatura do construtor causa alterações nas classes derivadas.Solução 1
Passar
IoC Container
para o construtorPor quê
Por que não
Solução 2
Crie uma classe que agrupe todos os serviços e passe para o construtor
Classe derivada
Por quê
A
depende, essas informações são acumuladas emA.Dependency
Por que não
X.Dependency
separadamente)IoC Container
A solução 2 é apenas uma questão bruta, se houver um argumento sólido contra ela, o comentário descritivo será apreciado
fonte
Essa é a abordagem que eu uso
Aqui está uma abordagem grosseira de como executar as injeções e executar o construtor após a injeção de valores. Este é um programa totalmente funcional.
Atualmente, estou trabalhando em um projeto de hobby que funciona assim https://github.com/Jokine/ToolProject/tree/Core
fonte
Qual estrutura de injeção de dependência você está usando? Você já tentou usar injeção baseada em setter?
O benefício da injeção baseada em construtor é que parece natural para programadores Java que não usam estruturas de DI. Você precisa de 5 coisas para inicializar uma classe e, em seguida, possui 5 argumentos para o seu construtor. A desvantagem é o que você notou, fica difícil quando você tem muitas dependências.
Com o Spring, você pode passar os valores necessários com os setters e usar anotações @required para garantir que elas sejam injetadas. A desvantagem é que você precisa mover o código de inicialização do construtor para outro método e solicitar ao Spring que depois de todas as dependências serem injetadas, marcando-o com @PostConstruct. Não tenho certeza sobre outras estruturas, mas presumo que elas façam algo semelhante.
Ambas as formas funcionam, é uma questão de preferência.
fonte