Di recente ho letto l'articolo di Mark Seemann sull'anti-schema di Service Locator.
L'autore sottolinea due motivi principali per cui ServiceLocator è un anti-schema:
Problema di utilizzo dell'API (che sto perfettamente bene)
Quando la classe impiega un localizzatore di servizi, è molto difficile vedere le sue dipendenze poiché, nella maggior parte dei casi, la classe ha un solo costruttore PARAMETERLESS. Contrariamente a ServiceLocator, l'approccio DI espone esplicitamente le dipendenze tramite i parametri del costruttore in modo che le dipendenze siano facilmente visibili in IntelliSense.Problema di manutenzione (che mi confonde)
Considera l'esempio seguente
Abbiamo una classe "MyType" che utilizza un approccio di localizzazione dei servizi:
public class MyType
{
public void MyMethod()
{
var dep1 = Locator.Resolve<IDep1>();
dep1.DoSomething();
}
}
Ora vogliamo aggiungere un'altra dipendenza alla classe "MyType"
public class MyType
{
public void MyMethod()
{
var dep1 = Locator.Resolve<IDep1>();
dep1.DoSomething();
// new dependency
var dep2 = Locator.Resolve<IDep2>();
dep2.DoSomething();
}
}
Ed ecco dove inizia il mio malinteso. L'autore dice:
Diventa molto più difficile dire se stai introducendo un cambiamento di rottura o meno. È necessario comprendere l'intera applicazione in cui viene utilizzato Service Locator e il compilatore non sarà di aiuto.
Ma aspetta un secondo, se usassimo l'approccio DI, introdurremmo una dipendenza con un altro parametro nel costruttore (in caso di iniezione del costruttore). E il problema sarà ancora lì. Se potremmo dimenticare di installare ServiceLocator, potremmo dimenticare di aggiungere un nuovo mapping nel nostro contenitore IoC e l'approccio DI avrebbe lo stesso problema di runtime.
Inoltre, l'autore ha menzionato le difficoltà del test unitario. Ma non avremo problemi con l'approccio DI? Non avremo bisogno di aggiornare tutti i test che stavano istanziando quella classe? Li aggiorneremo per passare una nuova dipendenza derisa solo per rendere compilabile il nostro test. E non vedo alcun beneficio da quell'aggiornamento e dal tempo speso.
Non sto cercando di difendere l'approccio Service Locator. Ma questo malinteso mi fa pensare che sto perdendo qualcosa di molto importante. Qualcuno potrebbe dissipare i miei dubbi?
AGGIORNAMENTO (SINTESI):
La risposta alla mia domanda "Is Service Locator è un anti-schema" dipende dalle circostanze. E sicuramente non consiglierei di cancellarlo dal tuo elenco di strumenti. Potrebbe essere molto utile quando inizi a gestire il codice legacy. Se sei abbastanza fortunato da essere all'inizio del tuo progetto, l'approccio DI potrebbe essere una scelta migliore in quanto presenta alcuni vantaggi rispetto a Service Locator.
E qui ci sono le principali differenze che mi hanno convinto a non utilizzare Service Locator per i miei nuovi progetti:
- Più ovvio e importante: Service Locator nasconde le dipendenze di classe
- Se stai utilizzando un contenitore IoC, probabilmente eseguirà la scansione di tutti i costruttori all'avvio per convalidare tutte le dipendenze e fornirti un feedback immediato sui mapping mancanti (o sulla configurazione errata); ciò non è possibile se si utilizza il contenitore IoC come Service Locator
Per i dettagli leggi le risposte eccellenti fornite di seguito.