Diskuze ke článku: Inject a DIC továrničky
- Filip Procházka
- Moderator | 4668
Prosil bych připomínky ke článku Inject a DIC továrničky.
Potřebujeme hlavně, aby to pochopilo co nejvíce lidí, takže upozorňujte na nejasnosti, nebo chybějící informace. Buďto mi napište sem, nebo to rovnou upravte. Máme chytrou wiki, takže se nebojte do toho sahat, kdyby se mi něco nelíbilo, tak to po vás opravím :)
Editoval HosipLan (22. 11. 2012 19:36)
- stekycz
- Člen | 152
Osobně bych přidal k příkladu pro formuláře více vysvětlení práce
s parametry pro factories. Když na to prvně kouknu, tak vidím, že
přidávám %userId%
pro klíč create
a pak to musím
znova specifikovat samostatným klíčem parameters
. Chybí mi tam,
proč to tak je a jak tyhle parametry fungují.
Plus bych k tomu přidal i nějaké varování (podobné jako pro rozhraní výše v článku), že tyhle parametry neslouží k předávání jiných závislostí. Vidím celkem reálně přístup toho, že udělám chybně něco takového:
factories:
userForm:
create: App\CreateOrEditUserForm(%database%, %userId%)
implement: App\ICreateOrEditUserFormFactory
parameters: [database, userId]
a pak to chybně použiju:
class UserPresenter extends BasePresenter
{
/**
* @persistent
*/
public $userId = 0;
/**
* @var ICreateOrEditUserFormFactory
*/
private $userFormFactory;
/**
* @var Nette\Database\Connection
*/
private $database;
/**
* @param ICreateOrEditUserFormFactory $userFormFactory
*/
public function injectUserFormFactory(ICreateOrEditUserFormFactory $userFormFactory)
{
$this->userFormFactory = $userFormFactory;
}
/**
* @param Nette\Database\Connection $database
*/
public function injectDatabase(Nette\Database\Connection $database)
{
$this->database = $database;
}
/**
* @return CreateOrEditUserForm
*/
protected function createComponentUserForm()
{
return $this->userFormFactory->create($this->database, $this->userId);
}
}
Předpokládá to sice nepochopení předchozí části článku, ale IMHO bych se na snahu snížit počet vlastních vazeb na další služby znovu odkázal.
- Filip Procházka
- Moderator | 4668
@vvoody V dokumentaci jsou též ukázky vygenerovaného kódu – spíše o ořežu o omáčku.
@stekycz Zrovna parametry bych takticky ignoroval a po téhle úpravě bych upravil i článek, aby je vůbec neřešil.
Editoval HosipLan (22. 11. 2012 20:25)
- Hafran
- Člen | 121
Hezké, jen se mi nelíbí pořád ukazovat příklady na třídě „article“
<?php
factories:
articles:
create: ArticlesControl
implement: IArticlesControlFactory
?>
tenhle příklad obsahuje 4 slova s dvojtečkou(tedy na první pohled důležitá), z nichž tři ale jsou klíčová a jedno ne – kdyby se to menovalo myOwnClass nebo nějaká taková blbost, možná to bude pro začátečníky jednodušší. Jelikož to articles by u někoho mohlo evokovat, že jde o klíčové slovo Nette. :/
Editoval Hafran (22. 11. 2012 21:19)
- Felix
- Nette Core | 1245
Me to prijde v pohode :)
Akorat u:
Kdybych nenapsal do create, že ArticlesControlFactory bude vytvářet ArticlesControl, tak se Nette Framework koukne na IArticlesControlFactory::create(), jestli nemá annotaci @return a kdyby ano, tak si z ní sám zjistí, jakou třídu bude vytvářet.
Nejmenovalo by se to ArticlesFactory??
factories:
articles:
create: ArticlesControl
implement: IArticlesControlFactory
# vs
articlesControl:
create: ArticlesControl
implement: IArticlesControlFactory
- vvoody
- Člen | 910
@HosipLan myslím si že to ani tam nepatrí, ešte si pamätám ako som sám z toho bol zmätený, nevedel som či pre mňa ten kód niečo znamená kedže je generovaný, ale na druhú stranu je napísaný v dokumentácií, takže jej autor si zrejme myslí že ho programátor potrebuje vidieť… s čím (imho) momentálne, keď už som v obraze, nesúhlasím. Aspoň u začiatočníkov si myslím, že to narobí menej „škody“, respektíve rýchlejšie pochopia danú problematiku, keď bude predstavená čo najmenším množstvom kódu. Snažím sa na to pozerať ako by to čítal človek, čo Nette pozná tak z 5–10%, nie ako taký čo ho pozná z 50–90%.
- kubajz
- Člen | 47
Já osobně mám trochu problém s tím, proč se pro takovou funkčnost mám psát interface, v jehož definici je přímo uveden návratový typ. Připadá mi to jako zneužívání rozhraní pro jiné účely, než pro jaké má sloužit, nebo mi něco zásadního uniká?
Naopak se zastanu toho, aby vygenerovaný kód v článku zůstal.
- David Grudl
- Nette Core | 8228
Díky za tento post! Je vážně skvělé, když se člověk zajímá, jestli to, co napsal, je srozumitelné!
Takže stručně: není :-)
A podrobněji: vysvětluješ lidem, kteří mají výborné znalosti současného DI, v čem jsou lepší továrničky. (A věřím, že nás pět ten článek pochopilo.) Ale zřejmě jsi chtěl vysvětlit běžnému programátorovi, k čemu je tahle feature dobrá. V tom případě je ale potřeba se odstínit od všech předpokládaných znalostí. Žádné jak to nedělat, o trošku lépe atd, ale naopak jak to dělat a jak to používat. Trvalo mi roky, než jsem to na školeních pochopil.
Tedy ideálně ukázat příklad, jak potřebujeme v presenteru vytvářet nějaký objekt → takže potřebujeme do něj dostat továrnu → ukázat výhodu, že ji framework vygeneruje sám. A teprve nakonec se dostat k složitějšímu tématu, jako jsou komponenty.
A opět zjednodušeně: nikdy nepoužívej „Jak jistě všichni víme“ a „občas nám může vadit“. Všichni neví a featury nikdy nevadí ;)
- Filip Procházka
- Moderator | 4668
Jsem to tedy vzal od podlahy … :) Líp už to ale asi nedám, takže pokud to nestačí, bude to muset napsat někdo jiný ;)
Koho zajímá „history of factories, how it was and how it is“, tak v historii to samozřejmě zůstalo ;)
Editoval HosipLan (23. 11. 2012 0:38)
- Cifro
- Člen | 245
Davam lajk na Davidov post. Dobre to zhrnul. I keď mám rank že „Nette guru“ ale s Nette som už dlho nerobil, a ani vývoj veľmi nesledujem (iba Latte) a tak članok mi prišiel taký že, „wtf? zase sa s tým DI inak pracuje v tom Nette ako pred paru mesiacami?“
Lepšie je napisať od akej verzie (commitu) je daná fičura možná. A ako sa to robilo predtým (stručne) a ako sa to robí teraz (podrobnejšie). Nie všetci sú vždy v obraze. You know there is other life out there outside of Nette…
- Cifro
- Člen | 245
HosipLan napsal(a):
Jsem to tedy vzal od podlahy … :) Líp už to ale asi nedám, takže pokud to nestačí, bude to muset napsat někdo jiný ;)
Tak teraz je to ooooveľa lepšie. Nice :)
- Eda
- Backer | 220
Díky za článek. Takovéto osvěty obzvlášť u nových věci není nikdy dost.
První verze byla podle mě taky fajn, ale asi jsem ovlivněn tím, že se zabývala přesně tím, co jsem taky řešil a prošel jsem si stejnými fázemi přístupu, které byly postupně čtenáři předkládány.
Poznámky k aktuální verzi článku:
- doplnit na začátek upozornění o tom, že návod je určen pro verzi 2.1-dev
- explicitně bych zdůraznil: „…zaregistrujeme do DIC jako bezejmennou službu:“ Ať aspoň lidi ví, co hledat, protože o bezejmenných službách zatím v dokumentaci nic není a dokud jsem to nečetl tady na fóru, netušil jsem, že bezejmenné služby existují
- enumag
- Člen | 2118
Asi patřím mezi těch pět nebo co, ale pro mne byla lepší původní verze. :-D Zejména protože jsem chtěl vědět jak to použít s komponentami. :-)
Poznatky k nové verzi:
- Nejdříve mi přišla trochu wtf ta vlastní služba mailer, když Nette přece vytváří vlastní službu nette.mailer. Až když jsem se podíval do debugBaru tak jsem zjistil, že to je jiný mailer (Nette vytváří SendMailMailer, v článku je SmtpMailer). Ale pořád s tím mám problém, že na to nepotřebuji vlastní službu. Článek ve mne zkrátka vyvolal dojem „toto je jediný správný způsob jak odesílat e-maily“, což dle mého názoru není.
- Očekával bych, že factory pro vytvoření věcí jako \Nette\Mail\Message nebo \Nette\Latte\Engine bude také poskytovat přímo framework jako služby nette.latteFactory a nette.messageFactory a že třeba \Nette\Mail\Message bude už přímo v sobě mít metodu injectMailer. Chystá se něco takového?
Editoval enumag (23. 11. 2012 6:59)
- Filip Procházka
- Moderator | 4668
enumag napsal(a):
Nejdříve mi přišla trochu wtf ta vlastní služba mailer…
To je schválně, abych to nekomplikoval nějakým nette.
, nebo
tím, jak
nakonfigurovat mailer, všimni si také, že jsem nikde nepoužil autowire,
aby na mě DIC neřval.
Nějaké to "tohle není best practice, ale demonstrace tovarnice doplnime.
- cabadaj
- Člen | 8
Jak Nette pozná, že má implementovat metodu create()
? Nikde
v configu není použito slovo create
. Co kdyby interface
obsahoval více funkcí? Nebo je create
nějaké magické
klíčové slovo?
Osobně se mě taky moc nezdá, ze interface určuje přímo třídu, kterou
vrací. To by měla podle mě být záležitost konkrétní implementace
interface. Mělo by tam být spíš Nette\Mail\IMessage
.
- Filip Procházka
- Moderator | 4668
@enumag přidal jsem poznámku, že to není best-practise.
@cabadaj doplnil jsem poznámku o
create()
metodě.
Osobně se mě taky moc nezdá, ze interface určuje přímo třídu, kterou vrací. To by měla podle mě být záležitost konkrétní implementace interface. Mělo by tam být spíš Nette\Mail\IMessage.
Tak jsem si to přečetl 3× a už tě chápu. Problém je v tom, že nikdo ti nebude psát interface kvůli tomu, aby ho implementoval jedné třídě ;)
Má to další důvody. Například z toho Nette pozná, že bude vytvářet
Nette\Mail\Message
, ikdyž mu to nenapíšu do configu.
Úkol pro všechny: vymyslete lepší téma, kolem kterého půjde článek napsat – emaily se zdají být dost kontroverzní. Ideálně něco, co vůbec není ve frameworku.
Editoval HosipLan (23. 11. 2012 9:10)
- enumag
- Člen | 2118
HosipLan napsal(a):
@enumag přidal jsem poznámku, že to není best-practise.
OK, to už vypůadá lépe. :-)
Úkol pro všechny: vymyslete lepší téma, kolem kterého půjde článek napsat – emaily se zdají být dost kontroverzní. Ideálně něco, co vůbec není ve frameworku.
Přesně to mne taky napadlo. Že bych to přepsal na něco jiného než maily a komponenty. A stejně jako ty jsem se zasekl, protože mne nenapadá vhodné téma. :-D
Co ta druhá část ohledně injectMailer() v \Nette\Mail\Meassage?
EDIT: Trochu jsem nad tím přemýšlel.
Jaký example vlastně hledáme?
- Něco co se použije vícekrát (jinak je to služba),
- ale současně něco co není vykreslitelné (jinak je to komponenta),
- a současně to musí mít nějaké závislosti (jinak stačí new).
To už myslím docela výrazně omezuje možnosti. Kromě toho, jaký byl důvod proč @HosipLan tuhle feature vůbec vymýšlel? Pokud vím tak to bylo kvůli komponentám (@Hosiplan: oprav mne pokud se mýlím).
Z téhle úvahy mi vychází, že komponenty budou jako příklad přeci jen nejlepší, co myslíte?
Editoval enumag (23. 11. 2012 10:30)
- Filip Procházka
- Moderator | 4668
To téma (emaily) jsem vymýšlel déle, než jsem psal článek. Pochlapte se někdo ;)
Editoval HosipLan (23. 11. 2012 10:26)
- Filip Procházka
- Moderator | 4668
Dle mého jsou komponenty téže nejlepším příkladem. Můžu přidat na konec ještě jednu kapitolu s komponentam, což?
Off topic: Stejně mám pocit, že ta třída Nette\Mail\Message by ten mailer vůbec neměla potřebovat a tedy by neměla mít ani metodu send. Myslím, že by bylo lepší odesílat přes $mailer->send($message);.
To je hodně offtopic, takže jen krátce: s první větou důrazně nesouhlasím, s druhou souhlasím. Proč? Convention over configuration ;)
No a samozřejmě bych opět ocenil inspirující komentář od Davídka :) Úplně nejlepší by bylo, tě napadlo geniální téma pro demonstraci :)
Editoval HosipLan (23. 11. 2012 11:01)
- romiix.org
- Člen | 343
Je to neporovnateľne pochopiteľnejšie ako prvá verzia;)
Jediná poznámka.. Pre nováčika by mohlo byť trošku mätúce kde sa vzalo
‚$this->database‘.
Možno by to ešte mohlo pokračovať tým, že formulár so spracovaním by šiel zvlášť do továrničky a tá by bola tiež nastavená tým istým spôsobom aj s nastavením ‚database‘ a ‚mailingFactory‘ cez inject.
Editoval romiix.org (23. 11. 2012 12:01)
- duskohu
- Člen | 778
neviem ci to nieje Off topic ale ako zaciaticnik by som uvital nieco taketo,
kedze stracam nejako prehlad:
https://forum.nette.org/…tre-a-modely
- Honza Marek
- Člen | 1664
Podle mě je to dost těžko pochopitelná a dost magická feature a jako takovou bych ji vůbec do frameworku nezařazoval.
- Je to takové programování v konfiguraci. Pokud přesně vím mechanizmus jakým to funguje, můžu některé třířádkové třídy napsat v neonu místo PHP.
- Není zřejmé na čem funguje konfigurace setup. Jestli na továrničce nebo na vytvářeném objektu.
- Nějaký kód stejně psát musím (ten interface).
<offtopic>
Ostatně soudím, že sekce factories by měla
být zničena. Neexistuje žádný rozdíl mezi továrničkou a službou, která
má metodu na továrničkování. </offtopic>
- Filip Procházka
- Moderator | 4668
To je řečeno tím, že nejprve ukážu, jak bych si ji napsal já a dále je řečeno, že stejnou třídu za mně vygeneruje Nette, ne?
- Patrik Votoček
- Člen | 2221
Honza Marek napsal(a):
- Je to takové programování v konfiguraci.
Ano Nette se stává o něco více deklarativní a zbavujeme se dalšího boilerplate (a toho se vždy rád zbavím). Imho nikdo a nic tě nenutí to používat (jenom pokud to používat budeš usnadníš si práci).
<offtopic>
Ostatně soudím, že sekce factories by měla být zničena. Neexistuje žádný rozdíl mezi továrničkou a službou, která má metodu na továrničkování.</offtopic>
Ten rozdíl je právě v tom generování třídy (resp. tak to vidím já).
- Michalek
- Člen | 211
Já do toho asi nemám co moc mluvit, ale když ten příklad (kompletní, na
konci) ze stránky zkopíruju do aktuálně staženého sandboxu z 2.1-dev, tak
to skončí
chybou Service 'nette.mail': Multiple services of type Nette\Mail\IMailer found: nette.mailer, mailer
Což buď jsem blbej já (zkoušel jsem to pro jistotu dvakrát), nebo je to záměr? :)
A za další, už týden se snažím správně pochopit
factories
a services
, v čemž by asi i tenhle
článek mohl pomoct, jenže slova
Tuhle továrničku si zaregistrujeme do DIC
uvozují příklad, kdy
se přidává do sekce services
a to je teda hodně moc matoucí :)
Proč se továrnička (i když to má v názvu) registruje do služeb a ne do
továrniček…
- enumag
- Člen | 2118
A už je to tady. :-(
@Michalek: Ten příklad je špatný. Snažíme se vymyslet něco lepšího, ale to bude chvíli trvat. Faktem je, že pro mailer nemáš vytvářet vlastní službu jelikož takovou už poskytuje samo Nette.
EDIT:
A ta druhá část se ti nezdá také oprávněně. Tohle je v podstatě ukázka toho jak bys to musel udělat dříve. Tj. továrnu si naprogramovat sám (to je ta třída MailingMessageFactory) a pak si ji zaregistrovat jako službu. Ten nový (preferovaný) způsob je potom níže, kde už to dáš přímo do sekce factories – to znamená že tu factory ty sám nepíšeš jako nějakou třídu, ale necháš Nette aby ji vyrobilo. To šlo používat i dříve, akorát takové továrny doteď nebyly injectovatelné, protože je Nette nevyrábělo jako třídu, ale pouze jako metodu DI containeru.
Myslím, že tohle stačí jako názorný příklad, že jakékoli „jakto bylo dříve“ nebo cokoli podobného začátečníky jen zbytečně mate a bude pro ně nejlepší ten nový správný způsob uvést hned na začátku a cokoli dalšího neuvádět buď vůbec nebo pod velkým červeným nápisem „takhle ne, tohle je jen ukázka pro detailnější pochopení“.
EDIT2:
@HosipLan: Lepší téma zřejmě nikoho nenapadá, takže asi čekáme než @dg povolí komponenty jako príklad, je to tak? Ty e-maily bych tam nechal jen opravdu nerad, připadá mi to hodně matoucí.
Editoval enumag (23. 11. 2012 19:00)
- Filip Procházka
- Moderator | 4668
Michalek napsal(a):
Což buď jsem blbej já (zkoušel jsem to pro jistotu dvakrát), nebo je to záměr? :)
Nejsi, opravil jsem to.
Jenže slova
Tuhle továrničku si zaregistrujeme do DIC
uvozují příklad, kdy se přidává do sekceservices
a to je teda hodně moc matoucí :) Proč se továrnička (i když to má v názvu) registruje do služeb a ne do továrniček…
Továrnička samotná je službou – je tam od toho, aby vytvářela
opakovaně nové instance nečeho (emailu). Pokud ale chceš, aby to ale za tebe
řešilo Nette, tak použiješ factories
.
enumag napsal(a):
@HosipLan: Lepší téma zřejmě nikoho nenapadá, takže asi čekáme než @dg povolí komponenty jako príklad, je to tak? Ty e-maily bych tam nechal jen opravdu nerad, připadá mi to hodně matoucí.
Komponenty tam přidám na konec (až bude chvilka).
Začínám si myslet, že tohle téma prostě není pro začátečníky.
Nenapadá mě totiž jednoduchý způsob jak jim to vysvětlit, ani na co by to
oni mohli použít. Je dost těžké takovému člověku ospravednit „psaní
takové spousty kódu“, když by prostě mohl napsat
new Message
.
Budu tam asi muset sepsat nějaký disclaimer, že je to „power-user feature“ a k její potřebě dojde člověk až po delší době používání Nette/psaní aplikací.
Editoval HosipLan (23. 11. 2012 22:08)