home *** CD-ROM | disk | FTP | other *** search
/ Chip 2003 January / ChipCD_1.03.iso / obsahy / Chip_txt / txt / 174-181.txt < prev    next >
Text File  |  2002-12-01  |  22KB  |  190 lines

  1. High Order Messaging
  2. Pru₧nΘ zprßvy
  3. High Order Messaging je velmi zajφmavß objektovß technologie, kterß umo₧nφ podstatn²m zp∙sobem zjednoduÜit k≤d a p°itom zv²Üit jeho flexibilitu. V tomto Φlßnku se na ni podφvßme podrobn∞ji.
  4.  
  5. Pro prvnφ p°iblφ₧enφ bychom mohli High Order Messaging (dßle jen HOM) p°elo₧it jako nep°φmΘ zasφlßnφ zprßv. Za normßlnφch okolnostφ p°i objektovΘm programovßnφ objektu posφlßme zprßvu, jejφm₧ prost°ednictvφm si vy₧ßdßme n∞jakou akci: poÜleme-li objektu, kter² reprezentuje pole prvk∙, zprßvu count, objekt vrßtφ poΦet prvk∙; poÜleme-li objektu okno zprßvu close, okno se zav°e. HOM m∙₧e fungovat v libovolnΘm objektovΘm jazyce, kter² podporuje polymorfismus a umo₧≥uje, abychom se na zprßvu dφvali jako na objekt; v tomto Φlßnku pou₧iji jako p°φklad Objective C. V n∞m se pro odesφlßnφ zprßv pou₧φvß konstrukce [p°φjemce zprßva], tak₧e v²Üe popsanΘ trivißlnφ p°φklady by v programovacφm jazyce vypadaly takto: 
  6. int n=[pole count]; 
  7. [okno close];
  8.  
  9. Princip HOM spoΦφvß v tom, ₧e zprßvu nezasφlßme objektu p°φmo; namφsto toho "mezi objekt a zprßvu" vlo₧φme dalÜφ p°φkaz, kter² urΦφ, co p°esn∞ se s nßsledujφcφ zprßvou mß stßt. Jednφm z nejjednoduÜÜφch p°φklad∙ m∙₧e b²t opo₧d∞nΘ odeslßnφ zprßvy - dejme tomu, ₧e chceme, aby se okno zav°elo za deset sekund. Vhodn²m °eÜenφm ve stylu HOM je pou₧φt specißlnφ high-order zprßvu, je₧ objektu °ekne: "Nßsledujφcφ zprßvu mßÜ dostat za deset sekund." Odpovφdajφcφ zßpis v programovacφm jazyce by vypadal p°ibli₧n∞ takto:
  10.  
  11. [[okno afterDelay:10] close];
  12.  
  13. Samoz°ejm∞ ₧e zde nejde o n∞jakou specißlnφ vlastnost objektu okno nebo zprßvy close; HOM je zcela obecn² systΘm, kter² dφky objektovΘ d∞diΦnosti a dφky polymorfismu m∙₧e pracovat s libovoln²m objektem a s libovolnou zprßvou - vΦetn∞ zprßv s argumenty:
  14.  
  15. [[okno afterDelay:15] setTitle:@"Uplynulo 15 sekund"]; 
  16. [[server afterDelay:30] login:@"Guest" password:@""];
  17.  
  18. Prvnφ p°φklad po uplynutφ patnßcti sekund zm∞nφ titulek okna. Ve druhΘm z°ejm∞ komunikujeme s n∞jak²m serverem, kter² vy₧aduje p°ihlßÜenφ u₧ivatele - v naÜem p°φkladu jsme si vy₧ßdali, aby se aplikace po t°iceti sekundßch p°ipojila jako u₧ivatel Guest s prßzdn²m heslem ( jist∞₧e HOM umo₧≥uje takΘ takto naplßnovanou akci zruÜit, pokud se v pr∙b∞hu danΘ doby u₧ivatel p°ihlßsφ jinak; to si ale ukß₧eme a₧ pozd∞ji).
  19. Slu₧by HOM nejsou omezeny jen na opo₧d∞nΘ odeslßnφ; naopak, skv∞le se hodφ na jakΘkoli komplexn∞jÜφ operace, kterΘ v tradiΦnφm API musφme rozepisovat do slo₧it²ch p°φkaz∙. Snad nejlΘpe se projevφ p°i prßci s poli, kde uÜet°φ spoustu p°φkaz∙ for.
  20.  
  21. HOM a pole
  22. Chceme-li n∞jak zpracovat ka₧d² prvek v danΘm poli, musφme na to v klasickΘm API pou₧φt p°φkaz cyklu; nejΦast∞ji jde o tradiΦnφ p°φkaz for. Dejme tomu, ₧e mßme vφce oken ulo₧en²ch v poli a chceme vÜechna zav°φt; v tradiΦnφ podob∞ bychom museli napsat n∞co jako
  23.  
  24. // klasick² p°φkaz cyklu 
  25. int i; 
  26. for (i=0;i<[poleOken count];i++)
  27. [[poleOken objectAtIndex:i] close];
  28.  
  29. Mßme-li k dispozici bohatΘ objektovΘ knihovny umo₧≥ujφcφ prßci s tzv. iterßtory, jsme na tom trochu lΘpe, proto₧e se m∙₧eme zbavit indexovßnφ a tφm i otßzek typu "Je pole indexovßno od nuly, nebo od jedniΦky?", nebo "Jsou v poli dφry - indexy, na kter²ch nenφ ₧ßdn² prvek -, nebo ne?", Φi dokonce "Jsou v∙bec prvky v poli °azeny sekvenΦn∞, nebo existuje d∙vod je zpracovßvat t°eba odzadu?". V Objective C s knihovnami Cocoa by to mohlo vypadat n∞jak takto:
  30.  
  31. // cyklus s iterßtorem NSEnumerator *en; 
  32. NSWindow *o; 
  33. for (en=[poleOken objectEnumerator];o=[en nextObject];)
  34. [o close];
  35.  
  36. Ani iterßtory zdaleka ne°eÜφ vÜe - po°adφ zpracovßnφ prvk∙ u₧ m∙₧e b²t pro r∙znß pole r∙znΘ ( jin²mi slovy objektovΘ, proto₧e polymorfnφ), stßle jsme se nezbavili p°φkazu cyklu. Co kdyby bylo pro n∞kterΘ pole v²hodnΘ provΘst p°φkazy nad vÜemi jeho prvky najednou, v rßmci r∙zn²ch thread∙? Takovou mo₧nost tady nemßme, tu p°inese a₧ HOM.
  37. S vyu₧itφm HOM toti₧ m∙₧eme snadno do p∙sobnosti pole p°enΘst kompletnφ cyklus: staΦφ zavΘst high-order zprßvu each, kterß poli °ekne: "Nßsledujφcφ zprßvu p°edej beze zm∞ny ka₧dΘmu ze sv²ch prvk∙." V programovacφm jazyce by to pak vypadalo asi takhle:
  38.  
  39. [[poleOken each] close];
  40.  
  41. Hlavnφ v²hoda, kterou jsme zφskali, je flexibilita: teprve nynφ programujeme skuteΦn∞ objektov∞, proto₧e mßme k dispozici skuteΦn² polymorfismus. V∞tÜina polφ vÜak bude zprßvu each interpretovat klasicky, tj. tak, ₧e nßsledujφcφ zprßvu (zde close) postupn∞ rozeÜle vÜem sv²m prvk∙m, od prvnφho do poslednφho. Je-li k tomu ale d∙vod, libovolnΘ konkrΘtnφ pole m∙₧e toto chovßnφ zm∞nit. Pole, je₧ dovoluje prßzdnΘ indexy, bude zprßvu rozesφlat pouze t∞m prvk∙m, je₧ v n∞m skuteΦn∞ jsou - to by s klasick²m p°φkazem cyklu vy₧adovalo dalÜφ p°φkaz if. Pole m∙₧e prochßzet svΘ prvky v libovolnΘm po°adφ, podle pot°eby. Stejn∞ dob°e pole m∙₧e - dßvß-li to pro n∞j smysl - namφsto cyklu vytvo°it pro ka₧d² ze sv²ch prvk∙ samostatn² thread a zprßvu close mu odeslat v n∞m, tak₧e se de facto vÜechna okna zav°ou najednou.
  42. Krom∞ flexibility jsme tak zφskali i na jednoduchosti a p°ehlednosti - poslednφ p°φklad je mnohem p°ehledn∞jÜφ ne₧ kter²koli z p°φkaz∙ cyklu; nepot°ebujeme ₧ßdnΘ pomocnΘ prom∞nnΘ... Takhle n∞jak by asi objektovΘ programovßnφ m∞lo vypadat. Nejde jen o jednoduchost; d∙le₧it∞jÜφ je, ₧e °φkßme p°esn∞ to, co chceme: "Chceme ka₧dΘmu prvku pole poslat zprßvu close." Nenφ pravda, ₧e chceme pou₧φt programov² cyklus, to je nßm p°ece jedno! V angliΦtin∞ se tomuto nesmφrn∞ d∙le₧itΘmu principu °φkß intention-revealing: m∞li bychom programovat tak, aby z k≤du bylo jasnΘ, Φeho jsme cht∞li docφlit. Nenφ naopak d∙le₧itΘ, jakou cestou.
  43. Pro prßci s poli m∙₧e HOM nabφdnout vφce a bohatÜφch zprßv ne₧ jen each. Dejme tomu, ₧e p∙vodnφ p°φkaz cyklu nem∞l jen rozeslat n∞jak² p°φkaz, ale ₧e m∞l naopak od ka₧dΘho z prvk∙ pole n∞co zjistit a vytvo°it seznam t∞chto informacφ - t°eba chceme titulky vÜech oken z pole:
  44.  
  45. // klasick² p°φkaz cyklu NSMutableArray *titulky=[NSMutableArray array]; 
  46. int i; 
  47. for (i=0;i<[poleOken count];i++)
  48. [titulky addObject:[[poleOken objectAtIndex:i] title]];
  49.  
  50. V cyklu ka₧dΘmu oknu v poli poÜleme zprßvu title, na ni₧ okno reaguje vrßcenφm svΘho titulku; ty hromadφme v poli titulky. HOM nßm ale m∙₧e nabφdnout jednoduÜÜφ a p°ehledn∞jÜφ variantu, zalo₧enou na high-order zprßv∞ collect. Ta funguje podobn∞ jako each, navφc vÜak hodnoty vrßcenΘ vÜemi prvky soust°edφ do novΘho pole, je₧ se stane jejφ nßvratovou hodnotou:
  51.  
  52. NSArray *titulky=[[poleOken collect] title];
  53.  
  54. Zprßvy HOM m∙₧eme °et∞zit jako ka₧dΘ jinΘ. Cht∞li bychom, aby zφskanΘ titulky oken byly velk²mi pφsmeny? Nic snazÜφho - na zφskanΘ pole titulk∙ p°ece high-order zprßva collect funguje stejn∞ dob°e jako na p∙vodnφ pole oken:
  55.  
  56. NSArray *titulky=[[[[poleOken collect] title] collect] uppercaseString];
  57.  
  58. DalÜφ mo₧nosti, kterΘ dßvß HOM nad poli, jsou zprßvy select a reject, je₧ vybφrajφ prvky z pole v zßvislosti na tom, zda na n∞jakou jinou zprßvu prvek reaguje kladn∞ Φi zßporn∞. Zprßva select tedy °φkß: "Nßsledujφcφ zprßvu poÜli ka₧dΘmu ze sv²ch prvk∙; vra¥ v poli ty, je₧ na zprßvu reagovaly hodnotou YES." Podobn∞ je to se zprßvou reject, kterß ovÜem sbφrß objekty, je₧ vrßtily NO. Nßsledujφcφ p°φkaz nap°φklad vybere jen viditelnß okna:
  59.  
  60. NSArray *vo=[[poleOken select] isVisible];
  61.  
  62. Slo₧it∞jÜφ je to v p°φpad∞, kdy bychom cht∞li vybφrat podle slo₧it∞jÜφho kritΘria. Dejme tomu, ₧e chceme vybrat vÜechna okna, jejich₧ titulek zaΦφnß pφsmenem H. Mßme k dispozici ji₧ znßmou zprßvu title i zprßvu hasPrefix:, je₧ ov∞°φ, zda textov² °et∞zec mß dan² prefix; jednoduÜe je slo₧it za sebe ovÜem nem∙₧eme:
  63.  
  64. NSArray *xo=[[[poleOken select] title] hasPrefix:@"H"]; // Üpatn∞
  65.  
  66. Toto samoz°ejm∞ fungovat nebude: high-order zprßva select spolu s nßsledujφcφ zprßvou title prost∞ vybere vÜechna okna, je₧ majφ n∞jak² titulek (tj. zaÜleme-li jim zprßvu title, dostaneme nenulovou hodnotu, co₧ je v jazyce Objective C "pravda"). Poli obsahujφcφmu seznam t∞chto oken bychom zaslali zprßvu hasPrefix: - a to ovÜem nechceme.
  67. Jednou z mo₧nostφ by bylo vyu₧φt jinou high-order zprßvu, je₧ se pro dan² problΘm hodφ lΘpe. V Objective C s knihovnami Cocoa, je₧ umo₧≥ujφ k atribut∙m objekt∙ p°istupovat podle jmΘna, by to mohlo vypadat t°eba takto:
  68.  
  69. NSArray *xo=[[poleOken selectWhereValueForKey:@"title"] hasPrefix:@"H"]; 
  70.  
  71. kde high-order zprßva selectWhereValueForKey: spustφ pom∞rn∞ komplikovan² mechanismus, kter² by se dal popsat slovy: "Zjisti od ka₧dΘho ze sv²ch prvk∙ atribut se zadan²m jmΘnem" - zde "title" "a hodnot∞ tohoto atributu poÜli nßsledujφcφ zprßvu. Vra¥ v poli ty prvky, jejich₧ atribut na zprßvu reagoval hodnotou YES."
  72. AΦkoli konkrΘtnφ implementace HOM m∙₧e obsahovat jeÜt∞ dlouhou °adu dalÜφch high-order zprßv °eÜφcφch v∞tÜinu b∞₧n²ch problΘm∙, n∞kdy to p°ece jen nestaΦφ a je zapot°ebφ zprßvy tak Φi onak °et∞zit. Uka₧me si, jak na to.
  73.  
  74. ╪et∞zenφ high-order zprßv
  75. P°ipome≥me si p°φklad z minulΘho odstavce, v n∞m₧ jsme v jedinΘm v²razu pou₧ili z°et∞zenφ Φty° r∙zn²ch zprßv; dv∞ z nich byly highorder, dv∞ normßlnφ:
  76.  
  77. NSArray *titulky=[[[[poleOken collect] title] collect] uppercaseString];
  78.  
  79. To samoz°ejm∞ nenφ ₧ßdn² problΘm. Vzhledem k tomu, ₧e zprßvy se st°φdajφ, rozpadß se vlastn∞ v²raz na dv∞ Φßsti, z nich₧ v ka₧dΘ je pou₧ita pouze jedna high-order zprßva. Prvnφ zprßva collect spolu se zprßvou title vrßtφ normßlnφ pole objekt∙, nad kter²m pracuje druhß zprßva collect se zprßvou uppercaseString.
  80. ╪et∞zenφ zprßv je mo₧nΘ i jinak - existuje °ada situacφ, kdy je ₧ßdoucφ °et∞zit high-order zprßvy bezprost°edn∞ za sebe. P°ipome≥me si prvnφ dv∞ zprßvy systΘmu HOM, s nimi₧ jsme se seznßmili: afterDelay: a each - co kdy₧ mßme pole oken a chceme je vÜechna zav°φt za minutu? Na prvnφ pohled se nabφzφ nßsledujφcφ °eÜenφ:
  81.  
  82. [[[poleOken afterDelay:60] each] close]; [[[poleOken each] afterDelay:60] close];
  83.  
  84. Ob∞ varianty jsou prakticky rovnocennΘ, prvnφ je malinko efektivn∞jÜφ - znamenß "Za minutu poÜli vÜem prvk∙m poleOken zprßvu close", tak₧e v implementaci staΦφ jedin² ΦasovaΦ. Druhß varianta °φkß "Ka₧dΘmu prvku poleOken poÜli za minutu zprßvu close", tak₧e ΦasovaΦ∙ je zapot°ebφ tolik, kolik je v poli oken.
  85. OvÜem... je to v∙bec sprßvnΘ? M∙₧eme high-order zprßvy tφmto zp∙sobem °et∞zit? V nejjednoduÜÜφm p°φpad∞ ne - tak, jak jsme si systΘm HOM dosud popsali, by to nefungovalo. Nap°φklad v prvΘm °ßdku by high-order zprßva afterDelay: zajistila, ₧e za minutu poleOken dostane zprßvu each. Nikde vÜak nenφ psßno, ₧e by se odeslßnφ zprßvy close takΘ o minutu odsunulo, tak₧e zprßv∞ each by vlastn∞ chyb∞l "argument" (tj. ta zprßva, ji₧ je t°eba rozeslat vÜem prvk∙m pole).
  86. NaÜt∞stφ existuje velmi jednoduchΘ rozÜφ°enφ pravidel, podle nich₧ se high-order zprßvy zpracovßvajφ. StaΦφ do souboru "pravidel HOM" p°idat podmφnku, ₧e jakßkoli skupina bezprost°edn∞ po sob∞ nßsledujφcφch high-order zprßv se v₧dy zpracovßvß jako jedin² celek. Je-li tomu tak, oba v²Üe uvedenΘ p°φklady budou bez problΘm∙ fungovat: zprßvy afterDelay: a each spolu vlastn∞ vytvo°φ jednu slo₧enou high-order zprßvu, jejφm₧ "argumentem" je nßsledujφcφ zprßva close.
  87. Podobn²m zp∙sobem m∙₧eme sestavovat i slo₧it∞jÜφ °et∞zy highorder zprßv, vΦetn∞ pon∞kud absurdnφho, ale pln∞ funkΦnφho
  88.  
  89. [[[okno afterDelay:1] afterDelay:2] close];
  90.  
  91. Stojφ za to si uv∞domit zcela zßsadnφ rozdφl mezi tφmto °et∞zenφm, je₧ je zcela v po°ßdku, a nekorektnφm p°φpadem z minulΘho odstavce. Pokud bychom zapsali
  92.  
  93. NSArray *xo=[[[poleOken select] title] hasPrefix:@"H"]; // Üpatn∞ 
  94.  
  95. k ₧ßdnΘmu spojenφ zprßv do jedinΘho celku nedojde, proto₧e zde pou₧φvßme jen jedinou high-order zprßvu select; zb²vajφcφ dv∞ zprßvy jsou standardnφ, a proto se nespojφ. To je jasnΘ, ale... Bylo by p°ece jen ÜikovnΘ, kdybychom je v p°φpad∞ pot°eby takto spojit mohli v principu to p°ece musφ jφt; m∙₧eme-li vzßjemn∞ spojovat high-order zprßvy, nenφ d∙vod, proΦ by to nem∞lo jφt i s ostatnφmi.
  96. Ukazuje se, ₧e tomu skuteΦn∞ tak je. Dobrß implementace HOM m∙₧e nabφzet specißlnφ high-order zprßvy begin a end, jejich₧ jedin²m ·Φelem je oznaΦit blok zprßv, je₧ se majφ spojit a provΘst jako jeden celek, vlastn∞ jako jedna jedinß slo₧enß zprßva. Mßme-li tyto zprßvy k dispozici, m∙₧eme minul² p°φklad p°epsat korektnφm zp∙sobem:
  97.  
  98. NSArray *xo=[[[[[poleOken select] begin] title] hasPrefix:@"H"] end];
  99.  
  100. Tentokrßt bude vÜe fungovat bez nejmenÜφch obtφ₧φ. High-order zprßva select narazφ na zprßvu begin, kterß °φkß: "Ber vÜe, co za mnou nßsleduje, a₧ po zprßvu end, jako jedin² celek." Proto zprßva select poÜle ka₧dΘmu prvku z pole ob∞ zprßvy - title i hasPrefix: - a a₧ podle v²sledku druhΘ z nich rozhodne, zda okno za°adφ do v²slednΘho pole, nebo ne.
  101.  
  102. P°φstup k °φdicφmu objektu
  103. Samoz°ejm∞ ₧e "skromn∞ v pozadφ" implementace HOM stojφ °ada pomocn²ch t°φd a objekt∙, je₧ zajiÜ¥ujφ vÜechny odpovφdajφcφ slu₧by. My se na n∞ podrobn∞ji podφvßme pozd∞ji, a₧ si budeme vysv∞tlovat princip, na n∞m₧ je implementace HOM zalo₧ena; prozatφm se soust°edφme na zßkladnφ programßtorskΘ rozhranφ.
  104. V n∞kter²ch p°φpadech je vÜak vhodnΘ zajistit p°φstup k °φdicφmu objektu i na tΘto ·rovni. Jde o high-order zprßvy typu afterDelay: nebo inNewThread (viz nφ₧e). V jejich p°φpad∞ toti₧ m∙₧e b²t n∞kdy ₧ßdoucφ se jaksi vrßtit k odeslßnφ zprßvy a n∞jak jej dodateΦn∞ modifikovat - nap°φklad zruÜit po₧adavek na opo₧d∞nΘ odeslßnφ zprßvy d°φve, ne₧ k n∞mu doÜlo, nebo poΦkat na ukonΦenφ threadu. NaÜt∞stφ systΘm HOM n∞jak² °φdicφ objekt stejn∞ obsahuje, tak₧e je to velice snadnΘ. StaΦφ pou₧φt prom∞nnou, do kterΘ ulo₧φme v²sledek odeslßnφ pat°iΦnΘ high-order zprßvy. P°ipome≥me jeden z prvnφch p°φklad∙, jφm₧ bylo automatickΘ p°ihlßÜenφ k serveru po uplynutφ zadanΘho Φasu; zde bychom samoz°ejm∞ v praxi cht∞li zruÜit automatickΘ p°ihlßÜenφ tehdy, kdy₧ se u₧ivatel v danΘm ΦasovΘm intervalu p°ihlßsφ sßm. Cel² k≤d samoz°ejm∞ bez grafickΘho u₧ivatelskΘho rozhranφ - by pak mohl vypadat asi n∞jak takto: 
  105.  
  106. id autLogin; // tato metoda se volß na zaΦßtku (zajistφ GUI) -(void)prepareLogin {
  107. [autLogin=[server afterDelay:30] login:@"Guest" password:@""]; 
  108. }
  109. // tato metoda se volß pokud se u₧ivatel p°ihlßsφ (zajistφ GUI) -(void)loginWithName:name password:password {
  110. [autLogin cancel]; // zruÜφ naplßnovanΘ automatickΘ p°ihlßÜenφ [server login:name password:password]; 
  111. }
  112.  
  113. Mßme-li k dispozici p°φstup k °φdicφmu objektu, m∙₧eme pohodln∞ zavΘst dalÜφ high-order zprßvu spojenou s Φasem. Zprßva repeatWithDelay: °φkß: "Nßsledujφcφ zprßvu poÜli ka₧d²ch N sekund." Chceme-li pravidelnΘ zasφlßnφ zprßvy ukonΦit, vyu₧ijeme op∞t °φdicφ objekt a zprßvu cancel.
  114. Slu₧by systΘmu HOM nejsou ani zdaleka omezeny jen na to, co jsme si dosud ukßzali - znaΦnΘ mno₧stvφ nejr∙zn∞jÜφch tradiΦnφch programov²ch struktur je mo₧nΘ nahradit high-order zprßvami. Uka₧me si n∞kolik dalÜφch typick²ch p°φklad∙ vyu₧itφ HOM.
  115.  
  116. Hlφdßnφ p°φstupov²ch prßv
  117. Ve slo₧it∞jÜφch programov²ch systΘmech Φasto platφ, ₧e °ada akcφ (reprezentovan²ch v objektovΘm prost°edφ zprßvami) je povolena pouze n∞kter²m u₧ivatel∙m, kte°φ disponujφ pat°iΦn²mi prßvy. V tradiΦnφm programovßnφ bychom museli poka₧dΘ pou₧φt p°φkaz if; elegantn∞jÜφ ale je p°ipravit high-order zprßvu ifAllowedForCurrentUser, a kteroukoli z "citliv²ch" zprßv posφlat jejφm prost°ednictvφm: 
  118.  
  119. id account=[[database ifAllowedForCurrentUser] accountForName:client]; 
  120. [[database ifAllowedForCurrentUser] removeClient:client];
  121.  
  122. Zprßva ifAllowedForCurrentUser zjistφ, kter² u₧ivatel je momentßln∞ p°ihlßÜen, a ov∞°φ, zda je pro n∞j po₧adovanß akce (v naÜem p°φkladu zφskßnφ nebo smazßnφ ·daj∙ o klientovi) p°φpustnß. Pokud ano, zprßvu p°edß; ne-li, generuje v²jimku.
  123.  
  124. OÜet°enφ v²jimek
  125. I pro zpracovßnφ v²jimek se mohou obΦas hodit slu₧by HOM. Pom∞rn∞ Φasto narazφme na situaci, v nφ₧ v²jimku bezprost°edn∞ nezpracovßvßme - jen ji ulo₧φme, aby jejφ ulo₧enou hodnotu mohly vyu₧φt rutiny grafickΘho u₧ivatelskΘho rozhranφ ve chvφli, kdy budou u₧ivateli hlßsit, ₧e doÜlo k n∞jakΘ chyb∞, a proto jφm vy₧ßdanß akce nebyla provedena. V tradiΦnφm programovßnφ obvykle odpovφdajφcφ k≤d vypadß n∞jak takto: 
  126.  
  127. lastError=nil; 
  128. NS_DURING // zaΦßtek chrßn∞nΘho bloku [sqlServer commit]; 
  129. NS_HANDLER // doÜlo k v²jimce lastError=localException; 
  130. NS_ENDHANDLER
  131.  
  132. Jestli₧e tedy p°i zpracovßnφ commitu doÜlo k v²jimce, vyvolß se chybov² k≤d, kter² tuto v²jimku ulo₧φ do prom∞nnΘ lastError.
  133. GrafickΘ u₧ivatelskΘ rozhranφ jen zkontroluje obsah tΘto prom∞nnΘ. Je-li nulov², akce byla provedena; jinak ohlßsφ u₧ivateli chybu, jejφ₧ p°φΦinou je lastError.
  134. Mßme-li k dispozici HOM, m∙₧eme tento p°φklad p°epsat daleko pohodln∞ji: 
  135.  
  136. lastError=[[sqlServer safely] commit];
  137.  
  138. High-order zprßva safely toti₧ °φkß: "Nßsledujφcφ zprßvu poÜli uvnit° chrßn∞nΘho bloku; dojde-li p°itom k v²jimce, vra¥ ji. Pokud zprßva prob∞hne bez problΘm∙, vra¥ nil."
  139.  
  140. Paralelnφ zpracovßnφ
  141. O paralelnφm zpracovßnφ u₧ jsme se zmφnili s tφm, ₧e zprßvy typu each nebo collect mohou v rßmci polymorfismu pro n∞kterß pole (a n∞kterΘ zprßvy) rozesφlat zprßvy v r∙zn²ch threadech. HOM ovÜem nabφzφ °adu dalÜφch mo₧nostφ. NejjednoduÜÜφ jsou varianty ji₧ znßm²ch zprßv, je₧ paralelnφ zpracovßnφ v ka₧dΘm p°φpad∞ vynutφ:
  142.  
  143. [[poleOken concurrentEach] close]; 
  144. NSArray *titulky=[[poleOken concurrentCollect] title]; 
  145. NSArray *vo=[[poleOken concurrentSelect] isVisible];
  146.  
  147. Tyto varianty high-order zprßv v₧dy spustφ tolik thread∙, kolik je v poli objekt∙, a v ka₧dΘm z nich poÜlou jednu zprßvu - ty jsou tedy vÜechny zpracovßny najednou. DalÜφ velmi Üikovnß high-order zprßva umo₧nφ p°φmo spustit dalÜφ thread:
  148.  
  149. [[sheet inNewThread] recalculate];
  150.  
  151. P°edpoklßdßme-li, ₧e sheet reprezentuje tabulku v spreadsheetu, je rozumnΘ vy₧ßdat si jejφ p°epoΦφtßnφ v samostatnΘm threadu - a to je p°esn∞ to, co high-order zprßva inNewThread zajistφ.
  152. Chceme-li s hlavnφm threadem poΦkat, ne₧ skonΦφ zpracovßnφ vedlejÜφho threadu, m∙₧eme pou₧φt p°φstup k °φdicφmu objektu velmi podobn²m zp∙sobem, jak²m jsme si to ukßzali s ΦasovaΦem:
  153.  
  154. [thread=[sheet inNewThread] recalculate]; 
  155. ...
  156. [thread wait];
  157.  
  158. Jde-li nßm ovÜem o zφskßnφ v²sledku, na n∞m₧ samostatn² thread pracuje, nabφzφ objektovΘ prost°edφ a HOM mnohem elegantn∞jÜφ °eÜenφ. Je toti₧ mo₧nΘ za°φdit, aby high-order slu₧ba vrßtila tzv. zßstupn² objekt. Ten ned∞lß nic jinΘho, ne₧ ₧e udr₧uje vazbu na thread a Φekß, a₧ mu kdokoli poÜle jakoukoli zprßvu. Jakmile se to stane, zßstupn² objekt nejprve vyvolß slu₧bu wait (poΦkß, a₧ thread svou prßci dokonΦφ), pak nahradφ sßm sebe v²sledkem threadu - a nakonec jeÜt∞ tomuto skuteΦnΘmu v²sledku poÜle zprßvu, ji₧ sßm dostal! (Vidφme, ₧e vzhledem k nep°φmΘmu odeslßnφ zprßvy vlastn∞ jde op∞t o dalÜφ slu₧bu HOM.) Na prvnφ p°eΦtenφ to znφ slo₧it∞, ale v programovacφm jazyce s vyu₧itφm HOM je to nesmφrn∞ jednoduchΘ:
  159.  
  160. NSArray *seznam=[[database future] complicatedSearch]; 
  161. ... 
  162. printf("%d prvk∙",[seznam count]);
  163.  
  164. High-order slu₧ba future spustφ nov² thread a v n∞m p°edß objektu database zprßvu complicatedSearch stejn∞, jako by to ud∞lala high-order zprßva inNewThread. Zprßva future vÜak navφc vytvo°φ specißlnφ zßstupn² HOM objekt a ten vrßtφ mφsto po₧adovanΘho pole.
  165. V dob∞, kdy b∞₧φ libovoln² k≤d oznaΦen² v naÜem p°φkladu t°emi teΦkami, zßrove≥ probφhß "komplikovanΘ vyhledßvßnφ" v databßzi, a prom∞nnß seznam neobsahuje pole (ale zßstupn² objekt). Jakmile ovÜem poÜleme zßstupnΘmu objektu prvnφ zprßvu - v naÜem p°φpad∞ zprßvu count -, vÜe se zm∞nφ. SystΘm HOM se postarß o to, aby hlavnφ thread nejprve poΦkal, ne₧ prohledßvßnφ databßze skonΦφ; pak se seznam nahradφ skuteΦn²m v²sledkem (tedy polem nalezen²ch ·daj∙) a ten dostane zprßvu count. P°φkaz printf tedy skuteΦn∞ vypφÜe sprßvn² poΦet nalezen²ch ·daj∙.
  166. Je tΘm∞° zbyteΦnΘ dodßvat, ₧e pokud nßhodou thread, v n∞m₧ probφhß slu₧ba complicatedSearch, skonΦφ d°φve ne₧ k≤d oznaΦen² t°emi teΦkami, systΘm HOM se postarß o to, aby se zßstupn² objekt seznam ihned nahradil skuteΦn²m v²sledkem. A₧ pak dojde na zprßvu count v p°φkazu printf, bude ji₧ seznam obsahovat skuteΦnΘ v²slednΘ pole a vÜe bude v po°ßdku.
  167.  
  168. Posφlßnφ zprßv tomu, kdo jim rozumφ
  169. V objektovΘm prost°edφ je nesmφrn∞ v²hodn²m a velmi Φasto u₧φvan²m trikem odeslßnφ zprßvy n∞jakΘmu objektu jen tehdy, kdy₧ objekt danΘ zprßv∞ rozumφ.
  170. Vzhledem k tomu, ₧e u₧ivatelΘ jazyk∙ typu C++ (a do jistΘ mφry i Javy), je₧ nabφzejφ jen nedokonalou podporu objektovΘho programovßnφ, nemajφ s tφmto systΘmem zkuÜenosti, stojφ za to uvΘst n∞kolik p°φklad∙:
  171. Mßme okno a jeho °φdicφ objekt. Okno °φdicφ objekt informuje o zm∞nßch velikosti, pokud °φdicφ objekt rozumφ odpovφdajφcφ zprßv∞.
  172. Mßme tabulku a objekt, jen₧ dodßvß data, kterß tabulka zobrazuje.
  173. Pokud °φdicφ objekt rozumφ zprßv∞ pro zm∞nu dat v danΘ °ßdce a danΘm sloupci, tabulka tuto zm∞nu automaticky umo₧nφ - jestli₧e tomu tak nenφ, tabulka bude "read-only".
  174. Mßme pole objekt∙ reprezentujφcφch aktivnφ prvky u₧ivatelskΘho rozhranφ. U₧ivatel si vy₧ßdal slu₧bu Copy. Vyhledßme proto v poli objekt, kter² rozumφ zprßv∞ copy, a poÜleme mu ji. Tak je automaticky zajiÜt∞no, ₧e kopφrujeme skuteΦn∞ obsah textovΘho pole, a ne t°eba tlaΦφtka.
  175. Ve vÜech p°φkladech jde v₧dy o to samΘ - na mφst∞ °φdicφho objektu m∙₧e stßt zcela libovoln² objekt, v jeho₧ rßmci implementujeme zpracovßnφ jen t∞ch zprßv, kterΘ pro nßs majφ v danΘ aplikaci smysl.
  176. P°i rozhodovßnφ, kterΘ zprßvy jakΘmu objektu poslat, nßm HOM op∞t pom∙₧e uspo°it n∞jakΘ "ify" a "fory" proti tradiΦnφmu programovßnφ:
  177.  
  178. [[delegate ifPossible] resizedFrom:oldSize to:newSize]; 
  179. [[views firstThatResponds] copy];
  180.  
  181. P°φklady jen ilustrujφ v²Üe uveden² text. V prvnφm posφlßme objektu delegate (°φdicφ objekt) zprßvu resizedFrom:to:, kterß jej informuje o zm∞n∞ velikosti - ovÜem pouze v p°φpad∞, ₧e °φdicφ objekt tΘto zprßv∞ rozumφ; nenφ-li tomu tak, jde o prßzdnou akci. Ve druhΘm p°φpad∞ vyhledßme v poli views ( je₧ obsahuje prvky u₧ivatelskΘho rozhranφ) prvnφ objekt, jen₧ rozumφ zprßv∞ copy, a zprßvu mu poÜleme.
  182.  
  183. To je zatφm vÜe...
  184. Do dneÜnφho Φlßnku se ji₧ vφce informacφ o systΘmu HOM nevejde. Bude-li vÜak k tomu p°φle₧itost, °ekneme si v budoucnosti o tΘto nesmφrn∞ zajφmavΘ technologii vφce. Vysv∞tlφme si princip, na kterΘm HOM funguje, ukß₧eme si p°φklad jeho konkrΘtnφ implementace a praktickΘ p°φklady jeho pou₧itφ.
  185. Ond°ej ╚ada
  186.  
  187. Umφte-li anglicky, m∙₧ete vφce informacφ o HOM vΦetn∞ zdrojov²ch text∙ najφt takΘ na adrese http://www.metaobject.com.
  188.  
  189.  
  190.