Praktický příklad na „posun meta“: Agenda Číselníky, 2.část

V předešlém článku jsme se zabývali možnými řešeními agendy zvané jako „číselníky“ alias „kódovníky“. Ukázali jsme si tři možná řešení s různými variantami posunu meta. V tomto článku navážeme na předešlý článek dalšími úvahami a doufám, že (podobně jako minule) také dalšími příspěvky v diskusi.

Statistické zastoupení řešení agendy číselníků

Nejprve bych se rád zmínil o mých zkušenostech z firem, co se týče zastoupení a četnosti řešení agendy číselníků ve firmách.

Označme si řešení takto (detailněji o řešení viz předešlý článek):

1. Hard coded = „co číselník, to tabulka“
2. Celkový posun meta = „jedna třída a dvojúrovňový strom“
3. Částečný posun meta = „dvě třídy: Číselník a jeho itemy“

Měl jsem možnost spolupracovat anebo školit velké množství firem jak v ČR, tak v SR. Protože tento příklad používám pro vysvětlení posunu meta také ve školeních (např. „Analytické modelování v praxi“), tak z toho důvodu často nad řešením agendy číselníků diskutuji a mohu si tedy dovolit relevantní odhad zastoupení daných řešení.

Pokud bych měl odhadnout procentuelní podíl nasazení daných řešení ve firmách, tak bych je odhadl takto:

1. Hard coded = „co číselník, to tabulka“: okolo 80%
2. Celkový posun meta = „jedna třída, dvojúrovňový strom“: zanedbatelný počet, řádově do pěti
3. Částečný posun meta = „dvě třídy: číselník a jeho itemy“ : okolo 20%

Rozbor

Pokusím se o malý rozbor (s tím, že samozřejmě je to pouze můj názor, a od toho je dole diskuse).

I když teoreticky se jeví řešení 2 s úplným posunem meta a uživatelskými číselníy jako velmi flexibilní a navíc s maximální opětovnou použitelností, tak přesto u něj vidím jednu obrovskou nevýhodu a tou je obtížná čitelnost v kódu. Oproti řešení 3 se ještě musí dobře hlídat, zda si ukazujeme na hlavičku číselníku anebo na item číselníku, protože jak číselník, tak jeho itemy používají tutéž entitu (nejsou typově odlišeny).

Druhý problém řešení 2 spočívá ve vyšší složitosti řešení omezujících podmínek resp. ošetření mezních stavů. Má-li být řešení flexibilní s možností přidat číselník bez zásahu do kódu (tj. přidat jej tzv. „uživatelsky“), musí být i návrh omezujících podmínek postaven také flexibilně, tedy „uživatelsky“ a nikoli „hard coded“. Jinak řečeno, nastavení omezujících podmínek musí být vytvořeno pomocí tzv. „konfigurací uživatelem“ (co je další malá agenda) a poté se musí tyto podmínky vyhodnotit opět z konfigurace (nikoliv natvrdo), tedy také flexibilně, např. pomocí polymorfismu s nasazením vzoru STRATEGY (jeden ze vzorů GOF): Každý typ podmínky má svou implementaci své metody pro svoje vyhodnocení.

Na druhou stranu existují situace, kdy musíme u hard coded řešení ustoupit a „imitovat“ posun meta. Mějme jako příklad následující zadání:

V pojišťovně jsou tři typy produktů jako typy pojištění:

Typ pojištění:
1. na život
2. na dům
3. na auto

Daný produkt pojištění je daného typu a má tedy odkaz na jeden z těchto tří prvků z typu pojištění.

V celém systému existuje N možných číselníků. Požaduje se, aby administrátor mohl nakonfigurovat, který typ pojištění potřebuje k ohodnocení který číselník (tedy toto nebude nastaveno „natvrdo v kódu“, ale uživatelsky). Pokud máme samotné číselníky očíslované (tj. v řešení 2 a 3 ano, nikoliv v 1), tak je řešení příkladu nasnadě: Zavedeme asociační třídu a potom by instance v textovém tvaru mohly vypadat nějak takto (tj. typ pojištění versus číslo požadovaného číselníku):


(1,25)
(1,38)
(1,81)
(2,4)
(2,54)
atd.

kde levá strana je typ pojištění (1,2 nebo 3) a pravá strana je kód daného číselníku (horní úroveň stromu u řešení 2 anebo prvek ze seznamu číselníků u řešení 3).

U řešení 1, tj. řešení natvrdo, musíme obsluze nabídnout seznam číselníků, což lze nejsnadněji vyřešit zavedením jednoduché pomocné doprovodné třídy (tabulky) obsahující seznam číselníků. Tato entita musí v daném řešení 1 (natvrdo) obsahovat kromě kódu a textu také další atribut (potažmo sloupec v tabulce) obsahující název tabulky (za předpokladu, že pracujeme v RDB systému). Tato třída tedy funguje jako meta-převodník mezi tím, co obsluha vybere (zobrazené instance) na straně jedné a jakou tabulku oslovit na straně druhé. Znamená to, že se následně musí s tímto názvem tabulky pracovat jako s parametrem v SQL příkazech (resp. „divoce“ poskládat SQL příkaz sloučením řetězců).

Všimněme si, že tato pomocná meta-převodníková tabulka se seznamem číselníků v našem příkladu s pojištěním u řešení natvrdo odpovídá přesně již zavedené třídě číselníků (potažmo tabulce) v řešení 3 jenom s tím rozdílem, že v řešení 3 nepotřebujeme meta-převodník (tj. není třeba zavádět další atribut jako název tabulky). Prvky číselníků jako instance v řešení 3 totiž obsahují přímo v kompozici svoje itemy číselníků. Zavedení převodníkové meta-tabulky v řešení 1 tedy vede ke kombinaci řešení 1 a 3, kdy sice existují číselníky natvrdo, ale současně existuje seznam těchto číselníků stejně jako v řešení 3.

Problém kombinatoriky v návrhu IS

V diskusi se také objevil argument pro použití řešení 1 (a nikoliv 2 a 3 „naměkko“), který se týkal požadované rozšiřitelnosti číselníků, což může být specifický problém daného číselníku, a to by byl určitě u řešení s posunem meta problém.

Pokud entita svou povahou opravdu potřebuje další atributy, které mají právo na život, potom tato entita již nespadá do našeho řešení, protože neodpovídá zadání. Naše řešení se totiž týká pouze entit ve smyslu „kódovníků“, tj. primitivní entity (kód text) přiřazující vlastnosti pomocí kódu a její interpretaci pro obsluhu textem.

Rád bych se tady zmínil o určité zvláštnosti pojmosloví v českém a slovenském jazyce, kde se pod pojmem „číselník“ skrývají (musím ale zdůraznit, že dost nepřesně!) i složité entity, které vůbec nemají povahu „kódovníku”. Typickými příklady jsou názvy jako „číselník adres“, „číselník osob“, „číselník firem“ atd. Toto označení složitých entit jako „číselník“ je sice obvyklé, není ale úplně přesné. Slovo „číselník“ je totiž odvozeno od slova “číslo”, tedy od slova “kód”. Označení „číselník“ vzniklo u složitých entit (které nejsou kódovníky) intuitivně díky povaze vazby, která je s těmito entitami nerozlučně spjata. Je to podstata těchto entit stejná jako u kódovníků: Instance z těchto tříd se nabízejí vůči jiným částem systému k tomu, aby se na ně ukázalo směrovou asociací ku jedné (většinou výběrem obsluhy), zvané “lidově” v diagramu jako „šipka s jedničkou“. V knize Analytické modelování ji nazýváme „Odkaz do seznamu“, někdy se také nazývá pouze jako „Odkaz“ („Pointer“) anebo také jako „Běžná asociace“. Tuto vlastnost „nabízet se do této vazby“ mají tyto entity totiž společné, a proto se zavedl pojem číselník i u těch entit, které nemají povahu kódovníku.

V některých případech však může být požadované rozšíření kódovníku o další atributy projevem „chyby kombinatoriky“ resp. optimalizace a rozšíření tohoto typu by nemuselo být vůbec zavedeno.

Poznámka: Je těžké posoudit v příkladech uvedených diskusi, zda se jedná o tento případ, v každém případě tento jev tady vysvětlím.

Představme si, že v řešení natvrdo zavedeme číselník (jako typický kódovník „kód + text“) X s instancemi X1 a X2 . Tímto kódovníkem budeme ohodnocovat např. entitu A. Budeme potřebovat tuto entitu ohodnocovat ještě další vlastností Y, označme instance tohoto kodovníku jako Y1 a Y2. Navíc budou existovat pouze některé povolené kombinace z X a z Y, například takto:

kombinace (X1, Y1), (X1, Y2) a (X2, Y1) povoleny,
kombinace (X2, Y2) zakázána

Nyní se naskýtají dvě možná řešení, jak danou situaci řešit: Jedno je „natvrdo“ a druhé „naměkko“.

První možností (natvrdo) je prokombinovat varianty X a Y do jedné entity. Postup by mohl být takový, že do entity X přidáme další sloupec pro Y (už to ale není kódovník) a v tomto „číselníku nekódovníku“ prokombinujeme požadované prvky podle výčtu v předešlém odstavci. Je třeba upozornit, že tímto ale entita X ztratila původní význam (už to není entita X), ale získala nový význam (už je to entita XY).

Druhé řešení by bylo „naměkko“, tedy nikoliv jako kombinace na úrovni kódu, tj. nikoliv v atributech potažmo sloupcích, ale v instancích, potažmo v řádcích v tabulce. Jak by takové řešení „naměkko“ vypadalo?

Absolventům našeho školení Analytické modelování se při vyslovení slovního spojení „Povolené kombinace“ okamžitě vynoří na mysli řešení pomocí stejnojmenného vzoru (protože se jedná o nejčastější použití asociační třídy). Znamená to, že řešení je třeba rozšířit o asociační třídu „Povolených kombinací“. V našem hypotetickém příkladu by se tedy žádný kódovník nerozšiřoval, ale zavedly by se dva kódovníky plus další entita jako asociační třída “povolené kombinace” a poté admisitrací by se zavedly instance „kdo s kým může“.

Samozřejmě nelze z několika řádků diskuse usuzovat, o kterou variantu se kde jedná. V každém případě mohou nastat ty situace, kdy je třeba specifikovat více danou entitu a rozšířit ji o další sloupce. V tom případě se ale nejedná o klasický kódovník z naší agendy, ale o obecnější entitu a nespadá tedy pod naše řešení. Na druhé straně může dojít ke kombinatorice natvrdo na úrovni kódu, kterou by mohla vyřešit asociační třída podle vzoru Povolené kombinace a kódovník jako takový by se nemusel rozšiřovat.

Závěrečné osobní hodnocení

Musím předem upozornit, že další řádky jsou hodně subjektivní povahy. Všechna tři řešení jsou totiž funkční a každé má svoje pro a proti. Protože jsem viděl nasazení všech tří variant v praxi, dovolím si zde tak trochu osobní ohodnocení.

O řešení 2 jsem psal v předešlých odstavcích a po zkušenostech v praxi bych jej moc nedoporučoval. Zbývá tedy varianta 1 a 3.

Vzhledem k tomu, že při nasazení varianty 1 natvrdo se nakonec takřka vždy zaváděla převodníková meta-tabulka se seznamem číselníků versus název tabulky, tak bych osobně jako hlavní analytik preferoval řešení číslo 3, které bude částečně „naměkko“, ale částečně také „natvrdo“ v tom smyslu, že tyto číselníky a jejich itemy budou do svých tabulek naplněny natvrdo při instalaci skriptem. K tomu je třeba zavést také asociační třídy podle vzoru „Povolené kombinace“. Toto řešení lze případně (pouze ale pokud bude třeba) rozšířit o flexibilní “uživatelské číselníky” a to bez zásahu do struktur tabulek (tj. některé číselníky budou natvrdo a zamknuty a některé budou uživatelské – naměkko).

Byl bych rád, kdybyste se vyjádřili v diskusi níže (můžete i anonymně),
těším se na vaše příspěvky dole pod článkem.


Nepřehlédněte aktuální nabídku

Sleva Pobytové kurzy ve Špindlerově Mlýně

* 3denní kurz + hotel s plnou penzí celkem za 9 980 Kč
* pro firmy až 6 účastníků zdarma


Sleva E-learningový kurz Čistý kód v OOP a Design Patterns (distanční kurz přes internet) sleva na příští běh 50%

Sleva E-learningový kurz AM PROFESSIONAL (distanční kurz přes internet), sleva 50% na příští běh

Chcete dostat upozornění na vydání nového článku? Přihlaste se k odběru novinek! Váš mail bude použit pouze k záslání novinek a k žádným jiným účelům použit nebude




Categories

About the Author:

správce a majitel Serveru objektových technologíí http://www.objects.cz

2 Comments
  1. Jiří

    Ještě bych chtěl zmínit, že číselník nemusí být vůbec v databázi, ale je řešen v kódu pomocí výčtů (např. v C# enum). Potom v DB tabulce, ze které je odkaz do “číselníku”, je pouze pole typu INTEGER, chybí FK, může být ale jiný DB CONSTRAINT.
    Mimo jiné jde o to, že v případě potřeby překládat pro UI významy hodnot číselníků do více jazyků, se neřeší na úrovni DB. Řeší to aplikace, kde se použijí např. jazykové resources.

  2. Eduard Sovák

    Na základě osobní zkušenosti dávám přednost řešení variantě 1, a to z těchto důvodů:
    – je z pohledu chápání nejjednodušší (s ohledem na přetrvávající tendence podceňovat analytickou dokumentaci a současně poměrně velkou fluktuaci členů vývojových týmů),
    – při případné dekompozici se do nových komponent stěhují celé entity, nikoli instance ve sdílených entitách.
    Mimo struktury (kód, text) obsahuje kódovník ještě zpravidla i příznak platnosti. Vzhledem k referencím z historických dat nelze neplatné položky smazat, ale je vhodné je označit jako nepoužitelné pro vznik nových referencí.
    Oceňuji vysvětlení pojmu “čistý číselník”, v mé praxi jich ale příliš mnoho není a týká se to především enumerací, tj. situací, kdy kód instance v číselníku je přímo odkazován v algoritmech a současně je vhodné mít enumeraci v DB (reporty, datové sklady). Z hlediska delší perspektivy vývoje komplexnějšího systému je vhodnější uživatelsky editovatený číselník rovnou navrhovat jako běžnou entitu, protože potřeba přidávat další atributy se v kratším či delším horizontu zpravidla objeví.

0 Pings & Trackbacks

Leave a Reply