Proč nemá být validace v modelu

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

Pokud model chápeme jako třídu umožňující přístup do databáze, je na tom kategoricky podobně jako mailer. Model data uloží, mailer je někam odešle.

Obě tyto kategoricky shodné třídy by data měly validovat z technického hlediska. Model musí obdržet hodnoty pro všechny povinné sloupce, mailer zase musí dostat platnou adresu. Je dobré, když je rozsah technické validace co největší, ale jedná se stále o validaci technickou.

Logická validace dat musí být prováděna v presenteru. Jen aplikační vrstva může rozhodnout, jestli je skutečně adekvántí mail odesílat, popř. data ukládat.

Ať mi nikdo netvrdí, že validace má být v modelu. Je to hloupá polopravda.

Editoval pmg (13. 8. 2009 12:13)

DocX
Člen | 154
+
0
-

Samozřejmě jde o názor a vyložení pojmu model ;)

Jakub Šulák
Člen | 222
+
0
-

Je to o výkladu, co je vlastně model.

Pokud budu mít bankovní aplikaci a v ní metodu sendMoney(amount, from, to).

Bude tato metoda vyžadovat (kromě dalších 1000 metod) volat vždy validaci MámPenízeNaÚčtu? a ExistujeÚčetPříjemce?
A to už není technická validace, ale součást bussiness modelu aplikace.
Proč?

Čistě prakticky:
Varianta A
Budu to mít skutečně v presenteru (tedy v nějakých prezenčních vrstvách jednotlivých aplikací-nemusí jít o jeden program).

Varianta B
Bude logický model – typicky takováto věc vytvořena jako uložná procedura na nějakém DB serveru.

A v tuto chvíli bych chtěl vědět, jakým způsobem by bylo možné hlídat, že všichni!!! ve svých prezenčních vrstvách (architekt aplikace na pobočce, programátor internetového bankovnictví, správce s právy změn na účtech) mají všechny validační parametry. Nemají? Průšvih!

Myslím si, že je to vidět lépe, vezmete-li si právě příklad z větších aplikací. V PHP těžko někdo bude dělat enterprise aplikaci, ale fakta platí pro oboje.

pmg
Člen | 372
+
0
-

Metoda sendMoney vykonává nějakou atomickou operaci nad databází a potřebuje, aby byly naplněny nějaké předpoklady. Ve všem bych se shodnul, ale potřebnou validaci bych podle své terminologie označil jako technickou, i když to v tomto případě není tolik intuitivní: stejně jako nemohu smazat řádek, který neexistuje, nemohu ani poslat peníze, které neexistují.

Použitá terminologie o technických a logických chybách vychází z předpokladu, že většina běžných tabulek vyžaduje jen přístup typu CRUD, přičemž model zaštiťuje práci s relacemi ap.

Uvědomil jsem si, že aby byly procedury v databázovém jazyce dobře použitelné, muselo by existoval lepší spojení s jazykem aplikačním. To, že ale takové spojení neexistuje, mě přinutilo začít o databázích uvažovat jako o hloupých skladištích dat, které dokážou rychle vykonávat určité operace. Skutečnou tvář má těmto hloupým skladištím dodat až aplikační vrstva reprezentovaná modelem.

Přestože je tento přístup špatný, jiná řešení jsou stěží použitelná. Dříve jsem zkoušel psát procedury přímo v SQL, bohužel jsem ale v jednom kuse narážel na problémy, neimplementované věci a měl jsem pocit, že programuji v Basicu. Výsledkem bylo, že jsem z PHP volal nějaký procedurální kód někde na databázi a žádný phpMyAdmin mi neumožnil s ním pohodlně pracovat. Abych pak mohl získat třeba chybový kód procedury, musel jsem ji volat přes multi_query, kterou zase nepodporovalo zrovna vycházející dibi. Je to dlouhá historie, která vedla k tomu, že jsem na takový způsob přístupu zcela rezignoval.

Konečným řešením těchto problému by nejspíš bylo, kdyby přímo v PHP existovalo rozšíření pro objektový přístup k databázím. Nevím, jestli se někdy dočkáme. Myslím, že nejpokrokovější je v tomto ohledu PgSQL. Bohužel vidím, že většině lidí je nějaká koncepce celkem lhostejná, pro ně je databáze jen tupý CRUD, ale však ano – MySQL také nic jiného neumí.

Abych to shrnul, vyvolal jsem určité nedorozumění, ale jinak se shodneme. A tím, že by validace neměla být v modelu, jsem myslel, že by neměla být výhradně v modelu. A pak samozřejmě záleží na tom, co se rozumí tím modelem. :-)

mancze
Člen | 58
+
0
-

Myslím, že to je spíše o postoji jednotlivce k tomu, co má model vlastně dělat. Já cítím model jako skutečně tupý obal nad databází, který mi právě umožní objektový přístup do ní. Kontrolovat by měl maximálně konzistenci dat, naplnění argumentů.

pmg napsal(a):

Metoda sendMoney vykonává nějakou atomickou operaci nad databází a potřebuje, aby byly naplněny nějaké předpoklady. Ve všem bych se shodnul, ale potřebnou validaci bych podle své terminologie označil jako technickou, i když to v tomto případě není tolik intuitivní: stejně jako nemohu smazat řádek, který neexistuje, nemohu ani poslat peníze, které neexistují.

A co když pak přijde požadavek, že účet se může zarývat do mínusu (což je mimochodem fakt)? Budete muset začít hrabat do modelu. Zřejmě přidáte novou metodu (případně přidáte přepínač k sendMoney), protože nemůžete upravit sendMoney – s tou se nějak v aplikaci manipuluje a vy nevíte jak. Když se toto párkrát zopakuje, budete mít X metod, které vlastně jen posílají peníze. Liší se jen v hloubce kontroly, kterou vykonávají. Myslím, že to vede (za pár let) k nepoužitelnému API modelů.

Přestože je tento přístup špatný, jiná řešení jsou stěží použitelná. Dříve jsem zkoušel psát procedury přímo v SQL, bohužel jsem ale v jednom kuse narážel na problémy, neimplementované věci a měl jsem pocit, že programuji v Basicu. Výsledkem bylo, že jsem z PHP volal nějaký procedurální kód někde na databázi a žádný phpMyAdmin mi neumožnil s ním pohodlně pracovat. Abych pak mohl získat třeba chybový kód procedury, musel jsem ji volat přes multi_query, kterou zase nepodporovalo zrovna vycházející dibi. Je to dlouhá historie, která vedla k tomu, že jsem na takový způsob přístupu zcela rezignoval.

Proto jsme si pro dibi napsali vlastní driver, který nám umožňuje toto volat (cca 200 řádků kódů s dokumentací). Jen procedury a funkce nám umožní využívat databáze naplno. Bez nich se to musí řešit v PHP a to není dobré, je to pomalé a náchylné k chybám.

Souhlasím, že můj postoj by mohl dělat trochu nepořádek u opravdu rozsáhlých aplikací. Vlastně poslední dobou si říkávám, že trojvrstvý MVC je sice fajn, ale příliš jednoduchý (což je i jeho pozitivum). Dokážu si velice dobře představit, že by se pro velkou aplikaci vyčlenil datový model a aplikační model (a pro controlery obdobně).

Editoval mancze (14. 8. 2009 11:05)

DocX
Člen | 154
+
0
-

Já osobně dělám model jako chytřejší ORM. Jednak mi umožní přistupovat k datům objektově, ale zárověň dokáže kontrolovat co s daty mohu dělat (například zmíněné sendMoney). Na druhou stranu autorizaci přenechávám controleru (presenteru), což by ve „správném modelu“ mělo být řešeno v databázi.
Proto by mě zajímalo jak třeba vy řešíte autorizaci (například uživatel může změnit heslo jen sobě, admin může změnit heslo komukoli)?

paranoiq
Člen | 392
+
0
-

já model, za tupý obal databáze rozhodně nepovažuji. model podle mě musí obsahovat veškerou logiku a to včetně validace dat a validace uživatelských práv. co naopak při užším pohledu model obsahovat nemusí je implementace úložiště (záměrně nepíšu databáze). pokud bych chtěl svoje chápání pojmu model nějak omezovat bylo by to spíše zespoda.

beru-li model jako skutečnou podstatu aplikace, její jádro, mozek, tak vyloučení validace není žádoucí. model musí fungovat stejně, ať je k němu shora připojen presenter a view, nebo třeba nějaký cli/rpc controler. na školení jsem se s Davidem bavil o tom, zda do modelu patří ověřování uživatelů. on tvrdil, že ne a že v takovém případě by nad modelem byla další vrstva, která to zajišťuje – ‚security-model‘. s tím souhlasím. zda je security-model součástí modelu nechme na pohledu každého soudruha. podle mě je součástí modelu a měl by obsahovat ošetření vstupu (a to i v případě, že to nadřazená vrstva dělá také) a ošetření práv

model bych tedy rozpitval hned na tři části:

  • security-model: ošetření vstupů a práv
  • business-model: aplikační logika. sem patří hlavně modelové objekty, které u složitějších aplikací budou rozhodně složitější než nějaké ORM. může více či méně prosakovat do úložiště (uložené procedury, agregační triggery, sekvence), to záleží na tom čeho je úložiště schopné
  • data-model: úložiště a integrita dat. z větší části na straně databáze (db-layer, referenční integrita, validační a integritní triggery)

oddělení jednotlivých vrstev samozřejmě nemusí být až tak očividné

pokud by se úložiště chovalo objektově, bylo by zřejmě možné spodní dvě vrstvy sloučit (?)

validace dat tedy může s různým stupněm přísnosti proběhnout v extrémním případě až čtyřikrát – u uživatele v JS, při přijetí formuláře (pokud neumí validaci pomocí modelu), na vstupu modelu a nakonec třeba triggerem v databázi. (sám jsem ale tak daleko zatím nezašel :)

mancze napsal(a):
A co když pak přijde požadavek, že účet se může zarývat do mínusu (což je mimochodem fakt)? Budete muset začít hrabat do modelu. Zřejmě přidáte novou metodu (případně přidáte přepínač k sendMoney), protože nemůžete upravit sendMoney – s tou se nějak v aplikaci manipuluje a vy nevíte jak. Když se toto párkrát zopakuje, budete mít X metod, které vlastně jen posílají peníze. Liší se jen v hloubce kontroly, kterou vykonávají. Myslím, že to vede (za pár let) k nepoužitelnému API modelů.

u tohohle příkladu by se nemělo nijak rozšiřovat API. tady nejlépe poslouží polymorfismus. od starší modelové třídy se zdědí nová s upravenými parametry. uživatelské rozhraní pak může s modelem pracovat, aniž by ho zajímalo, jestli je to třeba zrovna obyčejný účet, nebo kontokorent. rozhraní by se v takovém případě nemuselo upravovat vůbec