DI vs Service locator, state of the art?
- ooouuiii
- Člen | 2
Ahoj, muzete mi prosim pomoci s pouzitim DI?
Mejme tridu:
class ProductMetadata {
public function __construct(**Nette\Database\Connection $db, $categoryId**) {...}
}
Situace:
- $categoryId musi byt jiz v konstruktoru
- $db je zavislost ve vsech modelech
- chci vytvaret vic instanci teto tridy (ne jako sluzbu)
Co jsem pochopil, idealne bych mel nechat DI mi cely ten objekt instancovat = dotahnout vsechny zavislosti v konstruktoru. To bych mohl pres:
1. v neonu:
services:
project:
autowired: no #aby se to nechovalo jako service
parameters: [categoryId]
class: \Project(..., %categoryId%)
2. v presenteru neco jako:
$this->context->createServiceProject(123);
Ok, je to ciste, ale premyslel jsem, co me to stoji.
Odted uz nikdy jednoduse neudelam
$pm = new ProjectMetadata($catId=123);
,
na klientsky kod jsem prenesl odpovednost ziskat DB objekt a DB objekt bych mel
ziskavat pres DI.
- v prostredi presenteru to znamena – nemuzu pouzit @inject, protoze potrebuji predat do konstruktoru $categoryId. Konfigurovat kuli tomu Factory service se mi nechce (pro kazdy objekt s parametrem v konstruktoru?) a nebo si muzu na presenter injectovat vsechny zavislosti a ty pak do konstruktoru vlozit rucne… vse mi prijde komplikovane.
- v modelu je situaci v podstate horsi, protoze ten standardne nema k dispozici DI kontejner. Kdyz mam model tridu, ktera nepotrebuje pripojeni k db, ale za urcitych podminek potrebuje instancovat objekt, ktery spojeni potrebuje, musela by si zanest konstruktor zavislosti na db. A je to spravne, kdyz databazi sama nikdy nepotrebuje?
Dosel jsem k pocitu, ze modelova vrstva by mela mit DI od zakladu
k dispozici a nektere veci si aktivne z DI zadat, misto uvadeni jich jako
zavislosti. Tim predejit constructor hell a vratit se k jednoduchemu pouziti
new ClassName($jen, $specificke, $parametry);
Rozhodne nerikam pouzivat to pro vsechny sluzby, ale co si myslite o tom:
- mit BaseModel = predek vsech modelu, s protected $di = DI kontejner
- DB a sluzby, ktere maji prirozene jeden pristupovy bod (DB, Sessions apod.) si v modelu tahat pres $this->di->getService(…) = neuvadet je jako zavislosti
Myslim, ze podstata toho navrhoveho vzoru drzi. Porad se nestaram o to, jak mi DI moji zavislost uvari (a tzn. muzu to v DI vesele menit).
V Nette jsem nenapsal zadnou prehnane modularni aplikaci, napada vas, v cem
me to muze kousnout?
Vidim jen to, ze ty zavislosti az v kodu nejde odhadnout dopredu
(z konstruktoru ano), ale to nebude problem u DB a Sessions zase.
EDIT: sorry za ukecanost, nekolikrat jsem to prepisoval, nedokazal poradne zkratit.
Editoval ooouuiii (24. 7. 2014 0:46)