Hlavní navigace

Názory k článku Řízení změn záznamů v relační databázi

  • Článek je starý, nové názory již nelze přidávat.
  • 7. 12. 2016 0:30

    ded.kenedy (neregistrovaný)

    Našim systémem (řešením) jsme dosáhli toho, že se nám výrazným způsobem zjednodušil vývoj.

    Reci jsou levne, ukazte mi vas kod.

    Nic ve zlem, ale bez technickych detailu jsou tohle jen reklamni plky a clanek by tak mel byt i oznacen.

  • 7. 12. 2016 8:40

    vlasta (neregistrovaný)

    Nevím, proč Vás to tak dostalo. Jde-li o reklamní plky, pak na ně nemusíte vůbec reagovat a můžete si myslet své. Nemyslím si, že ukázka kódu Vám něco řekne. To nemyslím ironicky. Jaký kus kódu byste měl namysli? A z jaké části? Dva řádky, metodu, jednu třídu, všechen kód? V první úvaze jsem se snažil poukázat na tuto problematiku. Naše řešení je takové, že spojuje všechny věci nějakým způsobem spolu dohromady (spolupracují spolu). Tzn. oddělitelnost RDB, historie, schvalovací procesy, jazykové verze a další. Vytrhnout pouze malou část pro ukázku nedává smysl. Ale zkusím uspokojit Vaši touhu po vědění :)


    public void AttachnentsClear()
    {
    ClearCollecti­on(DDCApplica­tionConstProper­tyName.Attachmen­ts);
    }

    Nicméně, nedovolil bych si popisovat řešení, které nemám odladěné a odzkoušené. Proto se nevyjadřuji třeba k použití pro web. Mé úvahy nevedou k tomu, že si máte něco koupit. To jsem po Vás nikdy nechtěl. Máte přeci možnost si to navrhnout a naprogramovat sám. Mé úvahy vedou k tomu, že dnešní používaná. řešení, jsou nepřijatelná.

  • 7. 12. 2016 9:00

    Jirka (neregistrovaný)

    Dobrý den,

    nezlobte se, ale Váš popis v podstatě říká "máme svoje fungují řešení používejte ho a jak funguje Vám neřekneme". Tento článek je o ničem, tedy vynechám-li Váš framework. Ukažte malý příklad ať ho diskutující mohou vyzkoušet. Věta "přesvědčili jsme systém, aby si myslel,že datum je aktuální" - to jistě není řešení. Apokud uspokojujete naši zvědavost dvěma metodami výše, tak si z nás asi děláte legraci. Zároveň se popíráte, neboť tvrdíte, že řešením nemáte odladěné a odzkoušené.

    Prosím o jasný příklad (funkční kód, databázové schéma), ideálně stáhnutelný (Github, Bitbucket, Vaše FTP, ....)

    s pozdravem Jirka

  • 9. 12. 2016 22:59

    BoneFlute

    > Věta "přesvědčili jsme systém, aby si myslel,že datum je aktuální" - to jistě není řešení.
    Naopak, je to řešení docela čisté ve stylu FP.

    > Prosím o jasný příklad (funkční kód, databázové schéma), ideálně stáhnutelný (Github, Bitbucket, Vaše FTP, ....)
    To mi nezní jako prosba ale jako dost drzej rozkaz. Bejt autorem článku, hodím na vás bobek.

  • 7. 12. 2016 9:17

    dustin (neregistrovaný)

    Proč není anglický název metody anglicky, tedy clearAttachments? Nebo jinou velikost písmen, nevím, jaký je standard v .NET.

    Možná se to zdá jako blbost, ale každý den řeším rádoby anglické identifikátory, nad kterými si musím lámat hlavu, co jimi vlastně chtěl autor řici...

  • 7. 12. 2016 15:06

    Murděj Ukrutrný

    Podle mě to je srozumitelné

    Attachments - z toho chápu že to může být asi seznam příloh (Attachment)
    ClearCollection - podle názvu to promázne nějaký obecný seznam

    a proč to není clearAttachments ale ClearCollection? Protože by byla pakárna pro každou entitu takže se použije generika a udělá se metoda co funguje na všech typech kolekcí.

    "krásnější" objektový zápis by ale byl DDCApplication­ConstProperty­Name.Attachmen­ts.Clear()

  • 7. 12. 2016 17:15

    vlasta (neregistrovaný)

    Usoudil jste úplně správně. Děkuji. Až na poslední řádek. Nejde o volání metody, ale o název vlastnosti "DDCApplicati­onConstProper­tyName.Attachmen­ts", kde je v konstantě uložený string "Attachments". Pod ním je vyhledána konkrétní kolekce příloh, která se má vyprázdnit.

  • 7. 12. 2016 20:09

    rv (neregistrovaný)

    dustin neprotestoval proti ClearCollection, ale proti AttachmentsClear - z jazykoveho hladiska. (AttachnentsClear je potom snad iba preklep).

  • 7. 12. 2016 10:08

    ded.kenedy (neregistrovaný)

    Naše řešení je takové, že spojuje všechny věci nějakým způsobem spolu dohromady (spolupracují spolu)

    Jakym zpusobem?

    Tzn. oddělitelnost RDB, historie, schvalovací procesy, jazykové verze a další

    Jak je resena historie?

    Jak jsou reseny schvalovaci procesy?

    Kdyz napisete, ze to mate vyresene a nenapisete jak, je pro ctenare stejne uzitecne jako klavesa Scroll Lock.

    Jaký kus kódu byste měl namysli? A z jaké části? Dva řádky, metodu, jednu třídu, všechen kód?

    Je dobrym zvykem, ze pokud chcete popsat reseni nejakeho problemu, tak si vezmete jednoduchy minimalisticky priklad, ktery dany problemem trpi, ten ctenarum predstavite a pak ukazate, jak to lze vyresit lepe, napr. s vyuzitim vaseho reseni.

    Nemyslím si, že ukázka kódu Vám něco řekne.

    Proto se k ukazkam kodu obvykle dopisuji komentare, ktere vysvetluji, co se tam deje, viz treba clanky pana Tisnovskeho.

    můžete si myslet své

    Jako by se stalo.

  • 7. 12. 2016 10:30

    Jirka (neregistrovaný)

    I vzal jsem odstavec za odstavcem, kapitolu za kapitolou a hledal. Pane autore článku pomozte mi najít ...

    kapitola: Měníme data
    … Jsem přesvědčen, že řízení změn je dnes, na konci roku 2016, zcela nezbytnou vlastností moderních IS. … názor, z pohledu mého v pohodě.

    kapitola: Reálný příklad
    …. Popis reálného příkladu návrhu a jeho problem, polemika, co je nejlepším identifikátorem, ... názor, polemika, proč ne

    kapitola: Konkrétní řešení
    … Naše řešení vychází z předpokladu, že celý systém pracuje s dnešním (aktuálním) datem. K tomuto datu vrací aktuální záznamy. Pak šlo pouze o to, jak systém přesvědčit, že jakýkoliv dodaný datum je právě tím datem aktuálním … mohl by jste se vice rozepsat, abychom měli přesnější představu? Z celého článku se jedná o nepřesnější popis Vašeho řešení a přesto dává diskutujícím možnost takřka neomezené představivosti. Když to přeženo do extremu (za což se omlouám), Mění snad uživatel datum přes nastavení hodin? Jistě ne, zkuste popsat, o co jste musel obohatit databázové schéma

    ... Druhou částí bylo implementovat schvalovací a odmítací procesy nad prováděnými změnami záznamů. Čili mít plnou kontrolu nad tím, co se v DB děje. … jistě je schvalovací process důležitý, jestli Vám umožil vědět úplně všechno, co se v DB děje, … to se mi nepozdává. Možná, že jste dokázali ovlivnit chování DB až na úroveň pohybu hlaviček na disku či konkrétní práci s buňkou na SSD. V takovém případě klobouk dolů a velmi by mě zajímal postup (pomíjím-li fakt, že se nepoužila standartní komunikace s DB)

    ... Dále jsme požadovali, aby tato schopnost nebo vlastnost, chcete-li, byla aplikovatelná na všechny tabulky v RDB … zajimavý koncept, bohužel jste nám stále neprozradil jakým způsobem.

    ... Naším systémem (řešením) jsme dosáhli toho, že se nám výrazným způsobem zjednodušil vývoj. Z kódu se nám podařilo vytěsnit vše, co se odkazovalo na konkrétní RDB….. zdá se tedy, že jste to nepsal v jazyku DB, ale jedná se o něco mezi DB a aplikací. Opět bych Vás poprosil o popsání rozhraní vašeho frameworku, to, co je přínosem

    kapitola: Postačující řešení
    … závěr s hodnocením bez uvedení konkrétních hodnot měřených vlastností zkoumaných systémů
    … Vím jen, že řešení, která se před lety nabízela, byla, z mého pohledu, nepoužitelná. Vím jen, že dnes už bez těchto nástrojů nedokážu pracovat. … prosím, jaké řešení máte namysli? Mohl by jste uvést jejich jména, reference. V čem byly nepoužitelné? Jaké vlastnosti system Vám činili obtíže. Byla by možnost připadně definovat škálu pro vlastnosti a provést vyhodnocení? Např: výkon řešení v jednotkách operací, množství redundantních dat, nutnost 1NF,2NF,3,NF ….

    Příště bych rád představil další možnosti systému DDCF při nasazení ve vícejazyčném prostředí. Společná databáze, společná data, různí uživatelé, hovořící různými jazyky. … co uvidíme příště, proč ne

    s přáním o dodatečné informace, které patrně měli být obsahem článku, Jiří

  • 7. 12. 2016 17:04

    vlasta (neregistrovaný)

    Nějak jste se rozepsal :)

    Tak k tomu "kapitola: Konkrétní řešení".

    Každý den ukládáte (do Db) nové záznamy a původní měníte (již ne tak často). Vždy ten poslední (aktuální) den vidíte všechna aktuální data tak, jak jsou tam uložena. Aplikace pracuje s aktuálním datem a časem. Existují situace, kdy budete (musíte) chtít vědět, jaký stav údajů byl ten který den. Z mnoha důvodů. Proto máme možnost přepnout aplikaci tak, aby nepracovala s datumem aktuálním, ale s datumem zadaným. K tomu datumu pak dostáváme údaje tak, jak byly tehdy uloženy. Včetně původních hodnot. Nenastavujeme systémový čas, ale čas aplikace. Aplikace má menu "Nastavit aktuální čas" a na formu je radiobutton "1. Aktuální čas" - bere aktuální systémový čas a "2. Nastavit datum" - zadáte konkrétní datum do minulosti. Podle toho, co jste nastavil, to bude použito. Takové údaje se Vám vracejí. Nevím, jestli jsem to vysvětlil pochopitelně.
    Ještě k té historii. Představte si, že jste šéf a já zaměstnanec. Před půl rokem jsem měl něco udělat. Např. obeslat zákazníky. Po tom půl roce zjistíte, že některý z nich dopis nedostal a začnete mne pérovat. A já řeknu, "šéfe, vše odešlo jak mělo a to na tuto adresu, která tehdy platila". Tím se zároveň kryjeme z obou stran (zaměstnanec - zaměstnavatel).

    Pak "schvalovací procesy".

    Berme to s rezervou :) Nikde jsem nezmiňoval žádné hlavičky disku a pod. Ale zase příklad. Zase chci vidět (k datu v historii) kolik jsem měl zákazníků (jmenovitě) se všemi souvisejícími záznamy, jaké záznamy jsou v jakém stavu (schválené, editované, schvalované, vyřazované a pod.),
    chci se podívat (v intervalu: měsíc, kvartál, ...) kolik nových záznamů vzniklo, kolik se jich vyřadilo, ...

    Stačí?

  • 7. 12. 2016 6:22

    exo (neregistrovaný)

    Za mne taky obecně vyjádřené. Zajímavý příklad z praxe, ale bez jakýchkoliv dalších přesnějších popisů řešení.

    U nás taky neustále řešíme podobné problémy. Za mne je řešení dost jednoduché. Prostě se k údajům které se mohou měnit přidá jeden, nebo vice identifikátorů, které se měnit nesmí. Nicméně je možné podle nich v systému následně vše dohledávat.

    Tedy řekněme že k pacientovi přidáme nějaký jedinečný nesmyslný identifikační kód. Něco co se bude inkrementovat automaticky vždy o jedničku 000001, 000002, ..., 999999. Ve všech ostatních částech databáze se nebudu nikdy odkazovat na RČ nebo příjmení ale na konkrétní hodnotu.

    Pak není nic jednoduššího než napsat dotaz. Najdi mi všechny úkony za pacienta 000001. A žádné problémy které popisujete už dále nemusíte řešit. Vzhledem k tomu, že kód je jen váš, není to žádné státem nebo jinými okolnostmi vynucené rozlišení, nevznikne nikdy reálný důvod toto číslo změnit. Zůstane po celou životnost vaší DB stejné.

    Co se týče měněných dat, jako je rodné číslo, jméno, příjmení atp, v těchto případech je nutné vyčlenit je do samostatné tabulky s platnostmi. Rodné číslo už tedy nebude přímo na pacientovi. ale v tabulce rodných čísel s platnostmi od do.

  • 7. 12. 2016 8:16

    vlasta (neregistrovaný)

    Nemohu s Vámi souhlasit. Vy jste nabídnul řešení v konkrétním případě. Já se snažil na konkrétním případě popsat realitu. A dále jsem uvedl, že tyto situace nastávají (mohou nastat) u každého objektu v rámci celé aplikace. Týkají se tedy každé tabulky. Děláte-li aktivně s databázemi, pak se shodneme, že obsluhujeme stovky tabulek entit s tisící sloupci. Seskupíme-li všechny sloupce (např. dle názvu), pak se jejich počet sníží. Každý z nich může měnit hodnotu. Vaše řešení říká, že pak pro každý sloupec vytvoříte novou tabulku, kam budete ukládat změny. K původním stovkám tabulek s entitami, Vám pak přibydou stovky tabulek s hodnotami. Rozumím-li tomu správně. Pak bych chtěl vidět ty selecty!
    Já uvádím, že tato situace (změny) se týkají jakéhokoliv objektu (tabulky) a říkám, že je toto jedna z nejsložitějších disciplín, konzumující nejvíce času na řešení. Nám se to povedlo zobecnit a tak sjednotit celý přístup. To vše se zjednodušilo. Z Vašeho navrhovaného řešení mám pocit, že se to spíše zkomplikovalo.

  • 7. 12. 2016 9:22

    PQK

    ... ale houby, předřečník mám pravdu.

    Dokud budete říkat "děláme to skvěle, vyřešili jsme to", tak ten článej je jen reklama a vaše příspěvky o ničem.

    Pokud byste napsal princip fungování tak by to byl technický článek. Takhle to svádí k tomu, že se něčím nechcete pochlubit. A z "K původním stovkám tabulek s entitami, Vám pak přibydou stovky tabulek s hodnotami." mi vychází, že jste se vykašlali na normalizaci a máte všechno v tabulkách možná 1NF. A takovým návrhem bych se taky nechlubil.

    To bude hodně řídká databáze, ale on to hardware unese, že?

  • 7. 12. 2016 9:40

    vlasta (neregistrovaný)

    Jsem rád, že jste se ozval. Vždy si vážím lidí, kteří znají toto řešení lépe než já a dokážou ihned odhalit jeho princip :)
    Nikde jsem neuvedl, že to děláme skvěle. Uvedl jsem a uvádím, že se na problematiku dívám trochu z jiného, poněkud nestandardního, úhlu pohledu a k tomu potřebuji i nestandardní řešení. Stále se bavím o desktopové aplikaci a RDB. Smyslem není Vám, či ostatním čtenářům, cokoliv prodat. Smyslem je, vést diskusi na dané téma. Popíšete-li Vaše zkušenosti a nastíníte-li Vaše řešení, určitě se pohneme dále, aniž bych od Vás, respektive jiných diskutujících, vyžadoval konkrétní ukázky kódu a Db modelu. Já jsem reagoval pouze na příspěvek @exo.

  • 7. 12. 2016 9:59

    PQK

    ;-)

    To víte, tak to dopadá když máte super řešení, ale nikdo neví jak funguje. To je velký prostor pro divoké spekulace. viz např. revoluční EM pohon http://www.osel.cz/9118-jak-vypada-situace-okolo-mikrovlnneho-em-pohonu.html

    Snažil jsem se Vás vyprovokovat k technické diskusy, ale zase dostávám jen plané řeči. Tak mohu zas jen spekulovat.

    Buď to nesmíte publikovat (což respektuji, jen je to třeba přiznat) a v tom případě je článek jen reklama.

    Nebo to je "nepříliš hezké řešení", máte obavy z reakcí pod článkem a i v tom případě je článek jen reklama.

    Říkáte že "Smyslem je, vést diskusi na dané téma.", tak ji veďte, prosím. Své - i pro NEdatabázistu špatné - řešení jsem popsal, o Vašem zjednodušujícím řešení jsem se ještě nedozvěděl ani slovo.

  • 7. 12. 2016 10:13

    Torquemada666

    "Smyslem je, vést diskusi na dané téma."

    To jako fakt? Tak, krucinal, dodejte neco, o cem se da rozumne bavit. System "Mame reseni a nerekneme nikomu, jak funguje" je fakt na tri veci.

    A, mimochodem: Slova "Vždy si vážím lidí, kteří znají toto řešení lépe než já a dokážou ihned odhalit jeho princip" jste si opravdu, ale opravdu mohl odpustit. I kdyz ... take o necem vypovidaji.

  • 7. 12. 2016 12:13

    Filip Jirsák

    Uvedl jsem a uvádím, že se na problematiku dívám trochu z jiného, poněkud nestandardního, úhlu pohledu a k tomu potřebuji i nestandardní řešení.
    Mohl byste napsat, co je na vašem úhlu pohledu nestandardního? To, že se v databázi ukládají historické hodnoty, je standardní věc. Snad v každé příručce, kde se řeší základy, najdete nějaký příklad na trigger, který historická data odkládá. Nestandardní je asi vaše řešení, ale o tom nevíme nic.

  • 8. 12. 2016 17:48

    NULL (neregistrovaný)

    To je fakt. Dočetl jsem až sem a dozvěděl jsem se jenom to, že aplikace defaultně vybírá záznamy podle
    <pseudo>
    datum ->List<ID.record> (třeba nějaké UID), namísto obvyklého selectu na ID (třeba nějaké UID) -> List<datum.record>.
    </pseudo>

    A ještě to že je to nějaké neobvyklé řešení . . . nic víc.

    A stejně to jenom záleží na tom, jestli má z pohledu aplikace větší smysl zobrazovat data nejprve k danému datu a nebo spíš první radši všechna data vzhledem k uživateli a pak až třídit podle jejich data (času)

  • 7. 12. 2016 11:16

    Karel (neregistrovaný)

    Jen bych doplnil, že takto se to běžně řeší v logistických, výrobních, ERP apod. systémech. Dané věci je přiřazeno konkrétní, neměnné a unikátní ID. Obvykle sekvenční číslo. A pak se v jiné tabulce sledují reference. Těch může být více, mohou mít časovou platnost, mohou být navázané na další číselníky, například číselník zákazníků.

    U příkladu s rodným číslem mám prostě člověka s ID 1234. A v jiné tabulce mám napsáno, že člověk 1234 (klíč člověka) měl rodné číslo (typ reference) od 1.1.1990 do 12.12.2014 (časová platnost) 930101/1234 (hodnota reference). Pod tím mám záznam, že člověk 1234 měl rodné číslo od 13.12.2014 do nekonečna 935101/4567. Stejně tak sleduji co měl kdy za zdravotní pojišťovnu, jak se jmenoval, kde bydlel.

    V případě kusovníku položek v ERP systému pak reference k položce 1234 mohou být:
    Model number, od 1.1.2000 do nekonečna M1234
    Čárový kód, od 1.1.2000 do nekonečna 1P1234
    Číslo položky zákazníka, zákazník 11, od 1.1.2000 do nekonečna M6x30
    Číslo položky zákazníka, zákazník 12, od 1.1.2000 do 31.12.2015 M6x30
    Číslo položky zákazníka, zákazník 12, od 1.1.2016 do nekonečna "šroub M6 D30 válcová hlava křížový"

    Jak je zřejmé, jedná se o úlohu velmi běžnou a řeší se jak píšete: unikátním nic neříkajícím ID. Případné reference (rodné číslo, číslo položky zákazníka, sledovací číslo zásilky atd.) se řeší samostatnou tabulkou, kde je reference uložena pro relevantní identifikaci. Ta obvykle sestává ze sady ID, protože jen někdy stačí ID primárního objektu. Častěji musíte přidat i něco dalšího, například id zákazníka, id dodavatele, id přepravce atd. Framework tohle není schopen sám uhádnout, vždy se to musí nakonfigurovat ručně. Stejně tak se ručně musí uzpůsobit formuláře, sestavy atd.

  • 12. 12. 2016 11:45

    comodoro (neregistrovaný)

    Děkuji, tento příspěvek mi dal více informací než článek, za podstatně menší časové náklady:)

  • 13. 12. 2016 9:16

    v.sp (neregistrovaný)

    To mi připomělo jeden zajímavý problém z bankovního systému: ani tohle unikátní ID neřeší všechno. Co když mi někdo ukradne občanku a založí si na ní účet/úvěr? Když tohle banka zjistí, musí klienta rozdělit na dva. Jeden (já) bezproblémový, druhý (ten zloděj) ve vymáhání, policejním vyšetřování apod. A o tom druhém přitom neví nejspíš vůbec nic (jméno, adresu, RČ).

  • 7. 12. 2016 8:39

    Martin (neregistrovaný)

    Tento článek je PR. Odkazuje na konkrétní framework bez toho, aby popsal obecně použité principy. Neřeší tedy jak na to, ale doporučuje na řešení využít konkrétní produkt (mimochodem v .NET).

  • 7. 12. 2016 10:13

    Palo (neregistrovaný)

    Tak neviem ci to autor mysli vazne alebo si z nas fakt striela. Take problemy ako su nacrtnute v clanku riesime v 'biznis level' uz desiatky rokov. Na nastoleny problem neexistuje jedine riesenie. Technicke riesenie silne zavisi od dalsich detailov ku ktorym sa pan autor ani nepriblizil. Takze univerzalne technicke prevedenie tiez neexistuje. Pan autor sa nam tu snazi nahovorit ze nasiel univerzalnu odpoved na verzovanie dat v DB. Take riesenie neexistuje. To som pochopil pred 25 rokmi. Je to iba nedostatok skusenosti a jeho riesenie je velmi specificke, neuniverzalne a naviac bez detailov toho ako je to technicky realizovane absolutne bezcenne aj ako reklamny clanok lebo takuto ciernu skrinku nikto nekupi.

  • 7. 12. 2016 11:31

    Karel (neregistrovaný)

    Ale to jste nepochopil článek. Vy tvrdíte, že univerzální technické řešení neexistuje. Ale pan autor tvrdí, že existuje a že ho má a autor toho řešení ho každému za peníze rád ukáže. A jak je vidět z reakcí, funguje to. Prostě je nás tu teď plno zvědavých, kteří sice na perpetuum mobile nevěříme, ale přesto chceme ten zázračný stroj vidět. Bohužel autor nám ho ukázat nechce a naopak vybízí, abychom mu nejprve my ukázali stroje naše. A redakce to trpí.

  • 7. 12. 2016 12:22

    Palo (neregistrovaný)

    Riesenie sice existuje ale su mozne dva scenare:
    - Pan autor co sa tyka poziadaviek este nevidel hada cuvat a kona grdzat (ja uz hej)
    - Alebo je to univerzalne riesenie proste na houby a to posudit nevieme kedze detaily tam nie su
    Neviem co z toho je horsie ale ani jedno dobre.

  • 7. 12. 2016 10:41

    bez přezdívky

    Moc nechápu tu jednoznačně odmítavou kritiku
    - autor popsal několik obecných problémů, se kterými je potřeba se při vývoji databázových aplikací potýkat
    - deklaruje, že vyvinuli framework zaměřený na jejich řešení
    - připouští, že nejde o nejlepší možné řešení, ale že jim pro jejich účely funguje a vyhovuje
    - nevšiml jsem si, že to někomu vnucuje. Zkuste se něco dovědět o jakémkoliv frameworku tak, aby to trochu neobsahovalo jeho propagaci
    - popsal jakým způsobem řeší řízení změn z pohledu klienta. Jak je to implementované celkem pochopitelně v článku tohoto rozsahu popsáno není
    - žádný framework není vhodný v každé situaci. Vždy je nutné zvážit jeho konkrétní použití, k tomu je ale nutné o něm něco vědět.
    - ano, článek mohl být napsaný jinak. Zkuste, kritici, napsat nějaký vlastní.
    Rozhodně se jedná o zajímavé téma a o prezentovaném řešení se rád něco dalšího dozvím. Pokud podle mého názoru zbytečně negativní ohlasy autora neodradí od pokračování.

  • 7. 12. 2016 10:48

    Jirka (neregistrovaný)

    Dobrý den,

    bylo by dobré, kdyby autor naznačil, jakým způsobem ten mezikus mezi DB a aplikací funguje a jak muselo být obohaceno schéma DB. To je asi všechno, co diskutující požadují.

    ať se daří, Jirka

  • 7. 12. 2016 18:01

    j (neregistrovaný)

    Autor popisuje problem, kterej prakticky vsechny aplikace, ktery muzou narazit na potrebu se podivat "co tam bylo predtim" resej uz desitky let.
    Autor ani slovem nezminuje, jak ze to ten jeho uchvatnej framework ten problem resi, jen si pochvaluje, ze se to deje jaksi samo, nepise na zaklade prenosu subprostorovych vln.
    Autor zcela zjevne nema vubec ani predstavu (ani teoretickou), jak se v realne firme o vice nez 2 lidech s daty pracuje. "system schvalovani" ...

  • 7. 12. 2016 16:33

    vlasta (neregistrovaný)
    Zdravím.

    Pokusím se odpovědět jedním příspěvkem :) Čili, tématem bylo poukázat na problematiku tak, jak ji chápu já a na co já kladu důraz. Respektive oslovit ty, kteří tento problém při své práci identifikovali a (nebo) se jej snaží řešit.

    Byl jsem účastníkem mnoha projektů. Problém na KAŽDÉM z nich byl, že jsme VŽDY řešili to samé, vždy od začátku, pokaždé jinak s větší či menší mírou nějakého výsledku. Můj názor je, že ať řeším jakoukoliv databázovou aplikaci, s jakýmkoliv tématem, nacházím opakující se vzory. Viz. předchozí věta. Všechny takové aplikace mají společné entity: fyzické osoby, právnické osoby, adresy, číselník obcí, číselník názvů ulic, číselník pohlaví, ... a asi dalších (dejme tomu) 70 entit. Všechny tyto entity mohou být tedy uplatněny prakticky v každém projektu. Pro každý nový projekt nemusím vymýšlet základy. Toď 1. tvrzení.

    Dále pak. Vždy se vyskytne situace, týkající se změn záznamů, jejich historie a pod. Jde o další opakující se vzor, který je dále využitelný. Problém je vymýšlet to jednou pro jednu entitu, jindy pro druhou atd. Pokaždé trochu jinak. Dal-li by se navrhnout nějaký Db model (struktura), který by byl obecný a splňoval všechny MÉ (ne vaše) požadavky, šlo by o zjednodušení celé problematiky. A jde-li to, pak to implemenovat na všechny entity v Db. Tedy navrhnout takovou strukturu tabulek, aby to bylo snadno proveditelné, pochopitelné a realizovatelné. To je ta část, nacházející se v Db. Této filosofii se musí navrhnout i odpovídající struktura business objektů. Toď 2. tvrzení.

    3. tvrzením je, že data mohou být sdílena v rámci jedné Db, jedné aplikace, která s Db pracuje. A to tak, aby s ní mohli pracovat uživatelé např. v Česku, Německu, Polsku a pod. Podotýkám, že současně. Tedy tak, aby měl Čech data v češtině, Němec v němčině, Polák v polštině atd. Nebavím se o popiscích a hláškách! Tento bod bych (i z vaší strany) teď moc nepitval. Rád bych jej popsal v další úvaze a proto se dnes k němu nebudu vyjadřovat.

    Pokud to všechno mám, tak by bylo vhodné nezaměřit se na konkrétní Db, ale navrhnout to tak, aby Db byla snadno zaměnitelná. Toď 4. tvrzení.

    Toto základní schématické rozdělení slouží k tomu (MNĚ, NE VÁM), jak stále neobjevovat kolo. Zjednodušit a zrychlit vývojové práce. Mám-li hotové tyto základy, mohu je používat stále znovu a znovu a znovu .... a stejně a stejně a ....

    Této problematice se věnuji přes 11 let. Posledních 6 let pak na plný úvazek. Jelikož neznám ani jednoho z diskutujících, je přinejmenším zvláštní, obvinit mě z toho, že vám něco prodávám. Stejně tak podsouvat mi "vykašlání se na normalizace" a "tabulky v 1. NF". Nezlobte se, ale co si já chci koupit nebo potřebuji koupit, to neovlivní žádná reklama. Ani typu "Vy zíráte, my zíráme, zářivě bílé prádlo.". To samé předpokládám i u vás. Nehledě na to, že když to nechci, tak to ani nečtu. Natož pak, abych se k tomu vyjadřoval. K tomu vás nikdo nenutí. A jak napsal @karel. Řešení již zná a má.

    Celý systém je založen jak na Db, tak i na těch business objektech. Jde přinejmenším o 6 DDL, které musíte ve vašem případném projektu použít. Proto není snadné ukazovat kousky kódu. Asi vám nic neřeknou. Tu první ukázku kódu je třeba chápat jako ironii, za což se omlouvám. Dále, nezlobte se, ale náš vývoj také něco stojí. Rozumný člověk pochopí, že není možné ukazovat strukturu tabulek jen tak. Takže lze těžko popisovat implementaci, stahovat si zdrojáky z FTP a pod. Nejedná se o Open Source. Tabulky můžeme definovat tak, že mají systémovou část a datovou část. Systémová část řídí různé stavy záznamu. Datová část - to jsou už vlastní data (hodnoty a FK). Používáme uložené procedury (MS SQL). Dají se používat i parametrizované dotazy. To není problém.

  • 7. 12. 2016 17:46

    backup (neregistrovaný)

    no tak se to alespon trochu vyjasnuje.

    Kolem roku 2000 jsem hledali pro jednoho zakaznika nahradu stavajiciho ERP systemu, na ktery byly kladeny specialni pozadavkay - dnes se tomu rika 'multitenancy'. Jednoduse receno, nakupci pracoval dopolende pro firmu A - videl data firmy A a odpoledne pracoval pro firmu B (dcerina spolecnost) a pracoval s daty firmy B.
    Vsechna ta data byla spolecne v tabulkach (tedy ne jak tenkrat obvykle, tabulky pro data firmy A , tabulky dat firmy B ...atd.)
    Jedina firma, ktera to tenkrat mela na systemove urovni zpracovane byla firma ProAlpha (https://www.proalpha.com/en/).

    Ti meli take vsechny tabulky plne systemovych informaci, co se komu ma ukazovat (take tim samozrejme resili i ty ruzne jazyky). Aplikacni vyvojar v tom frameworku toho systemu ProAlpha nemusel nic zvlastne programovat, vsechny ty ruzne verze dat se zobrazovaly podle toho, jak se ktery uzivatel prihlasil a jak byl jeho account konfigurovan.

    Samozrejme, ze kazdy SQL dotaz mel krome vlastni dotazove logiky radu dalsich 'where', ktere zohlednovaly prave aby uzivatel videl ta patricna data. Kupodivu to system nijak zvlast nezpomalovalo.
    Podle me ale firma ProAlpha mela tu vyhodu, ze pouzivala (a pouziva) databazi Progress , kde pouzivali pro dotazy ten jejich 4GL jazyk - tedy vpodstate proceduralni dotazovani. Proto jejich system nemohl s zadnou jinou databazi fungovat. Jestli by to slo s nativni SQL si uprimne receno nedovedu predstavit.

    Takze si myslim, ze autor zrovna nemusel vymyslet perpetuum mobile, takove pokusy v obecnejsi rovine zde uz byly.

  • 7. 12. 2016 18:06

    j (neregistrovaný)

    A potom se zjisti, ze staci do policka filtru pridat %'& .... a zobrazej se libovolny data ;D. Defakto sem jeste nevidel system, kterej by resil zabezpeceni jinak, nez spolehanim se na to, ze uzivatel je BFu a o SQL vzivote nezavadil.

  • 8. 12. 2016 0:23

    ded.kenedy (neregistrovaný)

    Čili, tématem bylo poukázat na problematiku tak, jak ji chápu já a na co já kladu důraz. Respektive oslovit ty, kteří tento problém při své práci identifikovali a (nebo) se jej snaží řešit.

    A nebylo by lepsi si proto zalozit blog a tam psat blogiskove uvahy? Mozna to bude prekvapive, ale vetsina ctenaru na tento web chodi kvuli technickym informacim, a ne kvuli osobnim uvaham.

    Byl jsem účastníkem mnoha projektů. Problém na KAŽDÉM z nich byl, že jsme VŽDY řešili to samé, vždy od začátku, pokaždé jinak s větší či menší mírou nějakého výsledku.

    Bajecne, takze ctenari budou opet resit ten samy problem vzdy od zacatku bez ohledu na to, jestli vas clanek vysel nebo ne. Nejak mi nedochazi, proc to vlastne pisete? Co tim chcete vyresit?

    Nezlobte se, ale co si já chci koupit nebo potřebuji koupit, to neovlivní žádná reklama. Ani typu "Vy zíráte, my zíráme, zářivě bílé prádlo.". To samé předpokládám i u vás.

    Tady nejde o nejake ovlivnovani. Tady jde o skutecnost, ze se evidentne jedna o reklamni clanek, jelikoz text popisuje nejaky problem a jako reseni nabizi POUZE vas produkt. Ze zakona by takova reklama mela byt oznacena.

    Jde přinejmenším o 6 DDL, které musíte ve vašem případném projektu použít. Proto není snadné ukazovat kousky kódu. Asi vám nic neřeknou.

    Jak jsem psal vyse, ke kodu lze napsat komentar. Vsimnete si, ze napriklad v clancich Pavla Tisnovskeho jsou popsany cele procesory pro ctenare srozumitelnou formou. Vazne si myslite, ze popsat procesor je jednodussi nez 6 DDL?

    Dále, nezlobte se, ale náš vývoj také něco stojí. Rozumný člověk pochopí, že není možné ukazovat strukturu tabulek jen tak

    Vazne? A co by si kdo na tech hlavickach vzal? Takze jedina moznost, jak vyresit vami popsany problem je bud to vymyslet sam, nebo si koupit vase reseni?

    Nejedná se o Open Source.

    A proc to tedy pisete na server zamereny na open source?

    stahovat si zdrojáky z FTP

    Vazne? V roce 2016? Nekdo pouziva FTP pro distribuci zdrojaku?

  • 7. 12. 2016 17:48

    bez přezdívky

    Clanek jsem nepochopil a nebo je nicnerikajici. Po par odstavcich jsem zacal spis hledat nejake reseni popisovaneho problemu, ale nenasel.

    Jedna otazka: slozene indexy vypadaji jak? Ve vsech je cas zmeny? Takze vzdy jde o fullindex scan?

  • 7. 12. 2016 17:54

    j (neregistrovaný)

    ... no potes ...

    "prakticky vůbec nemáme pod kontrolou, co se s údaji v DB děje"
    "Správnost vkládaných nových záznamů teď pomineme."
    Neprekvapive je naprosto nejzasadnejsi ulohou zpracovani zcela libovolnych dat prave spravnost zadavanych udaju, vse ostatni je vedlejsi.

    "Úmyslné změny jsou změny provedené se záměrem škodit."
    Vazne? Takze treba nazev firmy zmeni uzivatel neumyslne, kdyz se zakaznik prejmenuje ... chmm..

    "Váš systém ale pacienta se starým rodným číslem už nezná"
    To je zajimave, mam v systemu tisice firem, a mnohe z nich maji nekolik ruznych IC, a DIC... a system zna vsechny.

    "Druhou částí bylo implementovat schvalovací a odmítací procesy"
    Jisteze ... ty tisice zmen od desitek (v male firme) uzivatelu bude schvalovat nejspis dalsich nekolik stovek schvalovacu, to aby kazdou zmenu radne overili a proverili.

    " nemusel to stále a stále složitě vymýšlet a nestandardně implementovat"
    Tj ... ono totiz udelat (a to aniz bych resil pripadne dalsi dusledky) trigger nad kazdou tabulkou, a vedle toho tabulku xyz_hist ... do ktery se insertne puvodni zaznam vyzaduje od programatora, aby to neustale resil. Pricemz podobnych postupu se da behem par minut vymyslet desitky. A voiala, ono to i pri vyuziti transakci (ja vim, sprosty slovo) garantuje, ze se zaznam vytvori a nebo update failne. To je zazracna technologie co?

    "Konkrétní řešení"
    Kde ze je popis toho konkretniho reseni? ...

  • 8. 12. 2016 11:35

    vlasta (neregistrovaný)

    Hmm, zřejmě se stále nechápeme. Ono totiž udělat triger nad každou tabulkou a vedle toho posadit tabulku xyz_his vymyslí téměř každý. Nic složitého. A transakce znáte pouze Vy? Děkuji, že jste mně na ně upozornil. Právě tento způsob není pro popisované užití vhodné. Stejně tak ty desítky způsobů, jichž jste vysypal z rukávu během par minut.

    Stovky schvalovačů také není třeba :) Nikde o tom není zmínky. Uvedl jsem, že schvalování a historii chci mít nad každou tabulkou. Tzn., že proces mohu (přes GUI) jednoduše zapínat i vypínat, nastavit až 39 úrovní schvalování a pod.

    Úmyslnou změnou může být např.: Prodáváte "ložiska". Za uplynulé období jste jich prodal, dejme tomu, 5000ks. Já Vám název změním na "příruba". Pokud se podíváte, vidíte, že jste prodal 5000 "přírub", na skladě máte 2 ks. Objednáte si dalších 5000 ks přírub. Budou Vám k čemu? Je to napsané ve zkratce. Pro Vás.

    Správnost zadávaných údajů je zásadní. Jak mi po čase potvrdíte, že Váš systém pracuje se správnými údaji? Viz. příklad výše? Jsem Váš klient a mám takový požadavek. Vyřešte jej.

  • 8. 12. 2016 14:25

    j (neregistrovaný)

    "Právě tento způsob není pro popisované užití vhodné"
    Proc ...
    Ocekavam zcela konkretni odpoved, ne PR blabol. Zatim sem nabyl presvedceni, a zjevne nejsem sam, ze bych rozhodne tohle tajuplne a magicke reseni nechtel, a to ani zdarma.

    O tom jak podobni "uzasne a genialni reseni" dodavatele pouzivaji transakce v databazi se presvedcuju dnes a denne.

  • 7. 12. 2016 21:49

    gnat (neregistrovaný)

    Možná by stálo za zvážení věnovat větší péči výběru RDBMS, než implementovat podmnožinu funkcionality Oracle Flashback svépomocí.

  • 7. 12. 2016 22:17

    Filip Jirsák

    Oracle Flashback podle mne řeší něco jiného. Pokud vím, řeší pohled na data v určitém okamžiku historie databáze, díváte se na data platná k určité transakci. To, co se zřejmě snaží popsat a zároveň utajit autor článku, je zobrazení historických dat, ale ne z hlediska historie databáze, ale z hlediska historie světa. Když přijde pacientka k očnímu lékaři po třech letech a lékař si zaktualizuje, že se před třemi lety vdala a změnila příjmení, bude ta změnová transakce mít dnešní datum provedení, ale bude měnit údaje o období před třemi lety. Pokud si vezmu včerejší stav databáze, bude tam původní příjmení, ale pokud se uživatel bude ptát (neřešme proč) „jak se pacientka jmenovala včera“, má dostat už změněné příjmení.

  • 8. 12. 2016 10:37

    Palo (neregistrovaný)

    Snazite sa o odpoved na neexistujucu otazku. Co a ako riesit zalezi od poziadaviek. Rozne institucie napriklad vyzaduju aby nieco bolo platne az od buduceho obdobia. Potrebujete to nastavit tak aby nieco bolo platne az o mesiac. Potrebujete riesit skutocne preklepy, to znamena ze nechcem novu verziu udajov ale skutocne 'opravit' (zmenit bez vytvorenia verzie) zle zadany udaj. Niekde potrebujem historiu zmien ale iba z dovodu auditu nema sa v tom vyhladavat. Niekde potrebujem vazby aktualizovat to zname zaznamy odkazujuce na stary udaj 'updatnut' na aktualne, niekedy potrebujem zachovat stare vazby na stare verzie a nove uz robit do novej verzie. Niekedy potrebujem aby system zachovaval stare a aj zobrazoval ale zaroven upozornil ze uz existuje aktualnejsia verzia zaznamu a umoznil na 'klik' update. A to vsetko moze byt roznym sposob pozadovane v jednej a tej istej aplikacii. Iba ja tu zijem v tomto komplikovanom svete sialenych klientskych poziadaviek?

  • 8. 12. 2016 13:29

    gnat (neregistrovaný)

    Ale to je přece triviální úloha. Stačí na to tabulka s identifikátorem atributu, jeho hodnotou, timestampem změny a timestampem začátku platnosti. Můžu pak triviálně získat log změn i hodnotu platnou v konkrétním čase.

  • 8. 12. 2016 14:08

    backup (neregistrovaný)

    a jestli jsem tomu dobre porozumnel, tak autoruv framework tohle dela automaticky u vsech tabulek a jeho business objekty a GUI s temito systemovymi udaji (napr. vami uvedene timestampy) pocitaji a vyuzivaji je.

  • 8. 12. 2016 14:36

    Filip Jirsák

    Ano, je to triviální úloha. Autor tvrdí něco jiného, ale nenapsal ani proč by tohle nefungovalo, ani jak by to řešil on (tedy kromě toho, že má nějaký nástroj, který „to řeší“, ale nevíme jak).

  • 13. 12. 2016 9:09

    v.sp (neregistrovaný)

    Takže v Oraclu 12c "temporal validity". Což tedy není o moc víc, než sloupce valid_from a valid_to.

  • 8. 12. 2016 13:20

    Ondřej Novák

    Přejděte na NoSQL a insert only DB a přestanete řešit historii.

    (každá změna = nový záznam do DB, je pak na DB, aby v pohledech zobrazovala jen poslední platné záznamy)

  • 12. 12. 2016 13:47

    dannak (neregistrovaný)

    "...je pak na DB, aby v pohledech zobrazovala jen poslední platné záznamy"
    Nejsem si jist, ze Vasemu prispevku rozumim spravne, ale vtip je IMHO prave v tom, ze tohle vy VZDYCKY nechcete; vetsinou jo, ale nekdy taky ne. Tzn. ten pohled by asi mel brat v uvahu nejake datum, ktere nejspis prijde zeshora z GUI/AS - aktualni, historicke, nebo treba zadne ?
    Prave proto, si tedy myslim, potrebujete moznost pristupu - tzn. hledat a zobrazovat, mozna i menit - i k historickym zaznamum.

  • 8. 12. 2016 13:45

    SB (neregistrovaný)

    Autore, neuvažoval jste o politice? Mluvit 20 minut a říci hovno, to taky neumí kdekdo...

  • 8. 12. 2016 14:40

    MikaMan (neregistrovaný)

    Pánové.

    Nerad cokoliv komentuji. Autor popisuje řešení určité problematiky, která mne dost zajímá. Mohu říci, že popisované téma není snadné uspokojivě vyřešit a sami s tím máme dost práce. Z vašich reakcí vidím, že jste k tématu ještě nedorostli. Autora se snažíte kamenovat na prkotinách, aniž byste pochopili popisovaný princip.

    Proto nechápu, kde se ve vás všech bere tolik agresivity. U obou článků jsem si nevšiml, že by nám bylo cokoliv vnucováno.

  • 9. 12. 2016 10:50

    vlasta (neregistrovaný)

    Dobře. Máte pravdu. Přiložím nějaké části kódu.

    Dejme tomu, že budeme dělat číselníky. To jsou vlastně předdefinované výčtové typy. Z 90% mají stejnou strukturu. U pár typů jsou pak nějaké property navíc. Nikdy ne méně. Pro číselníky, tak i ostatní typy, jsou předdefinovaní abstraktní předci, z nichž se dědí. Uděláme si nejprve svého abstraktního předka pro větev číselníků, z něhož budou následně dědit všechny naše classy (pro číselníky). Chceme, aby všechny číselníky měly přílohy. Implementujeme rozhraní příloh. Pak inicializujeme referenční objekty. Pro všechny typy číselníků jsou stejné:

    public abstract class AncestorDDCBa­seListData : BaseDDCDbListOb­ject, IDDCAttachments
    {
    protected AncestorDDCBa­seListData(Ba­seDDCObject holder)
    : this(holder, null) { }
    protected AncestorDDCBa­seListData(Ba­seDDCObject holder, DataRow row)
    : base(holder, row)
    {
    initProperties();
    }

    public DDCCollectionAt­tachment Attachments
    {
    get
    {
    if (this.Mid == null)
    return null;

    SysPropertyRef propRef = GetPropertyRef­Collection(DDCAp­plicationConstPro­pertyName.Attachmen­ts);

    DDCCollectionAt­tachment coll = propRef.Collection as DDCCollectionAt­tachment;

    if ((coll != null) && (coll.Count > 0))
    return coll;

    propRef.Proper­ties[DDCAppli­cationConstPro­pertyName.Mid]­.Value = this.Mid;

    FillPropertyCo­llection<DDCAt­tachment>(prop­Ref, DDCApplication­ConstProperty­Name.Attachmen­ts);

    return coll;
    }
    }
    public void AttachmentsClear()
    {
    ClearCollecti­on(DDCApplica­tionConstProper­tyName.Attachmen­ts);
    }
    public byte[] Image
    {
    get
    {
    if (this.AttachmentUid == null)
    return null;

    SysPropertyRef propRef = GetPropertyRef(DDCAp­plicationConstPro­pertyName.Ima­ge);

    if (propRef.Value != null)
    return propRef.Value as byte[];

    propRef.Proper­ties[DDCAppli­cationConstPro­pertyName.Attachmen­tUid].Value = this.AttachmentUid;

    DDCSingleBinaryData sbd = GetPropertyOb­ject<DDCSingle­BinaryData>(prop­Ref, DDCApplication­ConstProperty­Name.Image);

    if ((sbd != null) && (sbd.BinaryData != null) && (sbd.BinaryDa­ta.Length > 0))
    {
    propRef.Value = sbd.BinaryData;
    base.DataWasChanged = false;

    return propRef.Value as byte[];
    }
    else
    return null;
    }

    }
    private void initProperties()
    {
    SysPropertyRef propRef;

    propRef = new SysPropertyRef(this, DDCApplication­ConstProperty­Name.Image, null, DDCApplication­ConstQueryName­.AAAAAAAAAAAA­A, ExtendCommandMet­hod.ExecuteRe­ader, typeof(DataTable), typeof(DDCSin­gleBinaryData));
    propRef.Proper­ties.Add(new SysPropertyClr(prop­Ref, DDCApplication­ConstProperty­Name.Attachmen­tUid));
    base.AddProper­ty(propRef);

    propRef = new SysPropertyRef(this, DDCApplication­ConstProperty­Name.Attachmen­ts, null, DDCApplication­ConstQueryName­.AAAAAAAAAAAA­A, ExtendCommandMet­hod.ExecuteRe­ader, typeof(DataTable), typeof(DDCAttachmen­t));
    propRef.Collection = new DDCCollectionAt­tachment(this, DDCApplication­ConstProperty­Name.Attachmen­ts);
    propRef.Proper­ties.Add(new SysPropertyClr(prop­Ref, DDCApplication­ConstProperty­Name.Mid));
    base.AddProper­ty(propRef);

    propRef = this[DDCAppli­cationConstPro­pertyName.Lan­guage] as SysPropertyRef;
    if (propRef != null)
    {
    propRef.QueryName = DDCApplication­ConstQueryName­.AAAAAAAAAAAA­A;
    propRef.Instan­ceType = typeof(DDCLis­tLanguage);
    }

    propRef = this[DDCAppli­cationConstPro­pertyName.Maker] as SysPropertyRef;
    if (propRef != null)
    {
    propRef.QueryName = DDCApplication­ConstQueryName­.AAAAAAAAAAAA­A;
    propRef.Instan­ceType = typeof(DDCMaker­Checker);
    }

    propRef = this[DDCAppli­cationConstPro­pertyName.Chec­ker] as SysPropertyRef;
    if (propRef != null)
    {
    propRef.QueryName = DDCApplication­ConstQueryName­.AAAAAAAAAAAA­A;
    propRef.Instan­ceType = typeof(DDCMaker­Checker);
    }

    propRef = this[DDCAppli­cationConstPro­pertyName.Notes] as SysPropertyRef;
    if (propRef != null)
    {
    propRef.QueryName = DDCApplication­ConstQueryName­.AAAAAAAAAAAA­A;
    propRef.Instan­ceType = typeof(DDCNote);
    }

    propRef = this[DDCAppli­cationConstPro­pertyName.Type­Source] as SysPropertyRef;
    if (propRef != null)
    {
    propRef.QueryName = DDCApplication­ConstQueryName­.AAAAAAAAAAAA­A;
    propRef.Instan­ceType = typeof(DDCLis­tTypeSource);
    }

    propRef = this[DDCAppli­cationConstPro­pertyName.Type­Table] as SysPropertyRef;
    if (propRef != null)
    {
    propRef.QueryName = DDCApplication­ConstQueryName­.AAAAAAAAAAAA­A;
    propRef.Instan­ceType = typeof(DDCLis­tTypeTable);
    }

    propRef = this[DDCAppli­cationConstPro­pertyName.Dis­cretion] as SysPropertyRef;
    if (propRef != null)
    {
    propRef.QueryName = DDCApplication­ConstQueryName­.DiscretionGet­ByUid;
    propRef.Instan­ceType = typeof(DDCLis­tDiscretion);
    }
    }
    }

    Říkáme, jakým dotazem si o data mají požádat a s jakým návratovým typem mají počítat. Pokud začínáme, nemáme většinou ani dotazy a ani všechny potřebné typy. Chybí-li dotaz, použijeme "DDCApplicati­onConstQueryNa­me.AAAAAAAAAA­AAA". Chybí-li konkrétní typ, použijeme "UnderConstruc­tion". To proto, abych si byl jistý, že jsem inicializaci provedl (nezapomněl jsem na ni), ale v danou chvíli ještě nebyly k dispozici správné údaje. Pak stačí najít reference k fake názvu nebo fake typu a zaměnit je za konkrétní hodnotu.

    Přípravu máme a můžeme se pustit do výroby prvních číselníků. Základní číselník má identickou strukturu jako předek:


    public class DDCListTypeUrgency : AncestorDDCBa­seListData
    {
    public DDCListTypeUr­gency(BaseDDCOb­ject holder, DataRow row)
    : base(holder, row)
    {
    initProperties();
    }

    private void initProperties()
    {
    SysPropertyRef propRef;

    propRef = this[DDCAppli­cationConstPro­pertyName.Paren­t] as SysPropertyRef;
    if (propRef != null)
    {
    propRef.QueryName = DDCApplication­ConstQueryName­.TypeUrgencyGet­ByUid;
    propRef.Instan­ceType = typeof(DDCLis­tTypeUrgency);
    }

    propRef = this[DDCAppli­cationConstPro­pertyName.Chil­d] as SysPropertyRef;
    if (propRef != null)
    {
    propRef.QueryName = DDCApplication­ConstQueryName­.TypeUrgencyGet­ByParentUid;
    propRef.Instan­ceType = typeof(DDCLis­tTypeUrgency);
    }

    propRef = this[DDCAppli­cationConstPro­pertyName.RowOl­d] as SysPropertyRef;
    if (propRef != null)
    {
    propRef.QueryName = DDCApplication­ConstQueryName­.AAAAAAAAAAAA­A;
    propRef.Instan­ceType = typeof(DDCLis­tTypeUrgency);
    }

    propRef = this[DDCAppli­cationConstPro­pertyName.Row­New] as SysPropertyRef;
    if (propRef != null)
    {
    propRef.QueryName = DDCApplication­ConstQueryName­.AAAAAAAAAAAA­A;
    propRef.Instan­ceType = typeof(DDCLis­tTypeUrgency);
    }
    }
    }

    Udělali jsme číselník "DDCListTypeUr­gency" (typy naléhavost). Typ známe, tak jsme jej použili. Dotazy ještě nemáme, dali jsme fake string. To bylo jednoduché. Teď uděláme číselník jazyků, který má nějaké property navíc:

    public class DDCListLanguage : AncestorDDCBa­seListData
    {
    public DDCListLangua­ge(BaseDDCObject holder, DataRow row)
    : base(holder, row)
    {
    initMe(row);
    }
    private void initMe(DataRow row)
    {
    initProperties();

    if (row != null)
    fillProperties(row);
    }
    public virtual Int32? CultureIdentifier
    {
    get { return (Int32?)this[DD­CApplicationCon­stPropertyName­.CultureIdenti­fier].Value; }
    set { this[DDCAppli­cationConstPro­pertyName.Cul­tureIdentifier]­.Value = value; }
    }
    public virtual string CodeLanguage
    {
    get { return (string)this[DDCAp­plicationConstPro­pertyName.Code­Language].Valu­e; }
    set { this[DDCAppli­cationConstPro­pertyName.Code­Language].Value = value; }
    }
    public virtual string CodeRegion
    {
    get { return (string)this[DDCAp­plicationConstPro­pertyName.Code­Region].Value; }
    set { this[DDCAppli­cationConstPro­pertyName.Code­Region].Value = value; }
    }
    public virtual string CodeSuffix
    {
    get { return (string)this[DDCAp­plicationConstPro­pertyName.Code­Suffix].Value; }
    set { this[DDCAppli­cationConstPro­pertyName.Code­Suffix].Value = value; }
    }

    private void initProperties()
    {
    SysPropertyDb propDb;

    propDb = new SysPropertyDb(this, DDCApplication­ConstProperty­Name.CultureI­dentifier, null, DDCApplication­ConstParameter­Name.CultureI­dentifier, typeof(System­.Int32), DDCApplication­ConstColumnNa­me.CultureIden­tifier, ParameterDirec­tion.InputOutput, false);
    base.AddProper­ty(propDb);

    propDb = new SysPropertyDb(this, DDCApplication­ConstProperty­Name.CodeLangu­age, null, DDCApplication­ConstParameter­Name.CodeLangu­age, typeof(System­.String), DDCApplication­ConstColumnNa­me.CodeLangua­ge, ParameterDirec­tion.InputOutput, false, DDCApplication­ConstColumnSi­ze.CodeLangua­ge);
    base.AddProper­ty(propDb);

    propDb = new SysPropertyDb(this, DDCApplication­ConstProperty­Name.CodeRegi­on, null, DDCApplication­ConstParameter­Name.CodeRegi­on, typeof(System­.String), DDCApplication­ConstColumnNa­me.CodeRegion, ParameterDirec­tion.InputOutput, false, DDCApplication­ConstColumnSi­ze.CodeRegion);
    base.AddProper­ty(propDb);

    propDb = new SysPropertyDb(this, DDCApplication­ConstProperty­Name.CodeSuffix, null, DDCApplication­ConstParameter­Name.CodeSuffix, typeof(System­.String), DDCApplication­ConstColumnNa­me.CodeSuffix, ParameterDirec­tion.InputOutput, false, DDCApplication­ConstColumnSi­ze.CodeSuffix);
    base.AddProper­ty(propDb);

    SysPropertyRef propRef;

    propRef = this[DDCAppli­cationConstPro­pertyName.Paren­t] as SysPropertyRef;
    if (propRef != null)
    {
    propRef.QueryName = DDCApplication­ConstQueryName­.AAAAAAAAAAAA­A;
    propRef.Instan­ceType = typeof(DDCLis­tLanguage);
    }

    propRef = this[DDCAppli­cationConstPro­pertyName.Chil­d] as SysPropertyRef;
    if (propRef != null)
    {
    propRef.QueryName = DDCApplication­ConstQueryName­.AAAAAAAAAAAA­A;
    propRef.Instan­ceType = typeof(DDCLis­tLanguage);
    }

    propRef = this[DDCAppli­cationConstPro­pertyName.RowOl­d] as SysPropertyRef;
    if (propRef != null)
    {
    propRef.QueryName = DDCApplication­ConstQueryName­.AAAAAAAAAAAA­A;
    propRef.Instan­ceType = typeof(DDCLis­tLanguage);
    }

    propRef = this[DDCAppli­cationConstPro­pertyName.Row­New] as SysPropertyRef;
    if (propRef != null)
    {
    propRef.QueryName = DDCApplication­ConstQueryName­.AAAAAAAAAAAA­A;
    propRef.Instan­ceType = typeof(DDCLis­tLanguage);
    }
    }
    private void fillProperties(Da­taRow row)
    {
    base.FillProper­ty(row, DDCApplication­ConstColumnNa­me.CultureIden­tifier, DDCApplication­ConstProperty­Name.CultureI­dentifier);
    base.FillProper­ty(row, DDCApplication­ConstColumnNa­me.CodeLangua­ge, DDCApplication­ConstProperty­Name.CodeLangu­age);
    base.FillProper­ty(row, DDCApplication­ConstColumnNa­me.CodeRegion, DDCApplication­ConstProperty­Name.CodeRegi­on);
    base.FillProper­ty(row, DDCApplication­ConstColumnNa­me.CodeSuffix, DDCApplication­ConstProperty­Name.CodeSuffix);
    }
    }

    Property navíc vyžadují již převzetí hodnot z datového řádku. V metodě fillProperties(Da­taRow row) řekneme, kterou hodnotu z jakého sloupce má hodit do jaké property. Nic víc, nic míň.

    Práce velice jednoduchá, pochopitelná. V této fázi vůbec nepotřebuji invenční potenciál programátora. Pouze chci, aby inicializoval všechny související objekty a až budou hotové dotazy, aby je doplnil.

    Pro načtení vnitřních objektů je k dispozici málo parametrů. Jakmile se vyšle požadavek na data, je tento zachycen dříve, než je předán datové vrstvě (managerovi) a jsou doplněny hodnoty dalších potřebných parametrů:


    private void setParametersVa­lue(CommandDb item)
    {
    //Aktualni jazyk uzivatele
    item.SetParame­terValue(DDCAp­plicationConstPa­rameterName.Lan­guageUid, GetCurrentLan­guage());
    //Aktualne prihlaseny uzivatel
    item.SetParame­terValue(DDCAp­plicationConstPa­rameterName.U­serUid, user.Uid);
    //Id prihlaseni aktualniho uzivate - kontroluje se opravnenost pristupu na data v databazi
    item.SetParame­terValue(DDCAp­plicationConstPa­rameterName.U­serActivityId, user.Activity.Id);
    //Pro vyber intervalu od data. Nastavuje se z aplikace, chceme-li vybirat data z intervalu
    item.SetParame­terValue(DDCAp­plicationConstPa­rameterName.Pe­riodFrom, GetPeriodFrom());
    //K jakemu datu platnosti se maji zaznamy vybrat
    item.SetParame­terValue(DDCAp­plicationConstPa­rameterName.Pe­riodTo, GetPeriodTo());

    }

    a případně další parametry, které má uživatel předdefinovány nebo si je naklikal v konfiguraci aplikace. Teprve takto předzpracovaná žádost se předhodí data managerovi a ten již ví, kdo je za zpracování zodpovědný. Předá mu dotaz, počká na výsledek, který vrátí.

    Závěr.

    U jiných typů objektů se pracuje stejně. Společný základ se odvodí z odpovídající předka, inicializují se hodnoty a vytvoří se příslušné classy.

    Programátor neví a nemusí vědět, s jakou DB pracuje. Nemusí vytvářet šílené konstrukce dotazů, případně je následně ladit a opravovat. Pracuje pouze s názvem dotazu, který je jednoznačný. Název nemusí odpovídat názvu uložené procedury. Pod názvem se dá vrátit i dotaz ve formě stringu, něco jako "SELECT * FROM ....". I takové dotazy jsou pak uloženy mimo kód aplikace. Externě. O dotazy se mi stará specialista na danou DB. Pokud potřebujeme přidat nějakou property, rozšířit původní tabulku, nic složitého. Stejný princip, stejný postup.

    Myslím si, že z tohoto pohledu je to jednoduché, pochopitelné, eliminuje to chybovost, zrychluje to produktivitu, dělá to kód čitelným, programátora nahraditelným :) a pod.

    Tolik na ukázku.

  • 12. 12. 2016 20:00

    Martin (neregistrovaný)

    Pěkná ukázka.
    Kód je velmi čitelný a jednoduchý. Měl jste pravdu. Nedá se na tom nic pokazit. Budeme se s Vámi asi muset spojit, protože nás ten Váš způsob řešení zajímá.

    Díky, že jste se nenechal odradit.

  • 13. 12. 2016 10:27

    backup (neregistrovaný)

    ja nevim, jestli je vas komentar jen takova jemna ironie, ale ja jsem byl po precteni te ukazky zklaman.

    Takove nejake ciselniky se delaly v PC FANDu pred 25 lety za 2 minuty. A samozrejme to nektere nove frameworky umi zrovna tak rychle. Skutecne nechapu, kde je nejaka uspora.

  • 14. 12. 2016 18:23

    vlasta (neregistrovaný)

    Ale tady přece nejde o číselník. Může se jednat o adresu, právnickou či fyzickou osobu, kartu materiálu a pod. Tabulka jako tabulka. Úspora je v tom, že to programátor napíše úplně stejně. Všude. Bez ohledu na typ objektu (classy), který právě vytváří. Nešmrdlá tam žádné dotazy a pod.

  • 13. 12. 2016 23:46

    Martin Pištora

    Časové hledisko je zajímavý rys, problém je, že zpřesňování evidence v tomto směru nemá konce.
    Nějaká veličina se v nějakých časech mění v realitě.
    Se zpožděním to uživatelé evidují v databázi, včetně toho že zapíšou čas změny v realitě. Kromě toho se zapíše i aktuální čas tohoto zápisu.
    Ale i v tomto se mohou uživatelé zmýlit, musí mít možnost to editovat. Jak hodnotu samou, tak rozhodný čas změny.
    Datazy na tu veličinu se pak velmi zpřehlední - zní: Co si naše databáze v čase T2 myslela o veličině X v čase T1?

  • 14. 12. 2016 11:58

    vlasta (neregistrovaný)

    Máte pravdu. Jedná se o zacyklený případ. Můžeme klidně opravit původní špatnou hodnotu novou špatnou hodnotou. Pak musíme přistoupit na kompromis. Budete souhlasit, že můžeme mít tabulky, které se po celou dobu životnosti nebudou měnit. Určitě budeme mít tabulky, kde se hodnoty měnit budou. A budeme mít i velmi exponované tabulky, kde nám na změnách a schvalování bude nesmírně záležet.

    Jednoduché, zkratkovité a dle mého názoru, špatné řešení je přepsat původní hodnotu hodnotou novou. Jsou-li obě špatně (původní i nová) pak je otázkou, která hodnota se více blížila realitě. Zda-li uchování původní hodnoty nebylo přijatelnější. V takovém případě to nemáme šanci zjistit.

    U našeho řešení se jedná o způsob, kdy si takovou "validaci" můžete zapnout a to až do 39 úrovní schválení. Při vkládání exponovaných údajů můžete záznam označit (vkládat) v tzv. neschváleném režimu. A jednoduše můžete nastavit, že se na záznamy v takovém stavu nemůžete odkazovat z jiných záznamů (přes FK). Záznamy v tomto stavu musí být nejprve schváleny. Jsou-li zadány špatně, mohou být bez problémů opraveny, aniž by se to projevilo v relaci s jinými záznamy.

    Jedná se tedy o určitý kompromis, jak alespoň minimalizovat případné chyby. Uznáte, že pokud si budete věřit a plnit data sám sobě, i tak se nevyhnete případné chybě z nepozornosti. Lidský faktor nelze zcela odstranit. Pokud ale nepoužijeme nějaký způsob kontroly (neříkám že zrovna naše řešení), pak je otázkou, jak dalece se můžete spoléhat na záznamy, které jsou v průběhu času uživateli měněny. Máme-li v Db miliony záznamů a tisíce možných změn, nikdo nemůže zaručit, že mé rozhodování, konané na základě uložených údajů, bude správné a v souladu s těmito údaji.

    Jde o velmi zajímavou, složitou a obsáhlou problematiku, kterou se snažíme nějakým způsobem řešit a z našeho pohledu standardizovat. Chceme, a to se nám podařilo, implementovat tyto postupy na všechny tabulky (potažmo objekty). Přes GUI je zapínat, nastavovat a vypínat. Tak se při vývoji Db aplikací touto oblastí již nemusíme zabývat. Dostáváme tak spoustu volného času na řešení konkrétních problémů, spojených s tou kterou aplikací.

    O tom, jestli to řešíme dobře, špatně či zcela zle, tak to nevím. Chtěl jsem pouze upozornit na to, že takové situace jsou dnes zcela běžné a o žádném optimálním řešení jsme nevěděli. Mé úvahy měly vést k zamyšlení diskutujících. Vzhledem k reakcím většiny je jasné, že tato problematika kráčí mimo ně a úplně je míjí a dlouho míjet bude.

  • 14. 12. 2016 17:34

    Martin Pištora

    Obecně neplatí, že "špatné řešení je přepsat původní hodnotu hodnotou novou". Už u minulého článku jsem psal, že to záleží na aplikaci. Naopak si myslím, že pro většinu agend to bohatě stačí. Až na to, že možná ještě neexistují a daná agenda se řeší bez jakékoliv aplikace. Takže i ta triviální s editací hodnot na místě, by byla lepší. Protože cokoliv nad to komplikuje UI.
    Našel jsem nějaký odkaz k tomu, co jsem zmiňoval v předchozím příspěvku, jde o temporální databáze p. Vrška (tzv. "model vesmíru"): http://www.softmodel.cz/odw01/text.html

  • 14. 12. 2016 18:03

    vlasta (neregistrovaný)

    Já Vám plně rozumím. Vím, že to záleží na aplikaci. Vím, že se to tak dělá, protože je to nejjednodužší. Vím, že to v řadě případů stačí. Vím že to komplikuje UI. Ale zase existuje nějaké "ale". Určitě jste se s takovou situací setkal. Něco vyvíjíte. Máte základní požadavky. Vývoj trvá. Čas běží. Klient platí. Proto implementujete vše co nejjednodušeji. Předáte to k užívání. A následně to máte rozšiřovat. Pak stačí jediný požadavek, mimo původní zadání, právě na nějakou kontrolu a schvalování změn nad jednou blbou tabulkou. A máte problém. Domýšlíte to zpětně, nějak to tam zadrátujete, zesložiťuje se to.

    Chci říci, že tomu rozumím. Proto jsem publikoval řešení, které nás od této situace odstiňuje. My tento problém neřešíme. Nemusíme. Jednoduše to používáme. Včetně možné změny databáze. Protože, co si budeme namlouvat. Nastává doba, kdy to zákazník začíná vyžadovat. Zákazník není blbec. Ta data jsou jeho a chce je mít pod kontrolou. To je realita.

    Díky za rozumnou diskusi a za link. Podívám se na to.