Návrh modelu aplikácie rubrika: Návrh

3 MiB
položil/-a 17.5.2016

Zdravím,

rozmýšľam nad čo najlepším údajovým modelom pre uloženie objektov aplikácie.
(ak použijem terminológiu nevhodne, prosím nekameňovať)
Doménové entity sú jednoduchá úloha, úloha so zadaniami, úloha s otázkami, zadanie, otázka, zbierka úloh.

rozdiel medzi zadaním a otázkou je v tom, že zadanie je znovupoužiteľné v ďalších úlohách, naproti tomu otázka je viazaná len na tú svoju úlohu, pri ktorej vznikla.

U každej z entít si pamätám autora, čas vzniku, idčko a nejaké ďalšie veci. Špecifikom je otázka o ktorej si nemusím tieto veci pamätať, lebo je viazaná na svoju úlohu - mohol by existovať prechod od otázky k zadaniu, ak sa niekto rozhodne, že daná otázka sa môže znovupoužiť.
Zatiaľ uvažujem o takom rozhodení do tabuliek, že základom je tabuľka ENTITA(ID, CAS_VZNIKU, ID_AUTORA, TYP_ENTITY, ....) na ňu sú napojené cez FK tabuľky ULOHA, ZBIERKA, ZADANIE. Na tabuľku ULOHA sa napájajú tabuľky JEDNODUCHA_ULOHA, ZLOZENA_ULOHA, OTAZKOVA_ULOHA.

Vytvárajú teda akýsi les:

ENTITA .. ZBIERKA
       .. ULOHA .. JEDNODUCHA_ULOHA
                .. ZLOZENA_ULOHA
                .. OTAZKOVA_ULOHA
       .. ZADANIE
OTAZKA

všetky tabuľky pod entitou preberajú ako svoj primárny kľúč primárny kľúč entity (prebubláva cez FK k nim).

Ide o to, že napríklad zbierka úloh bude v mať v sebe úlohy, je jedno, ktorý podtyp to je. Robím to takto, lebo chcem mať referenčnú integritu údajov cez FK. Takže tabuľka ULOHA_ZBIERKY bude v sebe niesť ID_ULOHA (FK na idčko v tabuľke ULOHA) a ID_ZBIERKA (FK na idčko v tabuľke ZBIERKA).
V podstate potom si to predstavujem tak, že keď sa budú načítavať údaje, tak zoberie z tabuľky všetky úlohy pre danú zbierku aj s ich typom, ktorý načíta z entity. (Jeden selekt).
A budem ich načítavať postupne po jednotlivých typoch. Pričom podľa typu úlohy sa bude volať príslučný load pre príslušné idčka a načíta ich jedným selektom a vytvorí kolekciu.
Teda na načítanie zbierky budem potrebovať 4 selekty. (môj plán).

Je to takto vhodné? Alebo idem na to úplne zle?
Ako by som takéto správanie dosiahol cez ORM?

odkaz
9 pavel.stehule
odpověděl/-a 18.5.2016

Jenom malá důležitá poznámka - pokud pracujete s relační databází, a plánujete pracovat s daty trochu většími než malými zapomeňte, že existuje OOP - zejména, že existuje dědičnost. Simulace dědičnosti je jeden ze známých antipaternů. Relační databáze neumí dědičnost - tečka. Pokus o implementaci dědičnosti pak vede k nutnosti denormalizace, denormalizace pak k šílenému schématu, se kterým se extrémně špatně pracuje.

Komentáře

  • maryo : Jak která DB. Některý podporujou dědičnost na úrovni DB (Oracle, Postgres, CUBRID...). Ale neznám nikoho, kdo by to použil, zkoušel někdo?. Takže souhlas, třeba u Doctrine bych se dědičnosti (pokud nejde jen o mappedSuperClass resp. většinou abstraktní třídu) vyhnul určitě, přestože ji podporuje (ale celkem blbě). 18.5.2016
  • pavel.stehule : Znám dědičnost v Postgresu včetně celé historie, a pokud by se dědičnost z nouze nezačala používat pro partitioning, tak už tahle funkcionalita pěkných pár let v Postgresu není - rozhodně se nedoporučuje ji používat jinak než pro partitioning. 18.5.2016
  • MiB : Čiže ako by to bolo najvhodnejšie bez dedičnosti? Mám to chápať tak, že vytvorím len tabuľky zbierka, zadanie, jednoducha_uloha, zlozena_uloha, otazkova_uloha, otazka a každa z nich bude mať svoje vlastné stĺpce id, autor, cas_vytvorenia, ... . Len potom nebudem mať spoločný priestor všetkých úloh, ale osobitne všetky typy úloh. Práve preto som to chcel mať tak. Možno som tú schému nakreslil ako strom dedičnosti v OOP, ale ja tie tabuľky chápem len ako previazané tým ID, aby som sa vedel ľahko dostať z tabuliek na listoch stromu ku tabuľke entita a čerpať z nej. Podobne, aby som na jeden šup vytiahol IDčka všetkých úloh, bez ohľadu na typ. Každej tabuľke v DB by odpovedal jeden mapper, ktorý by s ňou pracoval. Rozmýšlal som o dedičnosti tých mapperov, že v aplikácii je abstraktná trieda Entita so svojimi údajmi, od nej dedí abstraktná trieda úloha a až potom je normálna trieda jednoduchá_úloha. Každá z týchto tried má svoj mapper, pričom znova mappery pre úlohu a entitu sú abstraktné a normálny je len mapper pre jednoduchú úlohu. Keď vytváram novú jednoduchú úlohu, tak mapper pre jednoduchú úlohu najprv zavolá mapper pre úlohu a ten zavolá mapper pre entitu, ten konečne zapíše do tabuľky novú entitu, odovzdá jej ID mapperu pre úlohu a ten si s ním vytvorí nový riadok pre úlohu a odovzdá ID mapperu pre jednoduchú úlohu, ktorý dokončí zápis. Naproti tomu čítanie úloh cez select by riešil len mapper pre jednoduchú úlohu, ktorý by ťahal údaje zo všetkých prepojených tabuliek a vytvoril objekt typu jednoduchá úloha. Je toto čo popisujem dedičnosť v SQL? Lebo ja to chápem len ako previazanie tabuliek v SQL pre rýchlu orientáciu. (Moje praktické zručnosti sú slabé - prvý projekt) PS: viem, že je to v podstate Class Table Inheritance podľa Fowlerovho katalógu, len tie selekty sú asi trochu inak riešené. 18.5.2016
  • maryo : A proč nemít pro sbírku jen jednu tabulku a jednu (nebo i víc tříd no - záleží)? Ten typ se dá odlišit třeba sloupcem pokud je to vůbec potřeba odlišovat. 18.5.2016
  • mamatoto : maryo: ano, to sa nazyva single table inheritance 19.5.2016
  • MiB : maryo: asi myslíš úlohu, nie zbierku. Áno rozmýšlal som o tom, ale chcel som urobiť čistú schému, aby už na úrovni DB si strážilo, čo nesmie byť a čo môže byť. Moje vedomosti sú skôr teoretické, mám to chápať tak, že sa v praxi používa predovšetkým single table inheritance? 19.5.2016
  • pavel.stehule : MiB: Při návrhu relační databáze je potřeba myslet v množinách, nepřemýšlet o mapperech, atd. Ze zadání vím, že budu realizovat některé procesy, což pak budou SQL příkazy - v SQL by se měl primárně objevovat filtrovaný JOIN, sem tam nějaký UNION. Datový model je jeden krok, hned další je verifikace primárníma SELECTama - vždy musím vědět, proč tu databázi píšu, co na ní budu dělat. 19.5.2016
  • maryo : matej.chrenko: Ne, nenazývá, pokud od sebe nedědí ty třídy, na které se ta tabulka mapuje. "Represents an inheritance hierarchy of classes as a single table...". MiB: Jj, myslel jsem úlohu, sorry. Já používám PHP a Doctrine. Tam se snažím vyhýbat jakýkoliv dědičnosti krom mapped superclass (ale ani to moc nepoužívám) hlavně z důvodu jak je to v Doctrine implementovaný. http://doctrine-orm.readthedocs.io/projects/doctrine-orm/en/latest/refer... There is a general performance consideration with Single Table Inheritance: If the target-entity of a many-to-one or one-to-one association is an STI entity, it is preferable for performance reasons that it be a leaf entity in the inheritance hierarchy, (ie. have no subclasses). Otherwise Doctrine CANNOT create proxy instances of this entity and will ALWAYS load the entity eagerly. Podobně u class table inheritance. Jak to řeší jiný ORM nevim, při ručním mapování věřím, že se to dá vyřešit, nicméně bez dědičnosti bude namapování a schema asi vždycky jednodušší. A ve spoustě případech i z hlediska OOP je prostě lepší řešit to kompozicí. Né vždy. Ale to už taky záleží na případech použití, ze zadání to dostatečně nevyplývá. 19.5.2016
  • mamatoto : maryo: bavime sa predsa o ulohe, z ktorej su zdedene jednoducha uloha, zlozena uloha a otazkova uloha. Ty to navrhujes dat do jednej tabulky a odlisit stlpcekom typ, to je presne "Represents an inheritance hierarchy of classes as a single table...". - tak funguje STI napr v active record v railsoch. 19.5.2016
  • maryo : V prvním komentáři jsem psal, že bych se dědičnosti vyhnul a reaguju na odpověď, která od dědičnosti taky odrazuje, takže já navrhuju mít buď jen jednu třídu pro úlohu anebo mít teda 3, ale bez dědění. Např. místo toho můžou implementovat stejnej interface. 21.5.2016
  • mamatoto : Preco by si sa dedicnosti vyhol? Toto je presne ten pripad, kedy je dedicnost vytana kedze tam je vztah "is a", na rozdiel od mnohych pripadov, kedy je dedicnost pouzivana nespravne. 21.5.2016
  • maryo : Hlavně kvůli Doctrine, tomu co jsem tu psal a kvůli jednoduššímu schematu obecně. Doctrine to teda taky podporuje ale věřím, že třeba Hibernate nebo Entity framework na tom budou líp, neznám je, pokud jo a pokud by dědičnost přinesla nějakou velkou výhodu (což z toho zadání nutně nevyplývá), tak bych jí třeba v případě použití těhle ORM taky použil, ale nejdřív bych si to několikrát rozmyslel. 21.5.2016

Pro zobrazení všech 7 odpovědí se prosím přihlaste:

Rychlé přihlášení přes sociální sítě:

Nebo se přihlaste jménem a heslem:

Zadejte prosím svou e-mailovou adresu.
Zadejte své heslo.