Supponiamo di avere 1001 clienti che costruiscono le loro dipendenze direttamente anziché accettare iniezioni. Il refactoring del 1001 non è un'opzione secondo il nostro capo. In realtà non ci è nemmeno permesso l'accesso alla loro fonte, solo ai file di classe.
Ciò che dovremmo fare è "modernizzare" il sistema che attraversano questi 1001 client. Possiamo riformattare tutto ciò che ci piace. Le dipendenze fanno parte di quel sistema. E alcune di quelle dipendenze che dovremmo cambiare per avere una nuova implementazione.
Quello che vorremmo fare è avere la possibilità di configurare diverse implementazioni di dipendenze per soddisfare questa moltitudine di clienti. Purtroppo, DI non sembra un'opzione poiché i clienti non accettano iniezioni con costruttori o setter.
Le opzioni:
1) Rifattorizzare l'implementazione del servizio che i clienti usano in modo che faccia ciò di cui i clienti hanno bisogno ora. Bang, abbiamo finito. Non flessibile. Non complesso.
2) Rifattorizzare l'implementazione in modo che deleghi il suo lavoro a un'altra dipendenza che acquisisce attraverso una fabbrica. Ora possiamo controllare quale implementazione usano tutti refactoring della fabbrica.
3) Rifattorizzare l'implementazione in modo da delegare il lavoro a un'altra dipendenza acquisita tramite un localizzatore di servizi. Ora possiamo controllare quale implementazione usano tutti configurando il localizzatore di servizi che potrebbe essere semplicemente una hashmap
stringa di oggetti con un piccolo casting in corso.
4) Qualcosa a cui non ho ancora pensato.
L'obiettivo:
Ridurre al minimo i danni di progettazione causati trascinando il vecchio codice client mal progettato in futuro senza aggiungere inutili complessità.
I clienti non dovrebbero conoscere o controllare l'implementazione delle loro dipendenze, ma insistono nel costruirle new
. Non possiamo controllare new
ma controlliamo la classe che stanno costruendo.
La mia domanda:
Cosa non ho considerato?
hai davvero bisogno della possibilità di configurare tra diverse implementazioni? Per quale scopo?
Agilità. Molte incognite. La direzione desidera un potenziale cambiamento. Perdere dipendenza solo dal mondo esterno. Anche test.
hai bisogno di una meccanica del tempo di esecuzione o solo di una meccanica del tempo di compilazione per passare da una implementazione all'altra? Perché?
La meccanica del tempo di compilazione è probabilmente sufficiente. Tranne che per i test.
quale granularità è necessario per passare da una implementazione all'altra? Tutto in una volta? Per modulo (ognuno contenente un gruppo di classi)? Per classe?
Dei 1001 solo uno viene eseguito nel sistema alla volta. Cambiare ciò che tutti i client utilizzano contemporaneamente è probabilmente corretto. Il controllo individuale delle dipendenze è tuttavia probabilmente importante.
chi deve controllare l'interruttore? Solo il tuo / il tuo team di sviluppatori? Un amministratore? Ogni cliente da solo? O gli sviluppatori di manutenzione per il codice del cliente? Quindi quanto deve essere semplice / robusta / infallibile la meccanica?
Dev per i test. L'amministratore mentre le dipendenze hardware esterne cambiano. Deve essere facile da testare e configurare.
Il nostro obiettivo è mostrare che il sistema può essere rifatto rapidamente e modernizzato.
caso d'uso effettivo per lo switch di implementazione?
Uno è, alcuni dati saranno forniti dal software fino a quando la soluzione hardware non sarà pronta.