Post by alexcosa ne pensate?
Dipende quanto controllo vuoi cedere.
Partiamo da una premessa: un SL implementato come nell'esempio è
pessimo, ma è anche vero che la maggior parte degli sviluppatori in
linguaggi dinamici tende a implementarlo così, per poi "vendere" un
framework che lo fa per te.
Il mio punto è che non serve una libreria esterna per implementare un SL:
class ServiceLocator {
static function getHouse(): House {
static $house = null;
if (is_null($house)) {
$house = new MyHouse();
}
return $house;
}
static function getWindow(): Window {
return new Window();
}
...
}
Vantaggi:
1- puoi avere strict typing
2- l'editor sa che oggetto torni e può autocompletarti i metodi
3- l'editor sa se il SL fornisce un service o meno
4- hai un errore (potenzialmente) molto prima da parte del compilatore
Svantaggi:
1- Devi modificare il SL quando aggiungi un servizio
Io non ho dubbi su cosa scegliere. :P
Ora veniamo alla DI. La DI dà allo sviluppatore controllo totale su cosa
passare a un oggetto. Invece di istanziare un oggetto e passargli il SL,
gli passi direttamente le dipendenze. Lo svantaggio è che se istanzi un
oggetto in profondità nel codice devi passare le dipendenze attraverso
tutto l'albero.
Nella mia esperienza conviene sempre tenere la struttura più piatta
possibile, ma siccome non è sempre facile, io preferisco avere un SL che
passo ai livelli più alti, i quali poi usano DI prendendo la roba dal SL
quando istanziano un oggetto.
Esempio insulso. Classico sito web "MV*".
Istanzio i vari repository (interfacce verso DB, servizi esterni,
logger, ecc.) e li infilo nel SL (o li faccio creare dal SL direttamente
passandogli i parametri di connessione, di solito via env vars).
Poi istanzio il router e passo il SL a ogni
Controller/ViewModel/Presenter/quellocheè.
Il controller può chiedere al SL la connessione al DB, il logger, il
mailer e magari il template engine e (se non li usa direttamente) può
istanziare altra roba passandola con DI. Per esempio può create uno
UserRepository passandogli il DB e il logger e prendere i dati, poi
creare un RichMailer passandogli il mailer, il logger e il template
engine, e infine creare un HtmlRenderer passandogli il template engine,
il template in HTML e i dati tornati dallo UserRepository per mostrare
il risultato all'utente.
Insomma: non è che uno esclude l'altro. :)
Bye.