Entity = DI vs. statika? aneb co patří do entity
- frosty22
- Člen | 373
Zdravím Vás,
již chvíli přemýšlím nad správně objektovým řešením entit (konkrétně v Doctrine 2) a obecně řečeno mě zajímá – co do entity patří a co ne?
Entita tedy obsahuje property, zároveň samozřejmě i jejich datový typ a stejně tak i definuje, zda-li některá položka může být nullable či nikoliv, tudíž je entita, co se týče obsahu zodpovědná sama za sebe, a podle mě by tedy i měla obsahovat validaci (= když již obsahuje definované typy a kontroluje nullable což již je validace objektu), tak by i měla obsahovat například kontrolu správnosti emailu apod.
Pokud se mnou do této části souhlasíte, tak teď přichází menší problém – co když je validace složitější, například jde o bankovní účet, jehož validace se zakládá i kontrole platnosti kódu banky (buď z databáze či z CNB.cz) nebo například validaci IČ, kde se kontroluje existence v ARESu, atd. atd.
Možností je zde potom několik:
- Buď pojmout i tyto validátory staticky (stejně jako je například nette objekt Validators) – na jednu stránku nejjednoduší možnost, na druhou je to vúči logice DI a jejím výhodám (- nepůjde zaměnit objekt validace, atd…)
- Vytvořit service, která bude mít nějakou tovární metodu na ono vytváření objektů a zároveň bude i validovat data a z dat vytvoří entitu. U tohoto řešení se mi však trošku příčí rozdělená validace – zda je například property číslo či další entita (- asociace) tak se to validuje v entitě, ale zda-li je property správné IČ, tak se validuje v service. A druhý problém, pokud se zapomene na tuto service, a vytvoří někdo uživatele přes new Entity .. ejhle nevalidní data.
- Přidat entitě závislosti na validačních objektech a vyžadovat je v konstruktoru, či setteru a při nastavování kontrolovat existenci tohoto objektu. Toto by již zaručilo že entita nepůjde vytvořit invalidní – ale patří toto co entity? Případně tedy toto by šlo zkombinovat s bodem 2, kdy se vytvoří továrnička na tuto entitu a předají se závislosti. V tomto řešení bude výhoda, jelikož pokud se továrnička nevyužije, tak závislosti se stejně musí předat.
Napadá Vás jiné řešení, či toto řešíte některým z těchto bodů?
Děkuji
- bazo
- Člen | 620
skvely blog beberleia ti mozno da odpoved http://www.whitewashing.de/…raction.html
a este zopar clankov kde su aplikovane ine principy na ten isty problem
- frosty22
- Člen | 373
Tak zatím se zde žádný větší „flame“ nestal, jinak tedy děkuji za link, podíval jsem se a je to zajímavé, leč stále přímo odpovědi nemám a člověk se podotýká s problémem pořád, respektive ideální řešení asi neexistuje, avšak tedy můžeme to zobecnit na ot. „Kam s validací dat?“
To je to oč tu běží, kde ideálně mít validaci dat – přestože Nette má krásné formuláře a validace tam je fajn, tak ale ideálně by to chtělo oddělit validační vrstvu jinam. V podstatě udělám validaci dat ve formuláři a ehle potřebuji import dat, či mám APi pro komunikaci s mobilní aplikací a co teď? Udělat další validaci zde? Při použití doctrine, řešit validaci v service i ve formulářích a i v entitách? Nebo entita POUZE reprezentuje datové úložiště – tabulku jako takovou, ale neměla by řešit validaci?
V podstatě na ideální stav jsem ještě nenarazil. Co si myslíte o tom vy?
- frosty22
- Člen | 373
Přemýšlím, jestli bych narazil na tento problém, resp. nenapadá mě zatím proprety entity, kterou bych validoval a neměl u ní getter, resp. nechtěl/nepotřeboval ho přímo vytvořit, přeci kdy použít write-only property ..
Osobně bych jako nejzásadnější problém viděl v odstínění validace formuláře – vytvořit validační vrstvu, která by šla „předat“ formuláři.
- Šaman
- Člen | 2666
Podle mého patří validace do entity. Entitu chápu jako plnohodnotnou reprezentaci objektu v systému, nekoliv jako přepravku pro data.
IMHO základní validace, které by byly v samostatné třídě (kvůli znovupoužitelnosti) mohou být buď statické metody, nebo metody injectované služby. Specifická validace však patří přímo do entity (např. validace RČ u entity Person, validace VIN u Auto apod.).
- frosty22
- Člen | 373
@Šaman: S tímto s Tebou souhlasím, ostatně jak jsem naznačoval výše, též bych raději bral entitu jako plnohodnotnou reprezentaci objektu, která má hlubší smysl, než jen předpis/definici úložiště/tabulky .. ale bohužel zde pak implementačně dochází k problémům – jak jsi uvedl právě díky složitějším validacím, které jsou závislé na dalších objektech aneb „statika“ je zlo :) A oproti tomu vytvářet nějaké továrničky na entity, nevím zda-li je ideální stav?
A následně to bohužel stále neřeší, jak to propojit s formuláři .. oproti tomu mít validační vrstvu mimo, tak by již bylo možné tuto vrstvu předávat i formuláři a vytvářet zde validační pravidla – ale na napsání to není otázka chvíle .. tedy minimálně teď vzhledem k nynějšímu stavu a pojmuní formulářů v nette
- Šaman
- Člen | 2666
V takovém případě mi příjde čistější, aby si formulář tu validační metodu vzal z entity. Když se chceme vyhnout statickým třídám, tak musí mít formulář k dispozici eantity jako služby. Dává to logiku – formulář pro editaci uživatele by měl mít vazbu na entitu uživatel, chceme-li aby využíval validaci specifickou pro uživatele.
Dotaženo do dokonalosti by si mohl formulář pomocí injectované entity validovat i primitivní validaci, jen by pro něho zůstala skrytá (např. jméno musí být neprázdný řetězec, věk celé kladné číslo od 0 do 150). Pokud by se například změnil tvar rodného čísla, tak se to přepíše v jediné entitě a ne v každém formuláři.
- frosty22
- Člen | 373
Tak zde jsem se lehce ztratil resp. nedokážu si zrovna představit ono rozhraní – vazbu mezi formuláři a entity, tady už by to trošku hraničilo s tím, že by entita měla na starost dost věcí, ikdyž spíše jsem tě nepochopil – stejně jako s tím, že by pro něj zůstala primitivní validace skrytá – to si nepředstavím jak myslíš.
- Patrik Votoček
- Člen | 2221
Osobně používám entity pouze jako přepravky a data v nich více méně jenom „normalizuju“ (převedu / kontroluju datový typ a prázný string převedu na NULL). Validace je před tím než data hodím do entity (typicky v mapperu z formulářových dat – kde na nevaliditu můžu rovnou reagovat) a pokud se jedná o kritičtější část tak může být validace i před uložením do DB. Což se dá v Doctrine 2 elegantně řešit díky lisenerum (eventům).
- Patrik Votoček
- Člen | 2221
Šaman napsal(a):
… eantity jako služby.
What? Jako že budu mít každou instanci článku (na stránku jich vypisuju 50) v DIc?
Dává to logiku – formulář pro editaci uživatele by měl mít vazbu na entitu uživatel, chceme-li aby využíval validaci specifickou pro uživatele.
Tohle se hezky říká ale v praxi narazíš na problémy. Stejně jako entita != databázová tabulka tak taky poměrně často entita != formulářová políčka.
- frosty22
- Člen | 373
Tohle ale asi neřeší odstínění validace od formuláře, resp. taky máš ve formuláře addRule, a v případě jiného přístupu importu/api tak validuješ v mapperu? Chápu-li to správně. A sice chápu, že property != formulářový prvek, ale myslím, že tohle by šlo řešit určitou abstrakcí, ale je to jen myšlenka – jelikož právě ono validování na více místech, bych se chtěl rád zbavit.
- Patrik Votoček
- Člen | 2221
frosty22 napsal(a):
… ale myslím, že tohle by šlo řešit určitou abstrakcí …
Abstrakcí jde řešit vše. Nicméně jsem stále nenarazil ani se mě nepodařilo vytvořit takovou abstrakci která by tohle řešila a byl bych sní spokojen.
- frosty22
- Člen | 373
Tak jistě vše má své úskalí, ale přeci jen mě zajímá jestli někdo již nemá lepší přístup k této problematice a pokud ne, tak jestli by se to nedalo vymyslet :)
Docela přemýšlím, jestli by se to právě nedalo udělat nějakou vrstvou zvlášt, která by řešila validace, dále udělat vrstvu i nad entitymanagerem, který by před persistováním kontroloval ony validace nad entitou (případně to propojit i spolu s událostmi, kvůli flushování změn managed entit) a v druhé části by mohla být nějaká „továrnička“, která by skloubila onu validační vstvu a formuláře .. ono špatně se to popisuje v tuhle hodinu, ale myslím si že myšlenka by to nebyla špatná, jen je potřeba ji právě dost domyslet, jelikož má jistě mnoho úskalí