Zamyšlení nad zakomponováním Doctrine 2 do Nette

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

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
+
0
-

Taky zdravím

  1. Vůbec nevidím že by volání EM* z presenteru bylo nějak zmíněné nebo dokonce doporučené v Sandboxu…
  2. Podle mě to skutečně není dobrý nápad, presenter by o EM neměl vědět
  3. 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)
  4. Zbytek v service (i když to slovo se mi vůbec nelíbí), prostě objektech co řeší business úkony
  5. 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
+
0
-

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
+
0
-

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
+
0
-

Patrik Votoček napsal(a):

Na totot téma jsem napsal ne jeden článek.

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
+
0
-

Během dneška nebo zítřka dodělám ACL a pak pushnu svoji implementaci.

mkoubik
Člen | 728
+
0
-

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
+
0
-

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
+
0
-

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
+
0
-

@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
+
0
-

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
+
0
-

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.