Princip modelování
Jak již bylo řečeno v úvodní kapitole, tak modelování pomocí Jet DataModel musí splňovat určitá pravidla a není to samoúčelné. V rámci Jet DataModel nekoukáme primárně na databázové tabulky. Databázové tabulky jsou až výsledek a nízkoúrovňový backend, kde jsou data fakticky uložena. Návrh datového modelu nezačíná u tabulek, ale rovnou u tříd. Možná je to někoho změna. Vím, že spousta z nás je prostě zvyklá nejprve vyrobit tabulku, přesněji tabulky. I já to tak roky dělal.
Vlastně se dá říct, že DataModel přebírá něco z filozofie NoSQL (ve smyslu Not only SQL), ovšem s tím, že využívá jednoznačné robusnosti, osvědčenosti, vyzrálosti a spolehlivosti starých a především dobrých relačních databází.
(Poznámka: backend DataModel v současné době oficiálně existuje pouze pro MariaDB/MySQL, ale experiméntálně a neveřejně byla ověřena možnost vytvořit backend pro Oracle a MS SQL - proto mluvím v množném čísle o relačních databázích a mám ověřeno, že správně vyvinuté aplikace lze mezi různými RDBMS přenášet)Velkou část mých projektů posledních let tvoří e-shopy, nebo v minulosti finanční produkty, IS a podobně. V mé praxi není prostor na možné nekonzistence a experimenty zrovna na úrovni práce s daty. Tedy spolehlivé a jasně struktorované datové úložiště považuji v mém obory za naprostou nutnost. Čím tedy Jet DataModel trochu připomíná NoSQL? Tím jak nahlíží na datové entity - dalo by se říct na ně nahlíží jako na dokumenty, primárně reprezentované třídami v aplikaci. Tento pohled, nebo úhel pohledu, je důležitější než pohled ze strany tabulek. A Jet DataModel přináší do datového modelování několik málo jednoduchých pravidel a principů, což si v ukážeme na následujících řádcích a také v následujících kapitolách.
Místo dlouhého teoretizování si to rovnou ukažme na praktickém příkladu. Zmínil jsem e-shopy, tak u toho můžeme zůstat jako příklad použijeme datový model - entitu - číselník, například číselník barev z vyvíjené platformy e-commerce Jet Shop.
Co o takovém číselníku můžeme říct?
- Bude mít nějaké základní společné parametry. Určitě ID celého číselníku, nějaké interní jméno a interní poznámky k číselníku. Nazvěme to obecnou hlavičkou číselníku.
- Číselník určitě musí obsahovat jednotlivé možnosti. Například barvy, nebo velikosti oblečení a tak dále. Každá taková možnost má určitě ID, nějaký interní název, interní kód a podobně.
- Protože platforma Jet se stavěna pro lokalizované aplikace, není tomu jinak ani u připravovaného produktu Jet Shop a číselník bude mít určitě rozdílné popisky možnosti pro různé lokalizace. Tedy název (například) barvy bude určitě jiný v češtině a třeba němčině. Stejně tak popisky, text nápovědy a tak dále.
Naší ukázkovou entitu můžeme nazvat option_group a ta bude mít subentitu option_group_option a tato subenetita další subentitu option_group_option_localized. Celá entita bude mít toto uspořádání:

V běžné situaci bereme celou entitu jako celek. Tedy například v administraci budeme potřebovat nahrát celý jeden konkrétní číselník, aby mohl být použit. Stejně tak podle číselníku budeme chtít vytvořit na e-shopu například filtraci pro zákazníky a tak dále. Tedy častou úlohou bude prostě získat / načíst číselník (nebo číselníky).
Poznámka: Ve skutečnosti je samozřejmě možné nahrát jen část entity. Tedy například pouze jednu možnost z číselníku, nebo určité možnosti číselníku a tak dále. A také je možné nahrát (nebo i uložit) pouze dílčí data. Třeba jen popisky a tak dále. To samozřejmě možné je, bez toho by nebylo možné mít efektivní aplikace. Ale o tom si povíme později. Teď prosím nahlížejte na našeho "pokusného králíka" číselník jako na jednu entitu.
Je patrné, že mezi subentitami jsou relace, zde konkrétně 1:N. Tedy jeden číselník bude mít určitě N možností a každá možnost může mít N lokalizací. Pochopitelně může existovat i relace 1:1, ale v praxi je mnohem častější 1:N. Tomu se říká vnitřní relace.
Je jasné, že kde existují relace tak musí být nějak definována jejich provázanost. To si ukážeme v rámci definic a podrobného rozebrání vnitřních relací. Pro teď jde především o to ujasnit si jak se v rámci Jet DataModel na entity nahlíží.
Tedy máme jednu hlavní entity, její subentity. Každá entita i subenetita bude reprezentována nějakou třídou a budou definované nějaké vazby. A když budu ve finále v aplikaci potřebovat číselník, tak si jej natáhnu třeba takto:
$option_group = OptionGroup::get( 'some-option-group-code' );
foreach( $option_group->getOptions() as $option ) {
//... ... ...
}
Jet DataModel už udělá tu otravnou rutinní práci, sestaví dotazy, načte data, vytvoří instance kterým data předá a pomyslný číselník je možno použít.
Do teď nic zvláštního, že? Ale pozastavme se u toho načtení číselníku, kde máme subentitu a subentiotu subentity a vše v relacích 1:N. Co když má číselník 50 položek a e-shop je v pěti lokalizacích? Pokud tušíte potencionální velký počet dotazů (což je přesně to co určitě nechceme), tak tušíte správně. Určitě by nebylo dobré natahovat lokalizovaná data pro každou možnost číselníku extra. To už můžeme pro aplikaci znamenat stovky dotazů a tam fakt vidím "velký špatný".
Máme tři entity a subentity, tedy tři tabulky. Tedy minimální (a optimální) počet dotazů je také 3. A přesně to Jet DataModel dělá. Načte minimálním počtem dotazů všechna potřebná data a ty pak "poskládá" do instancí.
Ale aby to bylo možné, tak musí být splněno jedno pravidlo. Všechny subentity (tedy i subentita subentity a subentita subentityt subentity a tak dále) musí vždy mít vazbu na hlavní entitu. Tedy v našem ukázkovém příkladu musí existovat tato vazba:

A to je vlastně jediná pevná podmínka. Pochopitelně je nutné vnitřní relace definovat - jak se dočtete v příslušné kapitole. Ale z hlediska návrhu uspořádání je nejdůležitější vazba všech entit na hlavní entitu - je to důležitý propojovací element.
Málem jsem zapomněl na jednu důležitou věc. Při návrhu uspořádání entit je důležité myslet na jejich teoretickou budoucí velikost a praktické použití. Příklad? V rámci ukázkové aplikace naleznete malinkou ukázku obrázkové galerie. Možná člověka intuitivně napadne, že obrázek (třída JetApplication\Content_Gallery_Image) samotný je prostě subentita entity galerie (třída JetApplication\Content_Gallery). To zní sice logicky, ale co když někdo do jedné galerie nahraje 1000 obrázků? To sice bude hezké, že počet dotazů je malý, ale datový objem se kterým se pracuje je úplně stejně důležitý faktor. A tahat informace o všech obrázcích, když je ve skutečnosti budeme potřebovat jen v určitých situacích a ještě jich může být hodně - to operavu není dobrý nápad. Tedy v rámci ukázkové aplikace je entita obrázek oddělená samostatná entita a mezi obrázky a galerií existuje vnější relace.
Při modelování je platí ten nejdůležitější princip: Používat vaše zkušenosti a intuici. Jet DataModel je pouze nástroj, který však ve skutečnosti není dogmatický a je pouze nutné jej použít správně.
Další podrobnosti o provázání entit a jejich subenetit se dozvíte v kapitole Vnitřní relace.