Nedostatečná DI u presenterů, inject*** settery nelze použít bez type hintů

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

V devel verzi závislosti Presenterů nastavuje PresenterFactory pomocí globálního service lokátoru – DIC – přes settery presenterů, které jsou pojmenované inject<Sluzba>. Má to ale zásadní omezení v tom, že lze setovat jen služby, které si DIC dokáže odvodit ze signatury metody – type hintem, např.

function injectBlogModel(IBlogModel $blog) {
 $this->blogModel = $blog;
}

To je trochu omezující, protože zdaleka ne všechny služby v DIC jdou takto předat, viz. např. ‚blog.articles‘ nebo ‚blog‘ zmiňovaná v dokumentaci. Asi by bylo možné předávat typehintem celý DIC a z něj si službu vybrat ručně, ale to se mi moc nezdá. Spíš bych byl pro to nějak zapojit tu část <Sluzba> v názvu metody inject<Sluzba>.

Filip Procházka
Moderator | 4668
+
0
-

Uprav si PresenterFactory, aby nevytvářelo instance, ale hledalo v DIC jako to mám já a pak můžeš Presenter konfigurovat dle potřeby.

Pokud ti jde pouze o factories, zapoj se do debaty zde, nebo zde.

Editoval HosipLan (2. 8. 2012 20:31)

blindAlley
Člen | 31
+
0
-

Mě nejde ani o jedno, nevidím důvod k tomu aby presentery byly v DIC, současná PresenterFactory je naprosto dostačující. Jediné co bych chtěl je vylepšit PresenterFactory tak, aby dovedla setter injection všech služeb dostupných přes DIC. Když mám v DIC službu ‚blog.articles‘ tak bych rád aby takovou službu PresenterFactory dovedla presenteru nasetovat. To je dnes možné jen přes type hint, což mi přijde jednak zbytečně pomalé a drahé a za druhé ne všechny služby definované v DIC takto mohu předat. Není důvod, abych musel kvůli tomu mít presenter jako službu v DIC.

Editoval blindAlley (2. 8. 2012 22:25)

Filip Procházka
Moderator | 4668
+
0
-

To co chceš je inversion of inversion of control. Tím že budeš psát nějaké jména služeb do annotací ke třídě popíráš DI, protože ho otáčíš naruby a přenášíš konfiguraci tak, kam nepatří. K tomuto není důvod. K tomu mít presenter registrovaný v DIC je spousta dobrých důvodů.

Už tady pár takových vtipálků bylo a nikomu to nevyšlo, ať měli sebevznešenější důvod. Žádné jména služeb se do tříd psát prostě nebudou.

Editoval HosipLan (3. 8. 2012 11:38)

blindAlley
Člen | 31
+
0
-

To je pořád dokola, nikdo mi jasně nedokáže vysvětlit, jak to mám zařídit, abych mohl do Presenteru přes built-in setter DI nastavit takové služby, které DIC chápe jako např. ‚blog.article‘ v příkladu v dokumentaci.

Presentery v DIC jsou řešením, ale až v případě, že to nepůjde jinak. Pak je také nasnadě zrušit použití injectXXX metod. Nikoho nenapadá něco jednoduššího jak upravit/opravit stávající setter injection u presenterů?

offtopic – HosipLan, nechte si ty narážky a výpady (vtipálek apod., párkrát jsem zahlédl na soc. sítích i něco o debilech s odkazy do fóra). Odrazuješ tak normální lidi od toho, aby vůbec na fórum něco psali, protože na ně zas naběhneš a začneš je stírat.

jasir
Člen | 746
+
0
-

Jen se zeptám, zmiňovaný příklad z dokumentace, blog.article, tohle přeci zafunguje?

function injectBlogArticles(MyBlog\ArticlesModel $articleModel) {
   $this->articleModel = $blog;
}
blindAlley
Člen | 31
+
0
-

Ano, ale tam právě musím napsat tu konkrétní třídu, při změně třídy v konfigurace služby ‚blog.articles‘ v kontejneru pak musím změnit i ten type hint, tohle mě právě vadí – bez konkrétní třídy v type hintu to nejde.

Jedno řešení má H. Marek – https://forum.nette.org/…ept-generics#…, s tím bych možná i souhlasil, určitě to stojí za vyzkoušení. Řeší to více problémů najednou bez nutnosti monstrózních úprav ve stylu presentery v DIC.

Editoval blindAlley (3. 8. 2012 11:25)

Filip Procházka
Moderator | 4668
+
0
-

To není řešení, to je nápad.

Víš od čeho jsou interfacy? Interface budeš vyžadovat a třída ho bude implementovat, když změníš třídu, nemusíš měnit typehint v presenteru. To je řešení.

OT: Neber si to prosím osobně, ale nemam sílu vést stejnou diskuzi každého půlroku. Tahle je tu minimálně potřetí a to mi opravdu nedělá dobře na nervy. Co se týče fóra, občas pošlu nějaké téma na twitter, ale nepamatuju si, že bych k němu někdy připojil „debil“, pokud to byl neznalý začátečník. Zásadně útočím jen na ty, kteří útočí na mě.

Editoval HosipLan (3. 8. 2012 11:55)

blindAlley
Člen | 31
+
0
-

Ano, o tom vím, ale mě se to moc nelíbí, na každou takovou servisu pak musím vymýšlet ještě extra interface. Mám raději duck typing, zvláště v dynamických jazycích.

Mě by stejně přišlo užitečné mít nějak možnost říci v presenteru, že chci v setteru injektovat servisu, které je v DIC jako ‚blog.articles‘ bez nutnosti na to tvořit interface a jednoduše to pak v DIC vyměnit.

Tak mě ještě napadá, nevíte, zda podporuje DIC autowiring s dědičností? V inject setteru bych měl type hint MyBlog\ArticlesModel a v DIC pak pod blog.articles třídu třeba MyBlog\TestArticleModel který by od toho MyBlog\ArticlesModel dědila? Bude to fungovat?

Filip Procházka
Moderator | 4668
+
0
-

blindAlley napsal(a):

Ano, o tom vím, ale mě se to moc nelíbí, na každou takovou servisu pak musím vymýšlet ještě extra interface. Mám raději duck typing, zvláště v dynamických jazycích.

To není extra interface. Celý DIC by správně měl být o interfacech a třídách, které je implementují. Pokud ti to dělá hodně problém, můžeš si jednoduše celý DIC v presenteru používat jako service locator. Nikdo ti v tom nebrání.

Mě by stejně přišlo užitečné mít nějak možnost říci v presenteru, že chci v setteru injektovat servisu, které je v DIC jako ‚blog.articles‘ bez nutnosti na to tvořit interface a jednoduše to pak v DIC vyměnit.

Jak jsem psal, dělá to tak sice Java, ale je to proti DI, takže v Nette to nikdy nebude. Ovšem, můžeš si napsat CompilerExtension, který přesně tohle bude dělat. Jako rozšíření. Do Nette to ale nepatří.

Tak mě ještě napadá, nevíte, zda podporuje DIC autowiring s dědičností? V inject setteru bych měl type hint MyBlog\ArticlesModel a v DIC pak pod blog.articles třídu třeba MyBlog\TestArticleModel který by od toho MyBlog\ArticlesModel dědila? Bude to fungovat?

Ano, autowiring to umí. Není to ale moc čisté. Interface by byl lepší. Samozřejmě si to udělej, jak uznáš za vhodné ;)

Editoval HosipLan (3. 8. 2012 12:35)

David Grudl
Nette Core | 8215
+
0
-

blindAlley napsal(a):

V devel verzi závislosti Presenterů nastavuje PresenterFactory pomocí globálního service lokátoru – DIC – přes settery presenterů, které jsou pojmenované inject<Sluzba>. Má to ale zásadní omezení v tom, že lze setovat jen služby, které si DIC dokáže odvodit ze signatury metody – type hintem,

Ano, tenhle nedostatek tam je a mám v plánu ho brzo odstranit. Patrně tak, že vznikne nová sekce presenters v configu.

…což mi přijde jednak zbytečně pomalé a drahé…

Z hlediska výkonu je to úplně nicotné.