Digamos que temos 1001 clientes que constroem suas dependências diretamente, em vez de aceitarem injeções. Refatorar o 1001 não é uma opção, de acordo com nosso chefe. Na verdade, nem sequer é permitido o acesso à fonte, apenas aos arquivos de classe.
O que devemos fazer é "modernizar" o sistema pelo qual esses 1001 clientes passam. Podemos refatorar tudo o que gostamos. As dependências fazem parte desse sistema. E algumas dessas dependências que devemos mudar para ter uma nova implementação.
O que gostaríamos de fazer é ter a capacidade de configurar diferentes implementações de dependências para satisfazer essa multidão de clientes. Infelizmente, o DI não parece uma opção, pois os clientes não aceitam injeções com construtores ou setters.
As opções:
1) Refatorar a implementação do serviço que os clientes usam para que ele faça o que os clientes precisam agora. Bang, terminamos. Não é flexível. Não é complexo.
2) Refatorar a implementação para delegar seu trabalho a outra dependência que ela adquire por meio de uma fábrica. Agora podemos controlar qual implementação eles usam refatorando a fábrica.
3) Refatorar a implementação para delegar seu trabalho a outra dependência que ela adquire por meio de um localizador de serviço. Agora podemos controlar qual implementação eles usam configurando o localizador de serviço, que pode ser simplesmente uma hashmap
sequência de caracteres para objetos com um pouco de conversão.
4) Algo em que ainda nem pensei.
O objetivo:
Minimize o dano do design causado arrastando o código do cliente mal projetado antigo para o futuro sem adicionar complexidade inútil.
Os clientes não devem saber ou controlar a implementação de suas dependências, mas insistem em construí-las new
. Não podemos controlar, new
mas controlamos a classe que eles estão construindo.
Minha pergunta:
O que deixei de considerar?
você realmente precisa da possibilidade de configurar entre diferentes implementações? Para qual propósito?
Agilidade. Muitas incógnitas. A gerência quer potencial de mudança. Só perca a dependência do mundo exterior. Também testando.
você precisa de uma mecânica de tempo de execução ou apenas uma mecânica de tempo de compilação para alternar entre diferentes implementações? Por quê?
É provável que a mecânica do tempo de compilação seja suficiente. Exceto para testes.
qual granularidade você precisa alternar entre implementações? Tudo de uma vez? Por módulo (cada um contendo um grupo de classes)? Por turma?
Dos 1001, apenas um é executado pelo sistema a qualquer momento. Alterar o que todos os clientes usam ao mesmo tempo provavelmente é bom. O controle individual das dependências provavelmente é importante.
quem precisa controlar o interruptor? Somente sua / sua equipe de desenvolvedores? Um administrador? Cada cliente por conta própria? Ou os desenvolvedores de manutenção para o código do cliente? Então, quão fácil / robusta / infalível a mecânica precisa ser?
Dev para teste. Administrador conforme as dependências externas de hardware são alteradas. Precisa ser fácil de testar e configurar.
Nosso objetivo é mostrar que o sistema pode ser refeito rapidamente e modernizado.
caso de uso real para a opção de implementação?
Uma é que alguns dados serão fornecidos pelo software até que a solução de hardware esteja pronta.