Neviditelný pes  |  Zvířetník  |  Ekonomika  |  Věda  |  SciFi Pátek 13.5.2005
Svátek má Servác




  Výběr z vydání
 >EVROPA: Budoucnost Evropy 60 let od konce 2. světové války
 >ÚVAHA: Co je svoboda? Popíjaj, popíjaj, nekradni, nezbíjaj!
 >POLITIKA: Zakázat komunisty?
 >MÉDIA: Lhář > velký lhář > superlhář > novinář?
 >RODINA A PŘÁTELÉ: Zlatá padesátá - Dobytčáky
 >POVÍDKA: Sázka života
 >CHTIP: Kvíz v časopisu Květy
 >BOTANICKÁ ZAHRADA: Zahajuje výstava Krajiny na mísách, bonsaje a suiseky
 >PSÍ PŘÍHODY: Není to náhoda
 >POČÍTAČE: Mac OS X 10.4 Tiger - co přinášejí jadrná data
 >MIGRACE: Co víme o dětech cizinců?
 >TISKOVÁ ZPRÁVA: ČT prodloužila lhůtu pro splacení dluhů z poplatků
 >TISKOVÁ ZPRÁVA: Big Brother vstupuje na obrazovky TV Nova
 >PENÍZE.CZ: Zneužití PINu u karty stále pojistí jen jediná banka
 >EKONOMIKA: Koruna posiluje přes snížení sazeb

 >>> HLAVNÍ STRÁNKA  >>  Společnost  >>  Internet  
 
13.5. POČÍTAČE: Mac OS X 10.4 Tiger - co přinášejí jadrná data
Ondřej Čada

Omlouvám se za ten brutální převod pojmu Core Data do češtiny, ale nešlo prostě odolat. Systém Core Data lze považovat za jednu z vůbec nejvýznamnějších novinek nové verse Mac OS X: přidává totiž do systému Cocoa třetí úroveň metaprogramování, poslední, jež byla zapotřebí pro pokrytí kompletní struktury běžné aplikace.

Samozřejmě, Core Data je v zásadě programátorský systém – jedná se o knihovnu služeb a programátorské prostředky pro jejich využívání. Běžní uživatelé se tedy přímo s Core Data nesetkají – v tomto smyslu (a jenom v něm) pro ně tedy může být systém Core Data "méně zajímavý" nežli Dashboard, Spotlight či Automator, jež mají vlastní grafické uživatelské rozhraní a jeho prostřednictvím nabízejí uživatelům nové možnosti.

Pro běžného uživatele se výhody Core Data projeví nepřímo: vzhledem k tomu, že Core Data umožňuje nesrovnatelně rychlejší a spolehlivější programování, objeví se pro Tygra více a lepších (a potenciálně levnějších) aplikací. Zcela typickým příkladem může být snad největší problém Mac OS X, české účetnictví: lze předpokládat, že díky systému Core Data se brzy pro Tygra objeví řada poměrně jednoduchých aplikací typu "peněžní deník" či "kniha jízd", neboť právě takovéto systémy – založené na velmi jednoduchých algoritmech nad známou datovou strukturou – Core Data umožňuje programovat téměř doslova "bez programování" a velmi rychle a pohodlně.

Následující text ovšem popisuje technologii Core Data jako takovou, takže bude zajímavý především pro programátory.

Model, View, Controller

Dříve, než si ukážeme konkrétní postavení technologie Core Data ve vývojovém prostředí Cocoa, si musíme říci něco málo o obecné struktuře jakéhokoli dobře navrženého objektového systému. Objektové programování samozřejmě neznamená jen 'využití dědičnosti', nýbrž především a hlavně daleko bohatší možnosti pro promyšlený a čistý návrh – který se pak zaplatí mnohem snazší implementací a hlavně údržbou a rozšiřováním software.

Základem kvalitního objektového designu je vždy dělení na tři přinejmenším logicky nezávislé moduly: ty se tradičně nazývají "model", "view" (uživatelské rozhraní) a "controller" (správce); pro aplikační strukturu, založenou na těchto třech modulech, se často používá zkratka složená z jejich prvních písmen: MVC.

Každý z modulů má jasně stanovenou úlohu:

  • Model representuje data, nad nimiž aplikace pracuje: obrázek, film, textový dokument, databázi (nebo, v tomto případě zvlášť vhodně pojmenovaný, databázový model), strukturu čísel a formulí pro spreadsheet... Aplikace samozřejmě může obsahovat modelů více, v závislosti na tom, s kolika "datovými bloky" pracuje;
  • View je "uživatelský" pohled na model, tak, jak jej presentuje grafické uživatelské rozhraní aplikace. Podstatné a důležité z hlediska struktury aplikace je to, že samo grafické rozhraní neobsahuje ani vlastní data (to je úkolem modelu), ani logiku práce s nimi (o to se, jak hned uvidíme, stará "controller"). Jednou z nejběžnějších a nejčastěji opakovaných chyb při špatném objektovém návrhu jsou právě "views", obsahující data či řídící rutiny. Objektů "view" bývá v aplikaci obecně také více (protože obvykle zobrazujeme více údajů o modelu najednou);
  • Controller stojí mezi modelem a "view", a zajišťuje logiku chování celého systému. Controller přijímá události, vyvolané vstupními objekty v rámci "view" (např. nabídkami, tlačítky a podobně); zpracuje je podle potřeby, a pak odpovídajícím způsobem upraví výstupní objekty v rámci "view" (textová pole, tabulky a další). Přitom samozřejmě podle potřeby spolupracuje s modelem – předává mu požadavky na změny, a kdykoli je to zapotřebí, vyžádá si od něj údaje pro zobrazení. V jednoduchých aplikacích bývá jeden controller; v aplikacích, jež pracují s více nezávislými dokumenty, je obvykle jeden controller pro každý dokument.

Právě při takto strukturovaném návrhu získáme nejvyšší flexibilitu a vícenásobnou použitelnost kódu: model není nijak závislý na konkrétní aplikační logice, můžeme jej beze změny a snadno využít v jakékoli jiné aplikaci, jež pracuje se shodnými daty. Podobně "controller" nijak nezávisí na konkrétním vzhledu grafického uživatelského rozhraní (tedy "view") – to můžeme podle potřeby (a podle požadavků zákazníků) snadno měnit, aniž bychom museli zasahovat do kódu "controlleru" (natož pak modelu).

Samozřejmě, že vývojové prostředí Cocoa objektový design MVC přímo a velmi dobře podporuje: třídy jsou velmi čistě rozděleny na ty, jež representují data a tak se hodí pro model (např. třídy NSString či NSData), na ty, jež slouží pro řízení běhu programu a tak se hodí pro"controller" (třeba NSException) a na třídy grafického uživatelského rozhraní, representující "view" (NSWindow, NSMenu...). Cocoa však podporuje strukturu MVC i přímo, prostřednictvím svých vývojových prostředků (obr. 1).

Způsob, jakým sestavujeme objektové sítě, representující grafické uživatelské rozhraní, nezávisle na konkrétním modelu či "controlleru" prostřednictvím aplikace InterfaceBuilder je už dávno známý. Táž aplikace nabízí i prostředky pro definování samotného "controlleru" prostřednictvím tzv. systému vazeb (bindings); vazby jsou novinkou systému Mac OS X 10.3, takže řada programátorů je dosud nemá tak zažité, jako objektové sítě grafického uživatelského rozhraní; řekneme si proto o nich malilinko více.

Základním principem systému je možnost navázat (pomocí prostředků metaprogramování vyšší úrovně, tedy bez psaní jakéhokoli zdrojového kódu) spojení mezi konkrétním prvkem uživatelského rozhraní (dejme tomu textovým polem), a pojmenovaným atributem konkrétního datového objektu (dejme tomu atributem "firstName" objektu "person"). Jakmile to uděláme, systém vazeb udržuje automaticky synchronizaci mezi oběma objekty: kdykoli se jakkoli v daném objektu změní hodnota atributu "firstName", ihned se nová hodnota objeví v textovém poli. Jakmile uživatel do textového pole zapíše nový text, objekt "person" ihned automaticky dostane zprávu "setFirstName:", jejímž argumentem je nová hodnota. Ovšemže systém vazeb je mnohem bohatší; jeho služby však nejsou obsahem tohoto článku, takže důkladnější popis si necháme na jindy – dnes se vrátíme k datům.

Právě práce s daty – tedy s modelem – je obsahem frameworku Core Data: zatímco až dosud museli programátoři v Mac OS X své "objekty person" tak či onak přímo programovat (byť s pomocí velmi flexibilních služeb standardních knihoven, zahrnujících mj. i persistenci objektových sítí), v Tygrovi Core Data nabízejí velmi pohodlnou úroveň metaprogramování i pro tento účel – jak vypadá a funguje si popíšeme v následujícím textu.

Tradiční model

V tradičních systémech – včetně Mac OS X až do verse 10.3 – jsme museli své datové objekty tak či onak programovat. Pojďme si pro srovnání s možnostmi, jež nabízejí Core Data, jen v rychlosti ukázat základní princip takové implementace. Představme si jednoduchou aplikaci representující diář: spravuje řadu událostí, každá z nich se týká nějakého počtu účastníků (přičemž každý hraje různou roli: organizátor, host...) a událost proběhne v nějakém místě; několik různých událostí se může týkat jedné akce (třeba řada přednášek v rámci celé konference).

Klasický (objektový) přístup by znamenal vytvořit pro každý typ objektů samostatnou třídu – měli bychom tedy třídu Event pro události, třídu Person pro jejich účastníky a tak dále. V rámci každé třídy bychom museli definovat proměnné pro její atributy a jim odpovídající accessory – nějak takto:

@interface Person:NSObject {
  NSString *firstName,*lastName;
  ...
}
-(NSString*)firstName;
-(void)setFirstName:(NSString*)fn;
...
@end

Tomu by pak odpovídala patřičná implementace, vypadající – v systému Cocoa s jeho správou paměti – zhruba nějak takto (nejde o optimální implementaci, to však ani není účelem tohoto textu):

@implementation Person
-(NSString*)firstName {
  return firstName;
}
-(void)setFirstName:(NSString*)fn {
  [firstName autorelease];
  firstName=[fn copy];
}
...
@end

Takto definovaný objekt by již šel využívat pro datový model spolu se systémem vazeb (jak jsme si právě na hypotetickém příkladu vazby "firstName" na textové pole ukázali v minulém odstavci); to ovšem zdaleka neznamená, že jsme hotovi: skutečná práce teprve nastává, musíme totiž implementovat vazby mezi objekty. Je třeba definovat a implementovat metody, jež získají pro danou událost všechny její účastníky; pro danou osobu všechny události, jichž se účastní... a tak dále. Zde si již příklad ukazovat nebudeme, neboť by byl příliš komplikovaný – kromě jiného se také musíme postarat o to, aby vzájemné vazby zůstaly konsistentní – nesmí se kupříkladu stát, aby nějaká událost byla v seznamu událostí osoby A, a přitom ale osoba A nebyla v seznamu účastníků této události...

Ani to ještě není vše. Musíme korektně implementovat vhodnou metodu initWith... pro vytvoření instance a dealloc pro uvolnění atributů při jejím zániku. Musíme implementovat metody encodeWithCoder: a initWithCoder: pro ukládání objektové sítě do datového souboru a její opětovné načtení. A musíme implementovat řadu služeb na úrovni "controlleru", jež budou podle potřeby datovou síť načítat a ukládat a podobně (mnohé z těchto služeb nám samozřejmě zajistí systém vazeb, ne ale všechny).

Ačkoli v Cocoa si můžeme mnoho práce uspořit, pokud pro datové objekty použijeme beztypové kontejnery (především NSMutableDictionary), pořád spousta programování zůstává – především pak celý blok metod pro udržování vzájemných vazeb mezi objekty.

Core Data

Máme-li k dispozici systém Core Data, všechnu práci si můžeme ušetřit. Stačí, pokud – pomocí grafických prostředků – definujeme datový model na základě tzv. entity-relationship neboli E/R modelování. Tento pojem je velmi dobře známý uživatelům databází, a Core Data jej přináší do běžného aplikačního programování: v zásadě jde o to, že popíšeme jednotlivé "typy objektů" (entity), jejich atributy a vazby mezi nimi (relace) prostřednictvím přehledné grafické sítě – v našem případě by to mohlo vypadat asi nějak jako na obr. 2.

Podívejme se na entitu "Person": vidíme, že obsahuje atributy "firstName" a "lastName" (a "notes"), a že má relaci "participatingEvents", jež obsahuje několik entit "EventParticipant"; každá z nich specifikuje roli, již osoba v dané události hraje, a obsahuje další relaci na danou událost. Relace jsou ovšem obousměrné – stejně dobře můžeme vyjít z entity "Event", a pomocí relace "participants" získat seznam entit "EventParticipant" a jejich prostřednictvím přímo osob, jež se události účastní.

"Klasičtí dataři" si kreslili takového modely ručně nebo ve specializovaných grafických programech, a pak na jejich základě vytvářeli databázové tabulky. Pokročilejší systémy – kupříkladu takový Enterprise Objects Framework (EOF) navržený firmou NeXT a dnes spravovaný firmou Apple – na základě takovéhoto modelu databázové tabulky vytvořil automaticky, a dokázal automaticky spravovat i odpovídající objektovou síť.

Nejinak je tomu i v systému Core Data, který ostatně koncepčně z frameworku EOF vychází: navíc je optimálně integrovaný do celého vývojového prostředí Cocoa, a ostatní třídy mu "rozumějí" a "dokáží s ním zacházet". To znamená, že výše uvedený obrázek vytvoříme ve speciálním editoru datových modelů.... a jsme hotovi!

Systém Core Data na základě tohoto modelu automaticky vytvoří potřebné instance, representující události, jejich účastníky, místa a akce (Occasion); automaticky zajistí, že všechny atributy lze na základě jejich jmen, určených v "obrázku" (tedy v datovém modelu), připojovat k objektům grafického uživatelského rozhraní prostřednictvím vazeb... k tomu dokonce InterfaceBuilder dokáže vytvářet standardní rozhraní automaticky na základě datového modelu – stačí vhodit myší entitu z datového modelu do okna InterfaceBuilderu, a vytvoří se standardní tabulkové rozhraní typu master/detail pro zobrazení a úpravy jejích instancí (obr. 3)

Automaticky se systém Core Data postará také o správu vzájemných relací mezi objekty, včetně toho, aby relace vždy a za všech okolností konsistentní. A to ještě pořád není všechno: díky úzké integraci Core Data s ostatními třídami Cocoa automaticky funguje ukládání dat do souborů a jejich načítání (v několika různých formátech včetně XML), automaticky fungují dokonce i takové služby jako undo a redo...

Jak je to všechno možné?

Základní princip spočívá v geniálně navržené struktuře, koncepčně převzaté právě ze systému EOF: systém automaticky spravuje síť objektů založených na standardní knihovní třídě – v našem případě se tato třída jmenuje NSManagedObject – jejíž instance obsahují řadu atributů:

  • každá instance "coredatového" objektu může obsahovat libovolnou skupinu pojmenovaných atributů (v podstatě bychom si mohli představit, že v ní je obsažen beztypový kontejner typu NSMutableDictionary, jakkoli konkrétní implementace patrně bude odlišná);
  • každá instance také "ví", které entitě patří;
  • každá instance navíc "patří" správci objektové sítě; to je instance další standardní třídy (v Core Data NSManagedObjectContext).

Sám NSManagedObjectContext pak obsahuje odkaz na další standardní objekt, správce dat – v Core Data NSPersistentStoreCoordinator.

Kdykoli se pak pokusíme s objektem provést jakoukoli akci – dejme tomu, získat jeho atribut jménem "firstName" pro zobrazení v GUI – objekt na základě informací o entitě v datovém modelu ověří, že skutečně atribut "firstName" má, a prostřednictvím správce dat jej spojí s odpovídající hodnotou, načtenou z datového souboru.

Správce objektové sítě pak zajišťuje podle potřeby načítání objektů z datového souboru, přidávání nových, rušení existujících a podobně. Dokáže také vyhledávat objekty podle jejich atributů na základě tzv. predikátů – v podstatě jde o databázové dotazy typu "dej mi všechny objekty entity Person, jejichž 'firstName' je 'Josef' a nemají v 'notes' text 'xx'". Kromě toho správce zajišťuje také vazbu na aplikační strukturu Cocoa – právě jeho prostřednictvím fungují takové věci, jako automatické načítání či zápis datových souborů nebo undo a redo. Celkovou strukturu modelu, založeného na technologii Core Data, ukazuje obrázek 4.

Už brzy...

Dá se čekat, že nové aplikace se objeví velmi brzy, neboť úroveň metaprogramování, již nyní Cocoa nabízí, je zcela bezprecedentní a umožní tvorbu kvalitních, výkonných a stabilních aplikací ve zcela minimálním čase. Jistěže, Core Data není první ani jediná podobná technologie – kromě samotného systému EOF, o němž jsme se již zmínili, existuje i řada jeho epigonů – např. Cayenne. Core Data však jako jediný nabízí úzkou integraci s ostatními možnostmi plně dynamického vývojového prostředí Cocoa.

Ondřej Čada
pes@ocs.cz
OCSoftware

Obr. 1 Obr. 2 Obr. 4 Obr. 3



Další články tohoto autora:
Ondřej Čada

Počet přístupů na stránku:

Komentáře ke článku