Eu tenho uma grande base de código com muitos singletons "antipadrão", classes de utilitário com métodos estáticos e classes criando suas próprias dependências usando a new
palavra-chave. Torna um código muito difícil de testar.
Eu quero migrar gradualmente o código para o contêiner de injeção de dependência (no meu caso Guice
, porque é um GWT
projeto). Pelo meu entendimento da injeção de dependência, é tudo ou nada. Todas as classes são gerenciadas pelo Spring / Guice ou nenhuma. Como a base de código é grande, não consigo transformar o código durante a noite. Então, eu preciso de uma maneira de fazer isso gradualmente.
O problema é que, quando começo com uma classe que precisa ser injetada em outras classes, não posso usar um simples @Inject
nessas classes, porque essas classes ainda não são gerenciadas por contêiner. Portanto, isso cria uma cadeia longa até as classes "principais" que não são injetadas em lugar algum.
A única maneira que vejo é disponibilizar Injector
globalmente um contexto / aplicativo por meio de um singleton, para que outras classes possam obter um beans gerenciados a partir dele. Mas isso contradiz a ideia importante de não revelar composition root
a aplicação.
Outra abordagem seria de baixo para cima: para começar com as classes "de alto nível", inclua-as no contêiner de injeção de dependência e vá lentamente para as classes "menores". Mas então tenho que esperar muito tempo, pois posso testar as classes menores que ainda dependem de globais / estáticas.
Qual seria o caminho para alcançar uma migração tão gradual?
PS A pergunta As abordagens graduais para injeção de dependência são semelhantes no título, mas não respondem à minha pergunta.
fonte
Respostas:
Desculpe,
C#
é o meu idioma de escolha, eu posso ler,Java
mas provavelmente abafaria a sintaxe tentando escrevê-lo ... Os mesmos conceitos se aplicam entreC#
eJava
embora, portanto, espero que isso mostre as etapas em como você pode mover gradualmente sua base de código para ser mais testável.Dado:
pode ser facilmente refatorado para usar DI, sem o uso de um contêiner de IOC - e você pode até dividi-lo em várias etapas:
(potencial) Etapa um - receba dependências, mas nenhuma alteração no código de chamada (UI):
Refatorar 2 (ou primeiro, se estiver implementando o contêiner IOC e alterando o código de chamada imediatamente):
Tecnicamente, a Etapa 2 poderia ser executada por si só - mas (potencialmente) seria muito mais trabalhosa - dependendo de quantas classes estão atualmente "atualizando" a funcionalidade que você está procurando DI.
Considere seguir a etapa 1 -> etapa 2 - para a qual você poderá criar testes de unidade
Foo
, independentemente deBar
. Considerando que antes da refatoração da etapa 1, não era facilmente realizado sem o uso da implementação real de ambas as classes. A execução das etapas 1 -> etapa 2 (em vez da etapa 2 imediatamente) permitiria alterações menores ao longo do tempo, e você já terá o início de um equipamento de teste para garantir melhor que seu refator funcione sem conseqüências.fonte
O conceito é o mesmo, esteja você usando Java, PHP ou mesmo C #. Esta questão é tratada bastante bem por Gemma Anible neste vídeo do YouTube:
https://www.youtube.com/watch?v=Jccq_Ti8Lck (PHP, desculpe!)
Você substitui o código não testável por "fachada" (por falta de um termo melhor) que chama código novo e testável. Gradualmente, você poderá substituir as chamadas antigas pelos serviços injetados. Eu fiz isso no passado e funciona bastante bem.
fonte