Zamyšlení nad zakomponováním Doctrine 2 do Nette
- Jan Endel
- Člen | 1016
Zdravím,
používám HosipLanův sandbox
Nette+D2 mám takové zamyšlení, které pramení z toho, že se mi
nelíbí volat přímo entityManager z presenteru, čili bych chtěl to celé
nějak zapouzdřit, trošku jsem si ještě ten sandBox rozdělal a pro každou
entitu mám vytvořenou service a repository. Repository se stará
o získávání dat. Mám něco ve smyslu BaseRepository ve které právě
provádím to zapouzdření, plus odchytávání nějakých provozních
vyjímek. Zároven mám i základní service, která má api nějaké
takovéto:
$service->save($entity);
$service->detele($id);
...
přemýšlím správným způsobem nebo je volání entityManageru v presenterech košér, vytvářím ted projekt, na kterém bude spolupracovat větší množství programátorů, tak bych zase nechtěl vytvořit nějaký velký magický black box.
Děkuju za názory.
- Nox
- Člen | 378
Taky zdravím
- Vůbec nevidím že by volání EM* z presenteru bylo nějak zmíněné nebo dokonce doporučené v Sandboxu…
- Podle mě to skutečně není dobrý nápad, presenter by o EM neměl vědět
- Ale nemyslím si, že bys potřeboval duplikovat repository… stačí pracovat s ObjectRepository interfacem a pokud bys potřeboval vyměnit, nepotřebuje wrapper, stačí se podřídit kontraktu (interface)
- Zbytek v service (i když to slovo se mi vůbec nelíbí), prostě objektech co řeší business úkony
- Save() a delete() metody mi ale vůbec nevoní, to už je pro service dost low-level a naznačuje že by jí měly být dodaná už nějak zpracovaná data…
*) Silně doporučuji nepracovat s „EM“, ale s „OM“, tedy
ObjectManagerem, což není class ale interface, stejně tak v ostatních
případech.
Tohle mají mimo jiné kluci doctrinští fakt vychytané, jeden menší wip
projekt jsem převáděl mysql ⇒ mongo asi jen 10 minut
Editoval Nox (3. 10. 2011 7:48)
- Patrik Votoček
- Člen | 2221
Na totot téma jsem napsal ne jeden článek. Nehledě na to že to je otázka, která mě trápí (dnes už spíš trápila) neustále. Po skončení WebExpa jsme s HosipLan-em daly hlavy dohromady a vymysleli jak na to. Brzy by se řešení mělo objevit jak v Nella Frameworku tak v Kdyby.
Nox napsal(a):
Save() a delete() metody mi ale vůbec nevoní, to už je pro repository dost low-level a naznačuje že by jí měly být dodaná už nějak zpracovaná data…
Je ale nemá v Repository nýbrž v service kam dle mého imho patří. Nicméně souhlasím že tyto metody by měly pracovat s entitou a né „surovými“ daty.
*) Silně doporučuji nepracovat s „EM“, ale s „OM“, tedy ObjectManagerem, což není class ale interface, stejně tak v ostatních případech.
Naprosto souhlasím ale je s tím celkem prácička… :-)
Tohle mají mimo jiné kluci doctrinští fakt vychytané, jeden menší wip projekt jsem převáděl mysql ⇒ mongo asi jen 10 minut
Můžu potvrdit (i když mám zkušenost opačného převodu – přehodnocení situace).
- Nox
- Člen | 378
Je ale nemá v Repository nýbrž v service kam dle mého imho patří. Nicméně souhlasím že tyto metody by měly pracovat s entitou a né „surovými“ daty.
Omlouvám se, mělo tam být „service“ a ne „repository“ (opravil jsem)
Myslel jsem tím to, že pokud by service měla veřejnou metodu (pilec psal o API, takže asi měla být) „save“, pak by service předpokládala, že jí bude dodána entita k uložení. Tudíž na ní asi byly vykonány nějaké úpravy. Asi člověk nevolá jednu service aby pak entitu pouze uložil přes jinou (nebo jedna service nepoužívá druhou jen k uložení), takže by asi byla upravená přímo presenterem a to není ta čistá cesta … takže imho save ano, ale protected
- Jan Endel
- Člen | 1016
Patrik Votoček napsal(a):
Ty články jsem při googlení četl a dost jsem se inspiroval.
…
Nehledě na to že to je otázka, která mě trápí (dnes už spíš trápila) neustále. Po skončení WebExpa
jsme s HosipLan-em daly hlavy dohromady a vymysleli jak na to. Brzy by se řešení mělo objevit jak v Nella >Frameworku tak v Kdyby.
a dá už se říct alepoň rámcově, nechci termín, kdy to krásné voňavé řešení uvolníte? (týden, měsíc, příští pětiletka)
…
Je ale nemá v Repository nýbrž v service kam dle mého imho patří. Nicméně souhlasím že tyto metody > by měly pracovat s entitou a né „surovými“ daty.
ale tak vezměmež normální funkcionalitu:
public function actionDelete($id)
{
$this->context->service->delete($id);
}
není zbytečná režije ještě z databáze tahat konkrétně tu entitu? Za předpokladu, že mám nastavené triggery on delete
Naprosto souhlasím ale je s tím celkem prácička… :-)
To si musím dostudovat :-)
Editoval pilec (3. 10. 2011 11:09)
- Filip Procházka
- Moderator | 4668
Během dneška nebo zítřka dodělám ACL a pak pushnu svoji implementaci.
- mkoubik
- Člen | 728
ale tak vezměmež normální funkcionalitu:
public function actionDelete($id) { $this->context->service->delete($id); }
není zbytečná režije ještě z databáze tahat konkrétně tu entitu? Za předpokladu, že mám nastavené triggery on delete
Celkem běžně používám
public function deleteThing($id) // ne přímo v akci - bacha na CSRF
{
if (!$this->user->isAllowed(..., ...)) return; // nebo throw ...
$thing = $this->services->things->find($id);
if ($thing instanceof \Application\Model\Thing) {
$this->services->things->delete($thing)
}
}
Zas takovej overhead to není a výsledkem je konzistentnější API. Při návrhu rozhraní sevice vrstvy by ses neměl vůbec zatěžovat tím, kolik SQL dotazů se provede – to je několik vrstev pod tebou a dá se to optimalizovat/cacheovat pozdějc.
- Patrik Votoček
- Člen | 2221
Nox napsal(a):
Myslel jsem tím to, že pokud by service měla veřejnou metodu (pilec psal o API, takže asi měla být) „save“, pak by service předpokládala, že jí bude dodána entita k uložení. Tudíž na ní asi byly vykonány nějaké úpravy. … takže imho save ano, ale protected
Ano o tom jsem mluvil o veřejné metodě save. Co jiného by se mělo starat o uložení změněné / nové entity než service?
Asi člověk nevolá jednu service aby pak entitu pouze uložil přes jinou (nebo jedna service nepoužívá druhou jen k uložení), takže by asi byla upravená přímo presenterem a to není ta čistá cesta
Tohle jsem nepobral :-) a to jsem to četl 5× :-D
- Filip Procházka
- Moderator | 4668
Patrik Votoček napsal(a):
Nox napsal(a):
Asi člověk nevolá jednu service aby pak entitu pouze uložil přes jinou (nebo jedna service nepoužívá druhou jen k uložení), takže by asi byla upravená přímo presenterem a to není ta čistá cesta
Tohle jsem nepobral :-) a to jsem to četl 5× :-D
Asi nezná cascade={"persist"}
:)
- Nox
- Člen | 378
@Hosiplan: o cascade ses dozvěděl ode mě ;)
Zkusím jinak:
(pravda že teoreticky by to save($entity) mohla použít jiná service…pak
bych neměl pravdu; nebo jsem něco jednoduše nedomyslel…)
Myslel jsem to tak – ideálně by se mělo manipulovat s entitama v service. Pokud volám ->save($entity), tak ten objekt kde je tohle volané nejspíš ví o entitách a že byla entita změněná. Pokud ten objekt není service → nemá s entity co manipulovat a nemá vědět jestli byla změněná, nemá o existenci entit ani moc vědět, takže by to save nebylo dobrý (v případě teda že by to nepoužívala service na jiné service…což teď úplně nevim jestli by bylo ok)
Editoval Nox (3. 10. 2011 20:32)
- Filip Procházka
- Moderator | 4668
Nox napsal(a):
@Hosiplan: o cascade ses dozvěděl ode mě ;)
Ehm, člověk si nemůže pamatovat všechno :)
Zkusím jinak:
(pravda že teoreticky by to save($entity) mohla použít jiná service…pak bych neměl pravdu; nebo jsem něco jednoduše nedomyslel…)Myslel jsem to tak – ideálně by se mělo manipulovat s entitama v service.
Proč ne? Service je bussines vrstva a to nejsou jenom validace.
Pokud volám ->save($entity), tak ten objekt kde je tohle volané nejspíš ví o entitách a že byla entita změněná. Pokud ten objekt není service → nemá s entity co manipulovat a nemá vědět jestli byla změněná, nemá o existenci entit ani moc vědět, takže by to save nebylo dobrý
Není to jedno? Tříd můžeš mít hromadu a pokud máš persistenci
vyřešenou (řeší ji Doctrine), tak všechno mezi repozitářem a presenterem
je service vrstva. A někde to save
volat musíš.
(v případě teda že by to nepoužívala service na jiné service…což teď úplně nevim jestli by bylo ok)
Proč by ne? Když to dává smysl :)
Vůbec nevidím že by volání EM* z presenteru bylo nějak zmíněné nebo dokonce doporučené v Sandboxu…
Vůbec jsem to neměl potřebu řešit, chtěl jsem jenom pokrýt konfiguraci Doctrine. Entity si člověk může dodělat podle návodu (což by měl). Navíc k sandboxu je článek, sice jsem to v něm nezmínil, ale nechtěl jsem to tam opisovat z komentářů.
Podle mě to skutečně není dobrý nápad, presenter by o EM neměl vědět
Sranda je, že všechny tutorialy u Symfony pracují rovnou s EM.
Ale nemyslím si, že bys potřeboval duplikovat repository… stačí pracovat s ObjectRepository interfacem a pokud bys potřeboval vyměnit, nepotřebuje wrapper, stačí se podřídit kontraktu (interface)
Zbytek v service (i když to slovo se mi vůbec nelíbí), prostě objektech co řeší business úkony
Save() a delete() metody mi ale vůbec nevoní, to už je pro service dost low-level a naznačuje že by jí měly být dodaná už nějak zpracovaná data…
Service není jedna třída, je to vrstva. Presenter by mohl (a měl) klidně pracovat se service třídou i s repozitářem/entityManagerem (nebo s vrstvou nad nimi).
Silně doporučuji nepracovat s „EM“
To já taky, je to takové tfuj. EM toho umí moc a do teď jsem předával
vždycky repozitář aby třídy nemohly „všechno“. Ten repozitář měl
navíc metody save
a delete
. Jenomže to pak není
repozitář, ale „Data-Access-Object“. No jdu dělat na tom ACL, abych se
mohl podělit :)
- Patrik Votoček
- Člen | 2221
HosipLan napsal(a):
Pokud volám ->save($entity), tak ten objekt kde je tohle volané nejspíš ví o entitách a že byla entita změněná. Pokud ten objekt není service → nemá s entity co manipulovat a nemá vědět jestli byla změněná, nemá o existenci entit ani moc vědět, takže by to save nebylo dobrý
Není to jedno? Tříd můžeš mít hromadu a pokud máš persistenci vyřešenou (řeší ji Doctrine), tak všechno mezi repozitářem a presenterem je service vrstva. A někde to
save
volat musíš.
Tak tak něco tu entitu prostě uložit musí.
Podle mě to skutečně není dobrý nápad, presenter by o EM neměl vědět
Sranda je, že všechny tutorialy u Symfony pracují rovnou s EM.
A né jenom tutoriály :-). Resp. hledal jsem nějaké využití / implementaci service vrstvy pro symfony 2 a nenašel jsem.