DI vs Service locator, state of the art?

Upozornění: Tohle vlákno je hodně staré a informace nemusí být platné pro současné Nette.
ooouuiii
Člen | 2
+
0
-

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.

  1. 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.
  2. 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:

  1. mit BaseModel = predek vsech modelu, s protected $di = DI kontejner
  2. 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)