Fotografický magazín "iZIN IDIF" každý týden ve Vašem e-mailu.
Co nového ve světě fotografie!
Zadejte Vaši e-mailovou adresu:
Kamarád fotí rád?
Přihlas ho k odběru fotomagazínu!
Zadejte e-mailovou adresu kamaráda:
Informace
Mac OS X 10.4 Tiger - Co přinášejí jaderná data
12. dubna 2005, 00.00 | Omlouvám se za ten brutální převod pojmu CoreData do češtiny, ale nešlo prostě odolat ☺. Jak jsme si řekli již v úvodním článku k našemu tygřímu miniseriálku, systém CoreData 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.
Omlouvám se za ten brutální převod pojmu CoreData do češtiny, ale nešlo prostě odolat ☺. Jak jsme si řekli již v úvodním článku k našemu tygřímu miniseriálku, systém CoreData 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ě, CoreData 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 CoreData nesetkají – v tomto smyslu (a jenom v něm) pro ně tedy může být systém CoreData "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 CoreData projeví nepřímo: vzhledem k tomu, že CoreData 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 CoreData 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 – CoreData umožňuje programovat téměř doslova "bez programování" a velmi rychle a pohodlně.
Následující text ovšem popisuje technologii CoreData jako takovou, takže bude zajímavý především pro programátory. Čtenáře, jež programování vůbec nezajímá, prosím o malé poshovění – ještě chvilku zůstaňte naladěni, neboť hned příště se pustíme do systému Automator a samozřejmě začneme popisem služeb, jež prostřednictvím svého grafického uživatelského rozhraní nabízí všem uživatelům.
Model, View, Controller
Dříve, než si ukážeme konkrétní postavení technologie CoreData 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ů:
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 CoreData: 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 CoreData 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í CoreData, 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.
CoreData
Máme-li k dispozici systém CoreData, 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 CoreData 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 takto:
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 CoreData, 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 CoreData 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í:
Automaticky se systém CoreData 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 CoreData 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 CoreData NSManagedObjectContext).
Sám NSManagedObjectContext pak obsahuje odkaz na další standardní objekt, správce dat – v CoreData 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 CoreData, ukazuje následující obrázek:
Už brzy...
Mac OS X 10.4 bude všem uživatelům a programátorům k dispozici již velmi brzy: nezaručené pověsti dokonce mluví o tom, že finální "master" verse už je hotova a fixována, takže zbývá opravdu jen vylisovat DVD, zabalit je do krabic... a najít vhodnou příležitost k slavnostnímu zahájení prodeje ☺.
V každém případě nebudeme čekat déle, než pár měsíců na Tygra – a na nové aplikace. Dá se čekat, že ty 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, CoreData 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. CoreData však jako jediný nabízí úzkou integraci s ostatními možnostmi plně dynamického vývojového prostředí Cocoa.
Obsah seriálu (více o seriálu):
- Tiger, Tiger, burning bright...
- Mac OS X 10.4 Tiger - Co přinášejí jaderná data
- Mac OS X 10.4 Tiger - Nedělejte dvakrát, co stačí udělat jednou - Automator
- Mac OS X 10.4 Tiger - Automator a programátor
- Mac OS X Tiger - první dojmy (1)
- Mac OS X Tiger - první dojmy (2)
- Mac OS X Tiger - Textové služby
- Mac OS X Tiger - první dojmy (3)
- Mac OS X Tiger - Spotlight pod drobnohledem (1)
- Mac OS X Tiger - Spotlight pod drobnohledem (2)
- Mac OS X Tiger - Spotlight pod drobnohledem (3) - Tipy a triky
- Mac OS X Tiger - Spotlight pod drobnohledem (4) - skryté možnosti Terminalu
- Mac OS X Tiger v kanceláři (1) - Tipy a triky pro Mail z tygří klece