A Unix rendszerek alapvető segédprogramjait jellemző "tegyél egy dolgot, de azt helyesen" és "működj együtt más, elemi funkciókat ellátó programokkal" elvek eltűnni látszanak a mai monolitikus, behemót "desktop-alkalmazások" árnyékában. A GNOME Bonobo rendszere lehetővé teszi a szoftverkomponensek együttműködését a modern alkalmazások igényeit is kielégítve. BevezetőA bonobo (Pan paniscus) az óvilági emberszabásúak közé tartozó, veszélyeztetett (jelenleg alig 10,000-re tehető a számuk) majomfaj. A ma élő fajok közül ők hasonlítanak a legjobban a csimpánzok és az emberek közös ősére. Laikusok számára a legfeltűnőbb sajátosságuk az, ami miatt a GNOME komponensrendszerének névadói is lettek: nagyon szoros és gyakori az interakció a fajtársak között. Ez a gyakorlatban kevésbé cizelláltan jelenik meg: fehérmájú, szexőrült nimfománok.1 A Bonobo rendszer segítségével lehetőséget teremthetünk egymástól hálózatilag és platformilag független programok kommunikációjára. Az előadás során a rendszer általános működése mellett egy-két implementációs részlettel is megismerkedhetsz. 1. IPC megoldásokMint az a kivonatban is szerepelt, alapvető igény a programok iránt, hogy kommunikálni tudjanak egymással. Ez természetesen különböző szinteken és módokon történhet. Tekintsük át az inter-process communication lehetőségeit! Hagyományos UNIX IPC: pipe, socketEzeket az eszközöket minden Unix fejlesztő és felhasználó ismeri. Alacsony szintű, általános adatátviteli mód processzek között, lokálisan vagy hálózaton át. Az alacsony szintűség egyben a fő hátrányuk is: ezek az eszközök "analóg" továbbítják az információt. Képzeld el például, hogy egy olyan alkalmazás készítése a feladatod, amely az lpq program kimenete alapján készít valamiféle statisztikát a nyomtatási spool pillanatnyi helyzetéről. Különböző lpq implementációk különbözőképpen fogják formázni a kimenetüket, ezáltal lehetetlenné téve a kimenet parse-olását. CORBAA CORBA többek között ezt a problémát oldja meg, oly módon, hogy az egyes alkalmazások csak jól definiált interfészeken keresztül kommunikálhatnak egymással. Az egyes implementációk között így "kifelé" elvész a különbség, és (az előbbi példánál maradva) nem kell törődnöd különböző gyártók lpd implementációinak különbségével. A CORBA további, jól ismert előnyei a kommunikáció teljesen transzparens volta hálózati és/vagy platformi határok között. COMA Microsoft már egészen régi időktől fogva elkezdte a Windows komponensrendszerének kialakítását: bizonyára sokan emlékeznek a Windows 3.1 platform egyik legprominensebb újdonságát jelentő OLE (Object Linking and Embedding) hírértékére. Sok-sok reinkarnációval később, mára a COM rengeteg alkalmazás, vírus és backdoor motorját jelenti. A COM hátránya a többi IPC megoldáshoz képest, hogy kizárólag Windows platformokon érhető el, és (ennek megfelelően) architektúrája is sok mozzanatban lehetetlenné, vagy legalábbis nehézkessé teszi portolását más platformokra.
BonoboAz előadás tárgya, a Bonobo rendszer a COM alapfelépítésének egyes elemeit veszi át, a tényleges kommunikációt CORBA objektumokkal oldva meg -- így bárki elkészítheti saját Bonobo implementációját a saját platformjára.2 2. Komponensaktiváció: OAFEgy komponensalapú alkalmazás nem csak a code reuse előnyét nyújtja (ez sok más módon is megoldható), hanem lehetővé teszi, hogy olyan komponenseket is fel tudjon használni a programod, amelyeket tőled független fejlesztők (ISV-k) készítettek. Ehhez az szükséges, hogy az alkalmazás válogatni tudjon a különböző telepített, és igényeinek megfelelő komponensek közül. Ez két különböző, de összefüggő lépést jelent: (1) a telepített komponensek lekérdezése és (2) a kívánt komponensek aktivációja. Elliot Lee Object Activation Framework nevű programja ezeket az igényeket hivatott kielégíteni. CORBA-n át történik a lekérdezés és az aktiválás, így helyi és távoli objektumok egyaránt elérhetőek. A tényleges aktiváció folyamatakor az OAF gondoskodik a szerverprogram elindításáról (vagy ha az egy shared object-ben található, betöltéséről és linkeléséről), és a felhasználó már a "készre szerelt" CORBA objektumot kapja kézhez. A kiválasztható komponensek listáját az OAF egy, saját lekérdezőnyelvén írt kérésre juttatja el a programhoz. Ez a lekérdezés megszorításokat tartalmazhat például a megvalósított interfészekre ("milyen nyomtatható komponensek vannak telepítve"), vagy a fejlesztő által definiált tulajdonságok értékeire (pl. file-megjelenítő komponensek közül azok kiválasztása, amelyek egy adott MIME-típust támogatnak). A lekérdezések végrehajtását az OAF ObjectDirectory CORBA objektumokra bízza, így egy szerver több platform és számítógép komponenslistáit mutathatja egységesen a kliensprogram felé. A komponensaktivációnak létezik egy magasabbszintű lehetősége is, a Bonobo::Moniker3 interfészen keresztül. A különböző Moniker implementációkkal lehetséges például egy file megnyitása a hozzátartozó komponenssel, vagy egy összetett komponens egy adott darabjának kijelölése (például hivatkozhatunk egy Gnumeric táblázatfile egy bizonyos munkalapjának egy cellatartományára). 3. A rendszer alapköve: A Bonobo::UnknownAz előző pontokban dobálóztam már objektumokkal, anélkül, hogy konkétan megmondtam volna, mire is gondolok. Az Unknown interfész képezi a Bonobo rendszer alapját: valamennyi, tényleges feladatot elvégző felület ebből származtatik le. Ez az apró interfész mindössze a következőkből áll:
interface Unknown
{
void ref ();
void unref ();
Unknown query_interface (in string repoid);
};
Nézzük mit is jelentenek az egyes metódusok:
4. A rendszer működése egy példán keresztül4.1. A modellalkalmazásunkEbben a fejezetben egy hipotetikus alkalmazás: egy szövegszerkesztő működését mutatom be, az eddigi elméleti információ gyakorlati megjelenését. Szövegszerkesztőnk a Bonobo rendszer segítségével lehetővé teszi felhasználóinak, hogy a dokumentumot alkotó szöveget és a beillesztett objektumokat egységesen kezelje. Lássuk, hogyan is éri ezt el! 4.2. Komponensbeillesztés, szerkesztésFelhasználónk4 szeretne beilleszteni egy képet szövegébe. Ehhez kiválasztja alkalmazásunk megfelelő menüpontját. Ennek tényleges megvalósítása többféle is lehet: például egy file beillesztése a megfelelő Moniker-rel, vagy programunk lekérdezi az OAF szervertől azon komponensek listáját, amelyek megvalósítják az Embeddable és/vagy Control interfészeket. Mindkét esetben eredményképpen egy Unknown objektumot kapunk, amelyet vagy rögtön megjeleníthetünk (Control), vagy egy adathoz több nézetet készíthetünk (Embeddable, View). Ezekután a dokumentumunkban való tényleges megjelenítést az X protokollra bízhatjuk. Amikor a felhasználó módosítani akar a beillesztett elemen, két megoldás lehetséges: vagy külön ablak nyílik a szerkesztés elvégzésére, vagy pedig (a UIHandler interfész5 segítségével) a komponens felhasználói felülete összeolvad a konténerével. 4.3. Nyomtatás, tárolásA nyomtatás tulajdonképpen teljesen ugyanúgy történik, mint a beillesztés: amennyiben a komponens megvalósítja a Print interfészt, szövegszerkesztőnk kijelöl a papíron egy területet, és megkéri a komponenst, hogy nyomtasson oda. Példaalkalmazásunk szeretné a saját adatai (a dokumentum) mellett a beillesztett elemek állapotát is rögzíteni. Erre a Persist* interfész-család szolgál. A legegyszerűbb esetben a PersistFile felületet használva, egy filenév megadására van csak szükség, és a komponens gondoskodik a file kezeléséről. Ez azonban nem javasolt, mivel így a komponens futási helye szabja meg a file helyét is, később ugyanaz a komponens például egy másik számítógépen futva nem ugyanazokat az adatokat éri el. Ezen okokból két olyan interfész is része a Bonobo rendszernek, ahol az adatok CORBA-n át jutnak vissza a komponenstől a konténerig. A PersistStream interfész segítségével egy Stream-be, tehát egy egyszerű byte-sorozatba/ból írhatjuk/olvashatjuk adatainkat, a PersistStorage segítségével pedig a Storage nevű, fastruktúrájú "mini-filerendszerbe". Szövegszerkesztő alkalmazásunkkal a fenti lehetőségek megismerése után a teljes dokumentumot egy Storage-ban tároljuk. Minden komponensünk kap ezen belül egy Stream-et vagy egy újabb Storage-ot, amibe a megfelelő Persist* interfészen át elmentjük az állapotát.
4.4 Valódi példákTermészetesen az ebben a részben bemutatott modellalkalmazás mellett egyre több "valódi" alkalmazás is használja a Bonobo rendszert. Az alábbi lista a teljesség igénye nélkül említ meg néhány fontos, Bonobo-alapú alkalmazást.
5. A GNOME Bonobo implementációjaA legtöbben nem a "nyers" Bonobo CORBA hívásokon át kommunikálnak a többi komponenssel, hanem az adott platform és nyelv sajátosságaihoz igazodó, a felhasználást megkönnyítő API-ken át. A Bonobo rendszer kifejlesztésével párhuzamosan folyt-folyik egy implementáció fejlesztése is. A GNOME/C Bonobo implementáció fő célja, hogy minél tökéletesebben beépüljön a GTK+ objektumrendszerébe, ezért valamennyi objektuma a GtkObject osztály leszármazottja. Ez nem csak a CORBA objektumok GtkObject-té történő leképezését jelenti6, hanem sok implementációt, amely lehetővé teszi, hogy egy-két függvényhívással működő Bonobo komponenst készítsünk. Ahhoz például, hogy egy elkészített GtkWidget-ből egy Bonobo::Control-t hozz létre, elegendő a bonobo_control_new (GtkWidget *widget) hívást használnod. Ezekután a GNOME Bonobo implementáció gondoskodik arról, hogy megjelenjen a túloldalon a widget, lehetőleg optimális méretű legyen, stb. Hasonlóan egyszerűen hozhatsz létre egy Storage objektumot egy EFS file-ban, vagy nyújthatsz a felhasználónak lehetőséget, hogy a valamilyen feltételnek megfelelő komponensek közül válasszon. A libbonobo egyszerű kezelhetőségét talán mi sem mutatja jobban, mint hogy annak idején, amikor először ismerkedtem a Bonobo rendszerrel, a GTK+-os ismereteim alapján fél napba telt egy működő \interface{Embeddable} létrehozása. 6. MonkeyBeans2000 júliusában kezdtem el dolgozni a MonkeyBeans rendszeren. A project célja egy Java-alapú Bonobo implementáció létrehozása, ezáltal a gyakorlatban is vizsgálva a Bonobo architektúra platformfüggetlenségét. Sajnos hamar kiderült, hogy száz százalékosan tisztán Javában nem lehetséges megoldani a feladatot: a rendszer Unix-orientáltsága miatt szükség van olyan lehetőségek kihasználására, amik a Java platformfüggetlensége miatt nem érhetők el a virtuális gépen belül (például alacsonyszintű X hívások a beágyazhatósághoz, vagy adott filedescriptorokba írás az OAF-fal történő aktiválhatósághoz). Mindemellett a ráfordításokhoz képest nagyon gyorsan eljutott az "éppenhogy használható" szintre: feltöltöttem egy file-ból egy komponenst a PersistStream interfészen át, és beillesztettem egy AWT ablakba egy Control-t, a menük összeolvasztásával együtt. Sajnos a jövőben bizonytalan a MonkeyBeans sorsa: magam a sokkal hasznosabbnak (bár kevésbé úttörőnek) ígérkező Bonobomm C++ felület fejlesztésére tértem át, és egyelőre nem látni, hogy valaki átvenné a fejlesztést. Az érdeklődők bármikor megtalálják a kódot a cvs.gnome.org szerver monkeybeans moduljában. ÖsszefoglalásA GNOME eredeti célkitűzése (mint az a nevében is megjelenik) egy objektumokból felépülő, moduláris környezet létrehozása volt. Ennek elérésében a legfontosabb eszköze a Bonobo, minden határt megszüntetve a különböző szállítók, platformok, számítógépek között.Remélhetőleg előadásom meggyőzött, hogy a Bonobo egy erőteljes, de ugyanakkor egyszerűen használható megoldást nyújt a komponensalapú fejlesztéshez. Amennyiben igen, a libbonobo dokumentációjában megtalálhatóak azok az információk, amelyek a mindennapi használathoz szükségesek -- előadásom célja nem függvénynevek felsorolása volt, hanem egy átfogó kép átadása a rendszer felépítéséről. Lábjegyzetek
| ||||||||