ORM - Léccine...

Komolyan nem értem, hogy miért jó ez az egész. Tipikus IT-s design folyamat, amelynek eredménye ismételten egy félmegoldás, mint a legtöbb minden. És most a következő 10-20 évre ez lesz bebetonozva az IT-ben.

Probléma - mint oly' sokszor - a backward compatibility. Itt vannak nekünk ezek a fránya RDBMS-sek, amelyeket használjuk már több évtizede és az istenért sem tudunk elszakadni tőlünk. Pedig ma már jellemzően nem adatbázisokat akarunk kezelni sokszor, hanem objektumokat tárolni perzisztens módon.

És erre mit találnak ki az okosok? Hát taknyoljuk bele valami plusz rétegen keresztül, amivel megpróbáljuk elrejteni a különbségeket, mert fúj, különben SQL-t kell írni meg az ronda meg stb.

Eredmény?

- Objektumok perzisztens tárolása nem megoldott normális módon.
- Bonyolultabb RDBMS funkciók használata nehézkes, körülményes vagy egyenesen lehetetlen, mert vagy megsértjük vele a konzisztenciát vagy az egész ORM-et meg kell kerülni vele.

Szóval adódik a kérdés: miért nem a problémát próbáljuk megoldani ismét?

Hozzászólások

Ennyire még nem mélyedtem bele az adatbázistervezésbe, de ez az objektum vs reláció nem tiszta.

Relációs DB-nél nem pont az a lényeg, hogy az adatok egymáshoz való viszonyát adjuk meg? Ebben az esetben ki vagy mi gátolja a megfelelő adatbázisszerkezet használatát objektumokhoz is?

Nagyon elnagyolt példa: egy osztály mehet egy táblába, az egyedi adatok bele értékként, a közösek/állapotok meg kapcsolótáblával külön táblába.

Vagy nem ezzel van a gond, hanem a teljesítménnyel?

Az elnagyolt pelda nagy vonalakban az ORM definicioja (Object-Relaional Mapping).

Altalaban ezt ketfelekepp szokas megoldani, irnak egy db layert az alkalmazasba, ami ismeri mindket oldalt, es konvertal koztuk (ugye a legtobb db api egy tombot ad vissza mint sor, az pedig meg nem objektum...), a masik kap egy ures objektumot, es a tabla felterkepezese alapjan beleszorja a properyket az aktualisan lekerdezett sor adataival (ehhez ugye az adatbazisnak ismernie kell a SHOW FIELDS -szeru lekerdezest). Ebbol az utobbi az egyszerubb, cserebe ez mukodik a legkevesbe szeles korben, mert a nem dinamikus nyelveknel nem trivialis hasznalni (reflection, proxy, wrapper). Az elozo pedig altalaban teljesitmenygondokat okoz, ha mondjuk nem tiz, hanem ketszaz objektumot akarsz berenderelni egyszerre. Legalabbis, nagyon konnyen bottleneck tud lenni egy hibasan megirt DB layer.
--

Ki oda vagyik, hol szall a galamb, elszalasztja a kincset itt alant. | Gentoo Portal 

Röviden (és persze nagyon-nagyon pontatlanul) fogalmazva kb. annyi, hogy leképezel egy-egy objektumot egy adattábla rekordjára.

Csak személy szerint annyi a problémám az egésszel, hogy addig, ameddig egy weblapnál annyi a feladat, hogy lekérdezünk valamit, azt az user képébe hányjuk és nem foglalkozunk vele, addig egy olyan rendszernél, ahol hosszú órákig dolgozna ugyanazzal az objektumokkal - több helyről - a rendszer, ott az ORM mapping nem hogy nem segít, hanem még szerintem hátráltat, mert úgy is mindig vissza kell nézni a DB-be, hogy megvan-e egyáltalán az adat és friss-e még. Vagy ugyanígy, szívás van akkor, ha mondjuk valami komolyabb statisztikai dolgot kell csinálni (és abban jelenleg kétség kívül a relációs dolgok a jobbak).

----------------
Lvl86 Troll

Értem :)

Tudsz nekem mondani példát arra, ahol objektumokkal kell dolgozni sokáig és több helyen? Én eddig a "kihányjuk a user képébe" fázisnál tartok, de érdekel, hogy hol jelentkezik ilyen probléma (ilyen szempontból nem jó a fantáziám:)).

Szerk: valami elosztott számítási rendszerre tudok hirtelen gondolni.

Szerk2: esetleg valami banki dolog.

Ahol belefutottam konkrétan a problémába, az az, hogy adott egy cumó, amely futkosna egy szerveren és végezne számítgatásokat egy dinamikus szabályrendszer alapján. Továbbá adottak még felhasználók a rendszerben, ilyen őskövületekkel, mint desktop app (mert azt az UI-t nem vagyok hajlandó végigszívni böngészőre), akik időnként nyomkodják ezeket a szabályokat. Na meg persze a számításokat végző cucc se a devnullba végez dolgokat, azokból is jönnek időnként ki olyan dolgok, amiket szintén meg kellene jeleníteni az UI-n, minél előbb.

----------------
Lvl86 Troll

"ott az ORM mapping nem hogy nem segít, hanem még szerintem hátráltat, mert úgy is mindig vissza kell nézni a DB-be, hogy megvan-e egyáltalán az adat és friss-e még"

Javits ki ha tevedek, de ez az adatkonzisztencia amit emlitesz, teljesen fuggetlen attol hogyan reprezentalod es dolgozol az adattal, nem kenheted az ORM-re.

--
cythoon

Ha az objektum addig el, amig a request el, akkor mindegy, hogy megvan-e meg az adat, mert neked eleg a requestkori allapot. Persze, elojohet olyan inkonzisztencia, hogy pont akkor kerdezel le, amikor parhuzamosan fut egy cascade delete, de mivel eppen ezert vannak a tranzakciok, elvben te a sajat tranzakciodban meg latod azokat az adatokat, es csak utana torlodnek le. A legtobb normalis ORM rendszer vagy alapbol tranzakciozik, vagy bekapcsolhato benne, ugyanis csak igy van ertelmuk. Csekkolni legfeljebb update elott kell, az meg nem surun van.

Az ORM szerintem azert jo dolog, mert objektumokkal kenyelmesebb es egyszerubb dolgozni, mint azokkal a raw tombokkel, amiket a db apik kiadnak magukbol.
--

Ki oda vagyik, hol szall a galamb, elszalasztja a kincset itt alant. | Gentoo Portal 

Ez meg gyakorlatilag a cache-nem cache kerdeskor. Szakadjunk el egy pillanatra attol, hogy objektum, ha sima sql query lenne, akkor meddig tartanad ervenyben a cache-t? Minden lekeresnel megnezned, hogy az elcache-lt eredmeny ervenyes-e?

Szerintem az ilyen esetekre siman lehet igy gondolkodni. Addig ervenyes az objektum, amig azt mondjuk, hogy ervenyes. Cache eseteben is siman elofordulhat, hogy az elcache-lt vegeredmenyt mar valaki modositotta, de ettol a cache nem lesz invalid, mert erre nincs trigger, hogy a db kiszoljon, hogy akkor most tessek ervenyteleniteni a cache-t.
--

Ki oda vagyik, hol szall a galamb, elszalasztja a kincset itt alant. | Gentoo Portal 

Én nem mondanám, hogy teljesen hülyeség az ORM, csak olyan programnyelvvel kell összehozni, ami támogat reláció-szerű konstrukciókat (pl. rendes tupple, lazy adattípusok). És persze olyan programozó is kell, aki felismeri, hogy egy problémát egyszerűen lehet megoldani ezek használatával.

Így már elvileg lehet csinálni olyan ORM-et, ami az ilyen adatszerkezetek kiértékelését rábízza az RDBMS engine-re és nem mohó módon intéz mindent.
---
Internet Memetikai Tanszék

Na igen, csak jelenleg ott tart legtöbb esetben a tudomány, hogy fú, lusta a programozó SELECT/INSERT/UPDATE/DELETE -t írni, használjunk ORM-t. Aztán, ha egy butább ORM implementáció az 1000 objektum lekérdezését 1000 külön SQL query-vel oldja meg, az már részletkérdés.

De azt hiszem, nem írtam le jól a problémát: addig, ameddig az objektumot csak rövid ideig használjuk, addig nincs gond az RDBMS-sel. Viszont, ha már sok helyen, sokáig kell használni az objektumot, egyből adódik az, hogy nem jó, hogy valamit betöltünk a RAM-ba, és onnan szöszölök anélkül, hogy bármiféle kontroll lenne afelett, hogy a nagyvilágban mi történt még az objektummal.

----------------
Lvl86 Troll

Izé, hát ez így szerintem nem ORM probléma; az objektum minden művelet előtt újratöltheti magát a DB-ből. Ha az RDBMS eredményeket cache-elni akarod, akkor a probléma ugyanez ORM nélkül is: mikor invalidáljam a cachet? Lockolni, scope-olni meg lehet itt is, ott is.

Ez így inkább RDBMS hiányosság.

Azért ragaszkodunk hozzá, mert nélküle is ugyanazokkal az alapvető számítástehnikai problémákkal szembesülnénk, amire ugyanúgy nem lenne egyetemes válasz, ahogy RDBMS-ben sincs (párhuzamos feldolgozás, lassú háttértár, stb).

Ellenben egy csomó új problémát hoznánk be, kezdve onnan, hogy le kéne mondani az RDBMS előnyeiről (adatbányászat, platformfüggetlenség, stb).

"platformfüggetlenség"

Platformfüggetlenség most sincs. Ha választasz egy RDBMS-t, jó eséllyel hozzáláncoltad magad, főleg, ha kihasználod a fejlettebb funkcióit a rendszernek. Pl. próbáld meg lecserélni a Firefoxban az SQLite-t mondjuk MySQL-re vagy PostgreSQL-re ;)

"adatbányászat"

Ebben igazad van. Azonban nem csak adatbányászat létezik a világon. (És ott szerintem jellemzően nem is objektum-tutujgatás, hanem inkább statisztikai funkciók a hangsúlyosabbak, de javítsatok ki, ha tévednék.

Viszont mint ahogy látod, lennének megoldatlan problémák, amelyre most kb. annyi a válasz, hogy "hát van az ORM, de ott is trükközni kell".

----------------
Lvl86 Troll

Ah, látom nem érted a problémát. Adott egy Java-s vagy .NET-es vagy bármi OOP-s alkalmazás. Nem mindenféle vegyes platformú cucc, homogén rendszer a programnyelvek tekintetében. Itt kellene kifőzni valamit az objektumok tárolására úgy, hogy az osztott módon működik. És nekem úgy tűnik, hogy sokszor inkább ez az igény, cserébe inkább ORM-mezik mindenki, mert "jaj, nem szeret SQL-t írni".

----------------
Lvl86 Troll

Értem a problémát, csak próbálom végigvinni a szálat, ahol a kérdés az volt, hogy általánosságban "miért ragaszkodunk az RDBMS-ekhez?".

Az ORM olyan objektumokat ad, amik megosztják egymással az adataikat, innenstől nem értem, hogy mit vársz el az "osztott módú" működés alatt. Ami miatt panaszkodsz, az a cache koherencia, amit valóban rádbíz az ORM, ahelyett, hogy ráderőltetne egy számodra potenciálisan rossz megoldást, mivel ezt általánosságban sajnos lehetetlen hátrányok nélkül megoldani.

"A" gép beírja DB-be azonnal amint módosult az objektum (no writeback cache), "B" gép pedig kiolvassa újra és újra DB-ből, mindig, amikor szüksége van az adatra. "B" gépen nem muszáj memóriában tartani az adatot, ha szükség van rá, ki lehet húzni DB-ből. Ha a helyi memóriában is van egy másolat az adatrol, az már cache.

Már rég azon kéne vitatkozni, hogy "jóóó de ez így milyen lasssú lesz!" :)

és egyszercsak a teljes adatbázis terracottában fog lebegni?

júzer kilistázza a megrendeléseket, mondjuk 100 per page, az orm réteg meg felolvassa mindet, s amíg el nem unja, minden beszállító telefonszáma is ott fog lebegni a memóriában, mert egyszer valaki kilistázta az összes júniusi szállítást? GC-t mennyire terheli?

Az RDBMS mögött elég sok kutatás és matematika van, hogy gyors legyen pl. a lekérdezés, lehessen optimalizálni az utasításokat végrehajtás előtt, lehessen jó adatbázist tervezni.. Az OO db-k ilyen szempontból eléggé el vannak maradva, mert más a szemlélete eléggé. Nem véletlen, hogy fejből tudsz mondani pár RDBMS-t is, de valószínűleg egy ORDBMS-t sem. Az ORM csak egy konverter ha úgy tetszik.
Az, hogy valaki nem ért ahhoz, amit csinál, az nem az ORM hibája, és ugyanúgy tudna gányolni ha ORDBMS-t használna, akkor is.

Nezd, az ORM platformot ugyanugy ki kell tesztelni dontes elott, mint minden libet. Butabb ORM platformmal nem erdemes kezdeni, ennyi. Akinek meg annyi esze van csak, vagy annyira ert hozza, az meg megerdemli.

Szerencsere a jobb ORM platformok mar kepesek jol osszerakni a query-t. De ezzel egyutt a butabbaknak is van eselyuk, hiszen sokszor egy alap feladatra eleg lehet pl. a PHP-ban levo PDO is "ORM" rendszernek.
--

Ki oda vagyik, hol szall a galamb, elszalasztja a kincset itt alant. | Gentoo Portal 

Van ahol megoldottak rendesen, csak az IT altalaban 1. sosem tudja meg 2. leszarja magasrol ;) Az IT mar 20 eve nem a mernoki munkarol szol.
--
cythoon

csinald a kovetkezot:
vannak objektumaid, meg objektum azonositot(id-t) tartalmazo listaid.

ha bonyolultabb lista kell, akkor sql-t irsz ami visszaad egy string tablazatot, plussz soronkent 1 objektum azonositot, es az objektum tipusat.
a sztringeket megjelenited tablazatban, es amikor az user valamit akar csinalni valamelyikel, akkor szeded elo a valodi objektumot. ez mar automatikus sql-el megy. ekkor lesz elerheto az objektum funkcionalitasa. modositas/torles/insert csak szabvanyos modon, de a lekerdezesre megmarad a teljes szabadsag.
igy mind az sql teljes bonyolultsagat ki tudod hasznalni, mind az objektumaid megmaradnak es ugyanugy hasznalhatok.

--
Live free, or I f'ing kill you.

Azért, mert minden adattábla egy relációt (matematikai fogalom, rendezett n-esek részhalmaza) ír le.
A tábla egy sora a reláció egy eleme. A tábla oszlopai a reláció, mint rendezett n-es egy-egy komponensének felel meg.
Ezen a reláción lehet relációs algebrával műveleteket végrehajtani stb.

köszönjük a definíciót, de ez se vitt minket közelebb az ojjektumokká alakításhoz :)

S mivel úgy vált hagyománnyá, hogy az sql-t értő dbms-eket hívjuk rdbms-nek és néhány nosql alkalmazás úgy hirdeti magát, hogy "nem kell szopnod a relációkkal", kissé félreérthető, de így ragadt meg. sql=relational, nosql=valami más. Olyan ez mint a "fóliák".

Ami a valodi problema: objektumok allapotat perzisztensen tarolni. Ezt sokan ugye azert ORM-mel csinaljak meg, mert az hasonlora kepes.
Amugy erre inkabb az active record pattern lenne jo. Egy objektum sajat magarol eldonti, hogy melyik allapotat akarja perzisztensen tarolni, es o maga menedzseli sajat maga allapotanak megvaltozasat, figyelve a konzisztenciara.
Amit sokan rosszul csinalnak: DTO-k logika nelkul, igy barmilyen klienskod siman invalid allapotba hozhatja az adatokat. Sokan osszetevesztik az uzleti logikat a DTO-t allapotmodositasaival es a konzisztencia biztositasaval. De ez egy alapvetoen hibas szemlelet, a modell-osztalyok sajat maguk implementaljak az allapotmodositasaikat a konzisztencia biztositasaval. Az uzleti logika meg arrol szol, hogy ezek az objektumok hogyan mukodnek egymassal, hogy megvalositsak a szoftver celjat.

Osszessegeben: az ures, logika nelkuli adatmodellnek kulso mutatorral nincs sok ertelme.

A nevezektan jogos.

Viszont Fowlernek nagyon is igaza van szerintem. Az anemic domain model azert rossz, mert egy objektumodnak BARMELY kulso kod modositani tudja az allapotat, igy barmikor kerulhetne invalid allapotba. Ha az objektumodban jo az adatrejtes es az encapsulation, akkor a kulso osztalyoknak nem is kell (es nem is szabad) ismerni a belso logikat, nemhogy kivulrol vezerelni az allapotot.