Kde ideálně zapisovat do databáze

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

Zdravím,

mám jednu takovou ani né otázku jako spíš téma na diskusi.

Kde si myslíte, že je nejvhodnější místo pro zapsání do databáze, komponenta, presenter nebo ještě nějaká vlastní mezivrstva ?

Příklad, mám komponentu nějakého wizardu na míru, není to žádný univerzální wizard do kterého se nasypou formuláře a on je vykreslí, je to zkrátka takovej vylepšenej formulář a teď otázka, posílat si z komponenty přes nějakou vlastní onSuccess() metodu data zpátky do presenteru a tam je ukládat ? Nebo zapsat data v komponentě a zavolat onSuccess() jen třeba pro redirect v presenteru ? Nebo uložit v nějakém vlastním modelu a status operace poslat zpátky do komponenty a z té do presenteru ?

Vždy jsem si je poslal do presenteru a tam je uložil, protože jsem zastával myšlenku, že komponenta by měla sloužit pro nějakou obsluhu, ale ve finále by měl data zpracovávat presenter, jenže teď je tento insert proces tak rozsáhlý, že pokud bych tam udělal další dvě komponenty, tak bude mít tak milion řádků a to samozřejmě nikdo nemá rád.

Budu rád za vaše názory a poznatky :) Díky

iNviNho
Člen | 352
+
+4
-

Neviem, či presne a správne poradím, respektíve či pomôže môj názor, ale stotožňujem sa akosi názoru, že čím menej bude vecí v presenteri, tým viac bude aplikácia prehľadnejšia.

Napríklad ak chcem vykresliť formulár pre faktúry Invoice
Požiadam InvoiceFormFactory (alebo si to niekto nazve InvoiceForm, alebo InvoiceFactory) o vykreslenie formulára.
V tomto factory následne robím celú logiku, čo sa má stať v prípade odoslanie formulára. Tento formfactory si vyžiadava služby ako napr InvoiceService, tak aby dokázal vložiť Invoice do DB, vyžiadava si LogService, tak aby dokázal zalogovať akciu, vyžiadava Kdyby/Translation, aby dokázal napr. preložiť form a celú logiku formulára vždy viem kde hľadať.

Ak by som tieto akcie robil v presenteri (čo som kedysi robil), tak som mal presenter, ktorý mal 1000 riadkov a to ti garantujem, že nechceš :D

btw. a napadá ma vec, že ak by si onSucess robil teda v presenteri, tak si budeš vyžiadavať služby, ktoré neslúžia presenteru, ale jeho komponente, čiže sa svojím spôsobom môže porušiť nepísané pravidlo single responsibility

btw2. a ešte ma napadá teda, že ja konkrétne už SQL, alebo DQL(Dcotrine Query Language) dotazy mám až v InvoiceRepository. ˇVšetky repozitáre pracujú s DB, ale nemajú nejakú logiku. Logika a riadenie, čo sa stane pri vkladaní si rieši InvoiceService. Pri vkladaní to ide nejako takto: InvoiceFormFactory → InvoiceService → InvoiceRepository :) A pri žiadaní o data to ide presne opačne

Editoval iNviNho (20. 10. 2016 23:27)

jiri.pudil
Nette Blogger | 1028
+
+3
-

Přikláněl bych se k „Nebo zapsat data v komponentě a zavolat onSuccess() jen třeba pro redirect v presenteru ?“

Cokoliv, co je zodpovědnost komponenty, nemůže záviset na presenteru z důvodů více či méně akademických (oddělení zodpovědnosti – viz co píše @iNviNho; přinejmenším výrazně omezuješ znovupoužitelnost komponenty; pravděpodobně se ti začne duplikovat kód; atd.) i velmi pragmatických (někdy na to někde zapomeneš a rázem máš rozbitou aplikaci a ani si toho nemusíš hned všimnout).

Komponenty jsou stejně jako presenter součástí P v MVP, takže je legitimní dělat v nich cokoliv, co bys udělal v presenteru. Jejich síla je v tom, že ti navíc umožňují kód logicky rozdělovat a skládat. Já chápu komponentu jako jednotku

  • ucelenou, nezávislou: má a zapouzdřuje celou svoji jasně danou zodpovědnost;
  • předvídatelnou: jaksi podvědomě od formulářové komponenty očekávám, že data namapuje na doménu a uloží sama, a že to tedy už nemusím řešit já coby její uživatel;
  • znovupoužitelnou: mám rád plug-and-play komponenty, které v presenteru jen jednoduše vytvořím a nastavím to nezbytné minimum věcí, které se můžou na různých místech lišit, jako třeba kam přesměrovat nebo jakou vypsat flash message. A takhle si z komponent poskládám klidně celou stránku; presenter je pak krásně minimalistický.
Eda
Backer | 220
+
+3
-

Jak už psali kluci, určitě to nedělej v presenteru. Presenter by měl být pokud možno co nejmenší a nejčistší.

Ideální přístup je mít samotné ukládání někde v Repository / Mapperu, ten je vyžádán Servicou a servisa je vyžádána v komponentě. Tím zaručíš oddělení zodpovědností, udržitelnost, rozšiřitelnost a vhodnou modulárnost aplikace.

Další možný přístup je využít třeba kdyby events, pokud ta provázanost signál komponenty – navazující akce není tak silná (takto se dá hezky řešit třeba logování, ať se jím nešpiní výkonný kód byznys logiky).

Editoval Eda (21. 10. 2016 12:12)

kleinpetr
Člen | 480
+
0
-

Díky moc za vaše odpovědi :) Určitě to zní logicky, je tedy pravda, že například různé formFactories jsem používal jen pro vrácení čistého formu a metodu onSuccess jsem opět řešil v presenteru, ale pak právě vzniká presenter s milionem kódu.

Moje zamyšlení totiž vzniklo na tom, že používám nějaký, jak vy říkáte Repository, který dědí od nějakého obecného Repository, který je napojený na DB a v jednotlivých modelech pak jen měním $tableName; Takže tento model umí komunikovat s danou tabulkou přes základní funkce jako findAll() apod. Ale nechtěl jsem do tohoto modelu přidávat něco jako pulic function insertData($values){...} a v té funkci pak různě skládat $values, protože není zřejmé co proměnná $values obsahuje a není to obecná funkce. Ale jak píšete, pokud je to hodně kódu navíc, tak je vhodné udělat ještě mezi službu, která bude prostředníkem těchto dvou :)

Díky.

Editoval kleinpetr (21. 10. 2016 14:47)

kleinpetr
Člen | 480
+
0
-

@iNviNho

Vytvořil jsem toto téma, které je vlastně spojené s tím co jsi psal o továrně, pokud to používáš možná bys mi mohl poradit :)

Editoval kleinpetr (3. 11. 2016 14:27)