Jak správně používat inject?

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

(Nette 2–1dev)

Ahoj, mám dotaz ohledně správného používání inject. Pokud chci injectovanou službu využít ve všech presenterech, stačí tedy injectnout jednou v BasePresenteru a promennou nastavit na protected? A poté tedy jen ostatní presentery dědit od BasePreseneter.

2. dotaz: Je nutné pro zachování závislostí vyčleňovat formuláře, které používám v AdminModulu a každý vždy jen jednou, do zvláštních tříd a obsáhnout do konfiguračního souboru (config.neon)? Upřednostňuji rychlejší způsob, ale zas nechci mít každý kus kódu jiným způsobem.

3. dotaz: Pro datagrid(nifty) používám továrničky, které injectuji do presenteru. Existuje jiný způsob jak injectnou a vytvořit instanci továrničky než přes interface? Nechce se mi pro každý soubor definovat interface. Pokud jsem nevytvořil interface, tak to hlásilo: „No service of type AdminModule\ArticleGrid found. Make sure the type hint in AdminModule\ArticlePresenter::injectGrids() is written correctly and service of this type is registered.“;

Díky

Editoval czm4rty (12. 1. 2013 10:13)

Filip Procházka
Moderator | 4668
+
0
-

czm4rty napsal(a):

Pokud chci injectovanou službu využít ve všech presenterech, …

Ano, ale nedělej to tak u všeho, BasePresenter se ti pak bude nepěkně nafukovat.

2. dotaz: Je nutné pro zachování závislostí vyčleňovat formuláře, které používám v AdminModulu a každý vždy jen jednou, do zvláštních tříd a obsáhnout do konfiguračního souboru (config.neon)? Upřednostňuji rychlejší způsob, ale zas nechci mít každý kus kódu jiným způsobem.

Nutné to není, ale je velice dobrý způsob.

Nechce se mi pro každý soubor definovat interface.

Definovat interface není nic hrozného ;) A tohle by ti mohlo usnadnit používání.

czm4rty
Člen | 29
+
0
-

Díky za odpovědi .-)

vvoody
Člen | 910
+
0
-

Ja mám každý jeden formulár vo vlastnej triede a ku každému mám továrničku (celú triedu <ComponentName>Factory s metódou create) ktorá si drží DI container. K továrničkám nevytváram interface, registrujem si ich klasicky do configu ako anonymné služby. Presenter ich obdrží cez inject autowire na základe typehintu.

K tomu ešte má môj BasePresenter upravenú metódu createComponent tak, aby po nenájdení továrničky createComponent<ComponentName> vyhľadala protected property s anotáciou @componentFactory a @componentName s názvom požadovanej komponenty

/**
 * @componentFactory
 * @componentName newsForm
 * @var \App\Factories\NewsFormFactory
 */
protected $newsFormFactory;

Možno by bolo lepšie

@componentFactory(name="newsForm")

aj to len optional, predsa názov môžeme odvodiť z názvu triedy továrničky. :D Nepreháňam to už trochu?

Filip Procházka
Moderator | 4668
+
0
-

vvoody napsal(a):

K továrničkám nevytváram interface, registrujem si ich klasicky do configu ako anonymné služby. Presenter ich obdrží cez inject autowire na základe typehintu.

Víš proč je to špatně? Protože v jednom presenteru nemůžeš takovou komponentu použít 2×.

vvoody
Člen | 910
+
0
-

Neviem či sa dobre chápeme. Ja injectujem továrničku, nie komponentu. A ak tam mám továrničku tak si môžem navytvárať x komponent, napríklad aj cez multiplier. Niečo som zle pochopil?

Filip Procházka
Moderator | 4668
+
0
-

Aha, ty používáš tohle? Tak to se omlouvám, to je dobrý přístup :)

vvoody
Člen | 910
+
0
-

V podstate hej, len účel mojich továrničiek je len vytvoriť inštanciu a predať jej závislosti. Čiastočne automaticky (v BaseFactory) vyhľadávaním public inject<Cokolvek> metód tak ako v presenteroch. Logika formulára je až v triede inštancovanej továrničkou, ktorá dedí od BaseForm a tá od UI\Control. Takže od UI\Form nededím, ten mám ako subkomponentu.
BaseForm:

protected function createComponentForm()
{
	$form = new Nette\Application\UI\Form;

	// some magic

	return $form;
}

public function getForm()
{
	return $this['form'];
}

Zachoval som si defaultné renderovanie lebo ho najčastejšie využívam (s tvojím BootstrapRenderer-om)

public function render()
{
	// some magic
	$this->getForm()->render();
}

Len ma štve ten dlhý zoznam anonymných služieb s továrničkami a vlastne aj s väčšou časťou repozitárov. Továrničky sú u mňa vždy ako anonymné služby, lebo pri nich nikdy nepotrebujem predať žiaden parameter, kedže aj tak obdržia v konštruktore BaseFactory DI kontainer z ktorého si vytiahnem všetko čo potrebujem a hlavne lazy. Preto ich tam často zabudnem napísať, najradšej by som ich tam vôbec nepísal, ale neviem či je to dobrý nápad to načítavať podla zoznamu súborov v adresári.

czm4rty
Člen | 29
+
0
-

Vytvarite pro kazdy interface zvlast soubor?

Oli
Člen | 1215
+
0
-

Zkusím navázat na téma s mou otázkou.
1) Pokud vytvářím komponentu, jaký je rozdíl mezi tím, vytvořit si ji přes konstruktor a jako službu? Teď to vytvářím přes konstruktor, ale na spoustě míst na foru vidím, že se to dělá spíš přes služby.

public function createComponentEditPage()
{
	return new Form\PagesForm($this->getAuthorModel(), $this->getPagesModel(), $this->getLang());
}

vs.

public function __construct(EditPageFormFactory $formFactory)
{
        $this->formFactory = $formFactory;
}

protected function createComponentEditPage()
{
        return $this->formFactory->createForm($this->getAuthorModel(), $this->getPagesModel(), $this->getLang());
}

2) Jaký je rozdíl mezi inject<neco> metodou a konstruktorem? Zase, používám konstruktor a ty inject metody mě přijdou jako spousta metod navíc. Když potřebuju připojit třeba 4 služby do presenteru, tak bych měl vytvořit 4 metody? Jaká je teda výhoda?

public function __construct(\PageModel $pages, \AuthorModel $author)
{
	$this->pagesModel = $pages;
	$this->authorModel = $author;
}

vs

public function injectPage(\PageModel $pages)
{
    $this->pagesModel = $pages;
}

public function injectAuthor(\AuthorModel $author)
{
    $this->authorModel = $author;
}

U obou případů mě přijde nepoužití konstruktoru jako víc psaní. Předpokládám, že tam nějaká přidaná hodnota bude, ale jaká? A proč je použití mimo konstruktor „správnější“? Předpokládám, že správnější je, když na to vznikly ty metody…

Filip Procházka
Moderator | 4668
+
0
-

Pokud vytvářím komponentu, jaký je rozdíl mezi tím, vytvořit si ji přes konstruktor a jako službu? Teď to vytvářím přes konstruktor, ale na spoustě míst na foru vidím, že se to dělá spíš přes služby.

Oba přístupy jsou naprosto v pořádku. Na vytváření pomocí new (například v presenterech) není z hlediska čistoty kódu vůbec nic špatně. Rozdíl je v tom, že kdy budeš třídu vytvářet pres DIC (tedy přes továrničku, kterou ti generuje) tak budeš moci velice jednoduše změnit například konstruktor třídy a přidat ji závislost. A najednou místo nutnosti hledat všechna použití třídy v aplikaci se změna projeví úplně všude, protože máš konfiguraci na jednom místě ;)

Proto existuje DI Container.

Jaký je rozdíl mezi inject<neco> metodou a konstruktorem? Zase, používám konstruktor a ty inject metody mě přijdou jako spousta metod navíc. Když potřebuju připojit třeba 4 služby do presenteru, tak bych měl vytvořit 4 metody? Jaká je teda výhoda?

U obou případů mě přijde nepoužití konstruktoru jako víc psaní. Předpokládám, že tam nějaká přidaná hodnota bude, ale jaká? A proč je použití mimo konstruktor „správnější“? Předpokládám, že správnější je, když na to vznikly ty metody…

Vždy je lepší použít konstruktor! Kromě presenterů.


Příště prosím založ nové téma

duke
Člen | 650
+
0
-

@Oli Bod 1 se týká problematiky dědičnosti vs kompozice (viz příklad zde), kdy v případě kompozice je lepší daný objekt (v uvedeném případě formulář) sestavovat ve zvláštní tovární třídě než přímo v nadřazené komponentě (či přímo presenteru). Tato tovární třída pak umožňuje využívat formulář i v jiných komponentách, aniž by docházelo k redundancím v kódu.

Bod 2 pak souvisí s problémem dědičnosti při použití constructor dependency injection, kde při změně v konstruktoru předka je třeba upravovat konstruktory všech jeho potomků. Inject metody jsou workaroundem tohoto problému.

Editoval duke (15. 3. 2013 19:45)

Oli
Člen | 1215
+
0
-

Super, díky oběma.

Příště teda založím nové téma. Tohle se podle mě týkalo danýho problému, tak jsem to tam připsal. Na některých forech zase nemají rádi, když se zakládá pořád nový téma. Kdo se v tom má vyznat? :-)