Může mít fasáda závislost na jiné fasádě + představuje DB tabulka jednu třídu repository?
- freely111
- Člen | 41
Zdravím, předem se omlouvám, že to sem možná nepatří. Mám spíš dotazy na čistší psaní aplikace.
1. dotaz – Může mít fasáda závislost na jiné fasáde?
Mám dva modely:
App\Model\User (model pro práci s uživateli)
App\Model\Booking (model pro práci s rezervacemi)
Model User obsahuje fasádu UserFacade, které má závislosti na svých
repositářích.
Model Booking obsahuje fasádu BookingFacade, která má opět závislost na
svých repositářích.
Při zpracování objednávky po odeslání formuláře, potřebuji založit
zákazníka a objednávku.
UserFacade tedy obsahuje metodu
UserFacade->createCustomer($customerValues).
BookingFacade obsahuje metodu Booking->createOrder($orderValues).
Obě výše uvedené metody potřebuji volat za sebou, ale potřebuji je dát do transakce nette database a asi by nebylo vhodné toto řešit na straně presenteru, proto bych nejraději chtěl, aby BookingFacade třída měla závislost přes konstruktor UserFacade a provedlo se to v bloku transakce celé v té BookingFacade.
Např. v presenteru tedy zavolám:
BookingFacade->createOrder($customerValues, $orderValues).
A uvnitř této metody by byl blok transakce vč. zachycení vyjímek a uvnitř toho by se volalo $userFacade->createCustomer(customerValues) a potom $this->repositoryOrder->createOrder(orderValues).
Dalo by se to podle Vás považovat za správný návrh s využíváním nette database, že jedna fasáda má závislost na jiné?
2. dotaz – co tabulka v mysql, to repository třída?
Mám dvě tabulky, např.:
product (id, code, active, … hlavní parametry)
product_lang (id, lang_id, product_id, name, …parametry pro překlady toho
produktu)
Je i v tomto případě správné ve spolupráci s nette database dodržovat co tabulka to repository třída, která např. dědí od nějaké třídy s crud operacemi na tu tabulku? Např. by každá repository třída dědila od třídy Table, kterou jsem viděl v projektu Addons.Nette.
Předem moc díky za vaše názory k nakopnutí čistším směrem psaní app. Neustále mě hlodá, že to píšu totálně špatně a nepřibližuji se k čistšímu návrhu aplikace ve spolupráci s nette database.
- leninzprahy
- Člen | 150
ad 1.
Vzájemné závislosti fasád bych se vyhnul. Zvážil bych spíš vytvoření
OrderFacade
která by řešila co potřebuješ. V té fasádě by
dle mého názoru mělo být co nejméně logiky, pokud je tam nějaká
potřeba, snažil bych se jí přesunout do nějaké samostatné třídy, která
by mohla být případně využita i v jiné fasádě.
ad 2.
Zrovna v tomto případě bych asi použil jen jeden repositář, jehož metody
by vracely vše potřebné na základě jazyka. Ale je to pouze takový dojem,
záleželo by asi na konkrétním použití.
- freely111
- Člen | 41
leninzprahy napsal(a):
ad 1.
Vzájemné závislosti fasád bych se vyhnul. Zvážil bych spíš vytvořeníOrderFacade
která by řešila co potřebuješ. V té fasádě by dle mého názoru mělo být co nejméně logiky, pokud je tam nějaká potřeba, snažil bych se jí přesunout do nějaké samostatné třídy, která by mohla být případně využita i v jiné fasádě.ad 2.
Zrovna v tomto případě bych asi použil jen jeden repositář, jehož metody by vracely vše potřebné na základě jazyka. Ale je to pouze takový dojem, záleželo by asi na konkrétním použití.
Díky za reakci. Nějak tak jsem taky nad tím přemýšlel, že bych si vytvořil přímo pro to třídu. Např. se jménem OrderFacade nebo OrderService. Ale co bys do ní poslal jako závislosti? Konkrétní repository obou modelů resp. UserRepository a OrderRepository? Nebo fasády obou modelů resp. UserFacade a BookingFacade? To asi ty repository, že? Jenomže já bych potřeboval volat nejlépe tu nevyšší metodu createCustomer co je ve fasádě UserFacade.
A nebo mi pořád jakoby připadá, že bych potřeboval nejlépe ještě jednu vrstvu mezi vrstvami Facade a vrstvami Repository třídami a tu novou mezivrstvu resp. další mezifásádu bych si předával mezi modely. Tím bych docílil i toho, že fasády budou velmi tenké a jenom by delegovaly činnosti dál a to by dělal v podstatě i presenter, tak se to se mi nezdá.
Asi lepší jak píšeš ty, že bych si udělal mezifasádu se jménem OrderFacade nebo OrderService jenom na to konkrétní co potřebuji řešit, jenže já bych v ní nejlépe chtěl volat tu nejvyšší vrstvu modelu User resp. UserFacade->createCustomer, protože co kdyby uvnitř v budoucnu vzniklo nějaké další rozdělení v té metodě UserFacade->createCustomer, tak se mi automaticky promítne všude, kde ji volám a to by bylo asi dobré, kdy se to promítlo všude. Kdežto, když do té nové třídy co bych si vytvořil pro tu operaci na vytvoření zákazníka a objednávky šoupnu závislost UserRepository místo UserFacade, tak při změně UserFacade->createCustomer se mi to tam nepromítne :(
- Jiří Nápravník
- Člen | 710
ad 1) Co si představuješ pod pojmem fasáda? Podle návrhového vzoru by měla být opravdu co nejméně logiky a delegovat to na další třídy. Nicméně já používám název Facade pro hlavní modelové třídy, kde v podstatě zpracovávám vše kolem databází. A tak třeba u ArticleFacade mám i závislost na PhotoFacade, AdministratorFacade, která mi pak obstarává věci ohledně fotek, administrátorů apod u článků.
- freely111
- Člen | 41
Jiří Nápravník napsal(a):
ad 1) Co si představuješ pod pojmem fasáda? Podle návrhového vzoru by měla být opravdu co nejméně logiky a delegovat to na další třídy. Nicméně já používám název Facade pro hlavní modelové třídy, kde v podstatě zpracovávám vše kolem databází. A tak třeba u ArticleFacade mám i závislost na PhotoFacade, AdministratorFacade, která mi pak obstarává věci ohledně fotek, administrátorů apod u článků.
V podstatě si fásádu představuji asi jako ty. V aplikaci mám několik
modelů: App\Model\User App\Model\Booking, potom třeba App\Model\Acl atd.
A každý model má nejvyšší třídu s názvem Facade a presenter či
různé presentery komunikují pouze s těmito modelovými fásádami (na netu
se o tom píše jako servisní fásády, pokud jsem to pochopil správně).
Je to tak správně? Pokud ano, tak nevím zda není špatné řešení, aby jedna fasáda měla závislost na druhé.
- Jiří Nápravník
- Člen | 710
Tak to asi chápeme obdobně. Já tedy takhle závsilosti mezi sebou mám. Například v té ArticleFacade potřebuji získat jenom fotku podle id, ano mohu si předat jen repository, resp. z nej si to vytáhnout. Ale raději si to vytáhnu přes tu PhotoFacade, dle mě na fotky má sahat ta PhotoFacade, a pokud to nekdy potrebuji upravit, upravim na jednom miste. Asi to neni akademicky ciste, ale zatim mi to tak vyhovuje…
Nicmene cetl jsem nejaky doporuceni, hlavne psat a neresit porad dokola archutekturu, protoze pak se to furt predelava a nikdy nebudes spokojen, ono se casem vyvine co bude sedet nejlepe
- leninzprahy
- Člen | 150
freely111 napsal(a):
Díky za reakci. Nějak tak jsem taky nad tím přemýšlel, že bych si vytvořil přímo pro to třídu. Např. se jménem OrderFacade nebo OrderService. Ale co bys do ní poslal jako závislosti? Konkrétní repository obou modelů resp. UserRepository a OrderRepository? Nebo fasády obou modelů resp. UserFacade a BookingFacade? To asi ty repository, že? Jenomže já bych potřeboval volat nejlépe tu nevyšší metodu createCustomer co je ve fasádě UserFacade.
Já bych do té OrderFacade
dal jen repositáře, a funkčnost,
co je v UserFacade::createCustomer
přesunul do nějaké
CustomerService::createCustomer
kterou by ta fasáda využívala.
Stejnou službu pak můžeš využívat i v té
UserFacade::createCustomer
, což jen zavolá
CustomerService::createCustomer
, prostě ta fasáda bude jen volat
metody služeb a repositářů.
A nebo mi pořád jakoby připadá, že bych potřeboval nejlépe ještě jednu vrstvu mezi vrstvami Facade a vrstvami Repository třídami a tu novou mezivrstvu resp. další mezifásádu bych si předával mezi modely. Tím bych docílil i toho, že fasády budou velmi tenké a jenom by delegovaly činnosti dál a to by dělal v podstatě i presenter, tak se to se mi nezdá.
Asi lepší jak píšeš ty, že bych si udělal mezifasádu se jménem OrderFacade nebo OrderService jenom na to konkrétní co potřebuji řešit, jenže já bych v ní nejlépe chtěl volat tu nejvyšší vrstvu modelu User resp. UserFacade->createCustomer, protože co kdyby uvnitř v budoucnu vzniklo nějaké další rozdělení v té metodě UserFacade->createCustomer, tak se mi automaticky promítne všude, kde ji volám a to by bylo asi dobré, kdy se to promítlo všude. Kdežto, když do té nové třídy co bych si vytvořil pro tu operaci na vytvoření zákazníka a objednávky šoupnu závislost UserRepository místo UserFacade, tak při změně UserFacade->createCustomer se mi to tam nepromítne :(
Zkusil bych se na to podívat tak, že ta fasáda nemusí být ke každému modelu, ale spíš pro určité případy užití, nebo jejich skupinu.
Doporučuji přečíst si článek https://www.zdrojak.cz/…-doctrine-2/ od Vaška Purcharta, je sice o Doctrine, ale pokud uvažuješ nad architekturou tímto směrem, stejně k ní nejspíš dojdeš :)
- freely111
- Člen | 41
leninzprahy napsal(a):
freely111 napsal(a):
Díky za reakci. Nějak tak jsem taky nad tím přemýšlel, že bych si vytvořil přímo pro to třídu. Např. se jménem OrderFacade nebo OrderService. Ale co bys do ní poslal jako závislosti? Konkrétní repository obou modelů resp. UserRepository a OrderRepository? Nebo fasády obou modelů resp. UserFacade a BookingFacade? To asi ty repository, že? Jenomže já bych potřeboval volat nejlépe tu nevyšší metodu createCustomer co je ve fasádě UserFacade.
Já bych do té
OrderFacade
dal jen repositáře, a funkčnost, co je vUserFacade::createCustomer
přesunul do nějakéCustomerService::createCustomer
kterou by ta fasáda využívala. Stejnou službu pak můžeš využívat i v téUserFacade::createCustomer
, což jen zavoláCustomerService::createCustomer
, prostě ta fasáda bude jen volat metody služeb a repositářů.A nebo mi pořád jakoby připadá, že bych potřeboval nejlépe ještě jednu vrstvu mezi vrstvami Facade a vrstvami Repository třídami a tu novou mezivrstvu resp. další mezifásádu bych si předával mezi modely. Tím bych docílil i toho, že fasády budou velmi tenké a jenom by delegovaly činnosti dál a to by dělal v podstatě i presenter, tak se to se mi nezdá.
Asi lepší jak píšeš ty, že bych si udělal mezifasádu se jménem OrderFacade nebo OrderService jenom na to konkrétní co potřebuji řešit, jenže já bych v ní nejlépe chtěl volat tu nejvyšší vrstvu modelu User resp. UserFacade->createCustomer, protože co kdyby uvnitř v budoucnu vzniklo nějaké další rozdělení v té metodě UserFacade->createCustomer, tak se mi automaticky promítne všude, kde ji volám a to by bylo asi dobré, kdy se to promítlo všude. Kdežto, když do té nové třídy co bych si vytvořil pro tu operaci na vytvoření zákazníka a objednávky šoupnu závislost UserRepository místo UserFacade, tak při změně UserFacade->createCustomer se mi to tam nepromítne :(
Zkusil bych se na to podívat tak, že ta fasáda nemusí být ke každému modelu, ale spíš pro určité případy užití, nebo jejich skupinu.
Doporučuji přečíst si článek https://www.zdrojak.cz/…-doctrine-2/ od Vaška Purcharta, je sice o Doctrine, ale pokud uvažuješ nad architekturou tímto směrem, stejně k ní nejspíš dojdeš :)
Díky. Ten článek jsem už jsem četl, i když s doctrine nedělám. Prozkoumal jsem i ten článek 5 vrstev modelu. Od té doby, co jsem tyto články četl, jsem se právě totálně zasekl a neustále to svoje přepisuji, když už jsem se rozhodl přejít na nette a stejně z toho nemohu spát, tak už jsem zde musel položit dotaz.
Momentálně mě asi napadají 2 cesty, které bych mohl zvolit:
1:
Budu mít třídy repository pro konkrétní model, které bude obalovat jedna
nejvyšší třída Fásada toho modelu. Budu dělat i to, že jedna fasáda
bude mít závislost na jiné, tak jako psal „Jiří Nápravník“. (toto by
se mi asi líbilo, pokud by to nebylo nějaké šílené porušení
architektury)
Jenomže u toho řešení se mi nezdá to zvolené názvosloví Facade. Po přečtení několika diskusí atd., myslím, že i této: http://stackoverflow.com/…7ade-similar
mám v hlavě to, že fasáda by měla mít metody velmi tenké a pouze delegovat operace na další třídy a neprovádět žádnou aplikační logiku. Proto si říkám, že bych do metody ve fasádě vůbec neměl tahat nějaké spojení s databází, abych vytvořil blok na transakci a udělal v ní ve finále commit či rollback, sice nad operacemi, které deleguji dál, ale i tak tam bude ta transakce, která ten blok bude obalovat. Pořád si prostě říkám, že to tam asi do té fasády nepatří.
A díky tomu si začínám myslet, jestli tuto vrstvu nepojmenovat slovem „Service“ místo Facade, že by to více odpovídalo tomuto řešení, že se v té vrstvě bude provádět např. blok transakce.
A ten název Facade si ponechat do budoucna, kdybych nad tím celým konkrétním modelem resp. nad třídou Service chtěl vytvořit další vrstvu a ta už by se jmenovala Facade, které by už vážně jen delegovala činnost na různé Service modelové třídy, které by pracovaly s různými repository a vzájemně by ty Servisy měly i závislosti podle potřeby.
2.
To by bylo asi jak píšeš ty.
Budu mít nejvyšší vrstvu s názvem Facade pro každý model, která by
pouze delegovala volaní na různé Service třídy, které by prováděly
operace nad konkrétními repository. Jenomže to těch Service tříd bude
v podstatě stejně jako Repository tříd + další Service třídy, které
budou obalovat různé repository, když budu potřebovat pro nějakou operaci
jak repository z modelu A a další ze stejného modelu apod.
A nebo Fasáda bude delegovat na repository a i na konkrétní service třídy, které vytvořím pouze, když se to hodí a když to budu potřebovat, např. když budu potřebovat operovat nad repository A, tak i repository B, např. z jiného modelu a díky tomu vytvořím Service třídu ABService, která s těmi repository bude operovat.
Tak a teď se mi zdá, že v tom mám hokej snad ještě větší… :/
Asi bych snad zůstal u toho řešení jak psal „Jiří Nápravník“, jen
mi připadá, že by se ty třídy měly spíše jmenovat Service, které budou
mít i nějakou tu logiku + budou i někdy tyto service třídy na sobě
závislé z jiných modelů.
Uff…
- Jiří Nápravník
- Člen | 710
Ten zmatek Service Facade jsem taky resil. Ale pak jsem dosel k tomu, ze v mem pripade by facade bylo casto to, ze vezme co dostane a posle to na service, coz je nesmysl… Zkratka taky jsem moc nepochopil, co by melo byt v Service a co ve Facade
- freely111
- Člen | 41
Jiří Nápravník napsal(a):
Ten zmatek Service Facade jsem taky resil. Ale pak jsem dosel k tomu, ze v mem pripade by facade bylo casto to, ze vezme co dostane a posle to na service, coz je nesmysl… Zkratka taky jsem moc nepochopil, co by melo byt v Service a co ve Facade
No přesně, pokud jsem tě pochopil. Kdybych měl Facade nejvyšší vrstvu co bude komunikovat s presenterem a potom ještě Service jako podvrstvu té fasády pro komunikaci se všemi repository toho konkrétního modelu, kterou bych právě i předával jako závislost jiné Service z jiného modelu, tak by ve většině případech nejvyšší Facade vrstva jednořádkově delegovala metody na Service podvrstvu toho modelu.
A tak nevím zda to tak má dělat, že bych měl hlavní Facade třídu a hlavní Service třídu pro každý model a nebo si dělat jenom pro určité případy takové menší Service třídy jen na to co se má udělat, když se to zrovna pomocí takové mini Service třídy hodí a nebo se na to úplně vykašlat a používat jenom ty fasády resp. třídy s názvem Facade, které budou operovat nad repository konkrétního modelu a případně i s ostatními fasádami ostatních modelů a tím budou mít na sobě podle potřeby závislosti :/
- cubic
- Člen | 45
Zkus zapomenout na facade a service, pojmenuj si tu třídu pro začátek
jakkoliv, udělej si tam závislostí, kolik potřebuješ a jen začni psát.
Pokud vidíš, že se dá něco z toho logicky oddělit, refaktoruj to do nové
třídy. Vytvářej si nové třídy, až když je opravdu potřebuješ. Hlavně
je blbost vytvořit si na začátku x fasád, jen proto, že jsi to četl
v nějakém chytrém článku. Akorát budeš mít ukrutně dlouhou třídu
(aspoň mně ten název vždycky akorát sváděl k tomu psát třídu, která
všechno jakoby zastřeší), v ní veškerou logiku a stejně nebudeš
vědět, co s tím. Všechno bude mít závislost na všem a ty jen budeš
neustále přemýšlet, jak to přepsat, aby se ti to líbilo.
Tohle teoretizování stejně funguje možná u malého projektu, kde máš
3 tabulky a 3 třídy o pár metodách, ale jakmile máš začít psát něco
většího, tak se zasekneš.
Lepší začít klidně špatně a upravit to, až když víš a vidíš jak.
Klidně po malých krůčcích. Nemá ale smysl přečíst nějaký článek a
vzít z něj všechno jako dogma. Taky jsem si tím prošel.
Editoval cubic (30. 10. 2015 22:00)
- Jiří Nápravník
- Člen | 710
Přesne jak píše @cubic začni psát a neřeš jména, já to taky takhle řešil doprředu a furt něco přepisoval, pak se mi nelíbil název Facade a přepsal jsem to na Service. Atd. Uznáš asi sám, že ve fasádě jednořádkově přeposlat na service je celkem nesmysl…
Já to zkrátka nazvu Facade a píšu tam postupně vše, je pravda, že někdy hrozí jak píše cubic to, že to je moc dlouhá třída. Ale jak uvidíš nějaký celek, tak ho dáš ven. Například ty fotky, měl jsem tam taky vše, pak jsem si všiml, že samotné ořezy apod. by bylo vhodné oddělit, protože to je něco trochu jiného tak se udělal PhotoFileService, kde se stará o fyzické velikosti fotek.