2.2.1 A névmodell
Szükséges, hogy legyen egy modellünk arról, hogy a nevek hogyan kapcsolódnak bizonyos objektumokhoz. A rendszertervező létrehoz egy elnevezési sémát, amely három elemből áll. Az első elem a névtér, amely a szimbólumok ábécéjéből és az elfogadható neveket meghatározó szintaktikai szabályokból áll. A második elem egy név-leképező algoritmus, amely a névtér néhány (nem feltétlenül minden) nevét az értékek univerzumának néhány (szintén nem feltétlenül minden) értékéhez társítja, ami a névadási séma harmadik és egyben utolsó eleme. Az érték lehet egy objektum, vagy lehet egy másik név akár az eredeti névtérből, akár egy másik névtérből. A név-érték leképezés egy példa a kötésre, és ha létezik ilyen leképezés, akkor a nevet az értékhez kötöttnek mondjuk. A 2.10. ábra szemlélteti.
A legtöbb rendszerben jellemzően egyszerre több különböző névadási séma működik. Például egy rendszer használhat egy elnevezési sémát az e-mail postafiókok neveihez, egy másodikat az internetes hosztokhoz, egy harmadikat a fájlokhoz, és egy negyediket a virtuális memóriacímekhez. Amikor egy programértelmező egy névvel találkozik, tudnia kell, hogy melyik elnevezési sémát kell meghívnia. A név használatát körülvevő környezet általában elegendő információt nyújt a névséma azonosításához. Például egy alkalmazási programban a program szerzője tudja, hogy a programnak a fájlneveket csak a fájlrendszer, az internetes állomásneveket pedig csak valamilyen hálózati szolgáltatás értelmezésével kell számolnia.
A névvel találkozó értelmező lefuttatja a megfelelő megnevezési séma névleképező algoritmusát. A névtérképező algoritmus feloldja a nevet, ami azt jelenti, hogy felfedezi és visszaadja a hozzá tartozó értéket (emiatt a névtérképező algoritmust feloldónak is nevezik). A név-leképező algoritmust általában egy további paraméter, az úgynevezett kontextus vezérli. Egy adott névadási séma esetében több különböző kontextus is létezhet, és a névtér egyetlen neve különböző értékekhez kapcsolódhat, ha a feloldó különböző kontextusokat használ. Például a hétköznapi beszédben, amikor egy személy a “te”, “itt” vagy “Alice” nevekre hivatkozik, az egyes nevek jelentése attól függ, hogy az illető milyen kontextusban mondja ki őket. Másrészt egyes megnevezési sémáknak csak egy kontextusa van. Az ilyen elnevezési sémák úgynevezett univerzális névtereket biztosítanak, és rendelkeznek azzal a szép tulajdonsággal, hogy egy névnek mindig ugyanaz a jelentése az adott elnevezési sémán belül, függetlenül attól, hogy ki használja. Az Egyesült Államokban például a társadalombiztosítási számok, amelyek az állami nyugdíj- és adószámlákat azonosítják, egyetemes névteret alkotnak. Ha egynél több kontextus van, az értelmező megmondhatja a feloldónak, hogy melyiket használja, vagy a feloldó használhat egy alapértelmezett kontextust.
A névmodellt a következő, neveken végzett fogalmi művelet meghatározásával foglalhatjuk össze:
érték ← resolve (név, kontextus)
Amikor az értelmező egy névvel találkozik egy objektumban, először kitalálja, hogy milyen névrendszerről van szó, és így a resolve melyik változatát kell meghívnia. Ezután azonosítja a megfelelő kontextust, feloldja a nevet ebben a kontextusban, és az értelmezés folytatásakor a nevet a feloldott értékkel helyettesíti. A változó context megmondja a resolve-nek, hogy melyik kontextust használja. Ez a változó egy kontextusreferenciaként ismert nevet tartalmaz.
A processzorban a regiszterszámok nevek. Egy egyszerű processzorban a regiszternevek halmaza és a regiszterek, amelyekhez ezek a nevek kötődnek, mindkettő fix a tervezéskor. A legtöbb más, neveket használó rendszerben (beleértve néhány nagy teljesítményű processzor regiszterelnevezési sémáját is) lehetőség van új kötések létrehozására és a régiek törlésére, a névtér felsorolására a meglévő kötések listájának megszerzése érdekében, valamint két név összehasonlítására. Ezekre a célokra négy további fogalmi műveletet definiálunk:
status ← bind (name, value, context)
status ← unbind (name, context)
list ← enumerate (context)
result ← compare (name1, name2)
Az első művelet egy új kötés hozzáadásával megváltoztatja a kontextust; az állapoteredmény arról számol be, hogy a változtatás sikeres volt-e vagy sem (sikertelen lehet, ha a javasolt név sérti a névtér szintaxisszabályait). A bind sikeres hívása után a resolve visszaadja a name új értékét.*A második művelet, az unbind, eltávolít egy meglévő kötést a kontextusból, a status ismét sikert vagy sikertelenséget jelent (esetleg azért, mert nem volt ilyen meglévő kötés). Az unbind sikeres hívása után a resolve már nem adja vissza a name értékét. A bind és unbind műveletek lehetővé teszik a nevek használatát az objektumok közötti kapcsolatok létrehozására és a kapcsolatok későbbi megváltoztatására. Egy objektum tervezője egy név használatával egy komponensobjektumra való hivatkozással kiválaszthatja azt az objektumot, amelyhez a név akkor vagy később a bind meghívásával kötődik, és az unbind meghívásával megszüntetheti a már nem megfelelő kötést, mindezt anélkül, hogy a nevet használó objektumot módosítaná. A kötések késleltetésének és módosításának ez a képessége erőteljes eszköz, amelyet szinte minden rendszer tervezésénél használnak. Néhány névmegvalósítás enumerate műveletet biztosít, amely visszaadja a kontextusban feloldható összes név listáját. Az enumerate egyes implementációi a kontextusban jelenleg kötött értékek listáját is visszaadják. Végül a compare művelet azt jelenti (igaz vagy hamis), hogy name1 megegyezik-e name2-vel. Az “azonos” jelentése egy érdekes kérdés, amelyet a 2.2.5. szakasz tárgyal, és amely további kontextusargumentumok megadására lehet szükség.
A különböző névadási sémáknak különböző szabályai vannak a név-érték megfeleltetések egyediségére vonatkozóan. Egyes elnevezési sémák szabálya szerint egy névnek egy adott kontextusban pontosan egy értékhez kell tartoznia, és egy értéknek csak egy neve lehet, míg más elnevezési sémákban egy név több értékhez is tartozhat, vagy egy értéknek több neve is lehet, akár ugyanabban a kontextusban is. Az egyediség egy másik fajtája az egyedi azonosító névtér szabálya, amely olyan nevek halmazát biztosítja, amelyek a névtér élettartama alatt soha nem használhatók fel újra, és ha egyszer már lekötötték őket, mindig ugyanahhoz az értékhez lesznek kötve. Az ilyen névről azt mondjuk, hogy stabil kötéssel rendelkezik. Ha az egyedi azonosító névtérben az a szabály is érvényesül, hogy egy értéknek csak egy neve lehet, akkor az egyedi nevek hasznosak lesznek az objektumok hosszú időn át történő nyomon követésére, a hivatkozások összehasonlítására, hogy kiderüljön, ugyanarra az objektumra vonatkoznak-e, valamint a több példány koordinálására olyan rendszerekben, ahol az objektumokat a teljesítmény vagy a megbízhatóság érdekében replikálják. Például a legtöbb számlázási rendszer ügyfélszámlaszáma egyedi azonosító névteret alkot. A számlaszám mindig ugyanarra az ügyfélszámlára fog hivatkozni, amíg a számla létezik, az ügyfél címének, telefonszámának vagy akár személynevének változása ellenére is. Ha egy ügyfélszámla törlésre kerül, az ügyfél számlaszáma egy napon nem használható fel újra egy másik ügyfél számlájához. A számlán belüli névmezők, mint például az esedékes egyenleg, időről időre változhatnak, de az ügyfélszámlaszám és maga a számla közötti kötés stabil.
A névleképező algoritmus és egyetlen kontextus nem feltétlenül képezi le a névtér összes nevét értékekre. Így a resolve végrehajtásának lehetséges eredménye lehet egy nem talált eredmény, amelyet a resolve vagy fenntartott értékként, vagy kivételként közölhet a hívóval. Másrészt, ha a névséma lehetővé teszi, hogy egy név több értéket is leképezzen, a lehetséges eredmény egy értéklista lehet. Ebben az esetben az unbind művelethez szükség lehet egy további argumentumra, amely megadja, hogy melyik értéket kell feloldani. Végül, néhány névadási séma fordított keresést biztosít, ami azt jelenti, hogy a hívó megadhat egy értéket argumentumként a névleképező algoritmusnak, és megtudhatja, hogy milyen név vagy nevek kapcsolódnak ehhez az értékhez.
A 2.10. ábra a névadási modellt szemlélteti, bemutatva egy névteret, a megfelelő értékek univerzumát, egy névleképező algoritmust és egy kontextust, amely a névleképező algoritmust vezérli.
A gyakorlatban három gyakran használt névtérképező algoritmussal találkozunk:
Táblázatos keresés
■
Rekurzív keresés
■
Multiple lookup
A kontextus leggyakoribb megvalósítása egy {név, érték} párokat tartalmazó táblázat. Ha a kontextus megvalósítása egy táblázat, akkor a név-leképező algoritmus csak a név keresése a táblázatban. Maga a táblázat lehet összetett, tartalmazhat hashinget vagy B-fákat, de az alapötlet ugyanaz. Egy új név értékhez kötése abból áll, hogy a {név, érték} párost hozzáadjuk a táblázathoz. A 2.11. ábra a névadási modellnek ezt az általános megvalósítását szemlélteti. Minden kontextushoz egy ilyen táblázat tartozik, és a különböző kontextusok különböző kötéseket tartalmazhatnak ugyanahhoz a névhez.
A valós világban számos példa található mind az általános névmodellre, mind a táblázatos keresés megvalósítására:
A telefonkönyv egy táblázatos keresési környezet, amely személyek és szervezetek neveit telefonszámokhoz köti. Az adatkommunikációs hálózati példához hasonlóan a telefonszámok maguk is nevek, amelyeket a telefontársaság fizikai vonalmegjelenésekké old fel egy olyan név-leképező algoritmus segítségével, amely magában foglalja a körzetszámokat, a központokat és a fizikai kapcsolóberendezéseket. A bostoni és a San Franciscó-i telefonkönyvek ugyanannak a névsémának két kontextusa; bármelyik név megjelenhet mindkét telefonkönyvben, de ha igen, akkor valószínűleg különböző telefonszámokhoz van kötve.
A processzor regisztereit kis egész számok nevezik el. Az érték maga a regiszter, és a név-érték leképezése huzalozással történik.
A memóriacellákat hasonlóan nevezik el a címnek nevezett számokkal, és a név-érték leképezése ismét huzalozással történik. Az 5. fejezet ismerteti a virtuális memória néven ismert címátnevezési mechanizmust, amely virtuális címek blokkjait egybefüggő memóriacellák blokkjaihoz köti. Ha egy rendszer több virtuális memóriát valósít meg, minden egyes virtuális memória különálló kontextust jelent; egy adott cím minden egyes virtuális memóriában más-más memóriacellára utalhat. A memóriacellák megoszthatók a virtuális memóriák között is, ilyenkor ugyanaz a memóriacella különböző virtuális memóriákban azonos (vagy különböző) címekkel rendelkezhet, ahogyan azt a kötések meghatározzák.
Egy tipikus számítógépes fájlrendszer a nevek és kontextusok több rétegét használja: a lemezszektorok, lemezpartíciók, fájlok és könyvtárak mind elnevezett objektumok. A könyvtárak példák a táblázatkeresési kontextusokra. Egy adott fájlnév több különböző könyvtárban is megjelenhet, azonos vagy különböző fájlokhoz kötve. A 2.5. szakasz egy esettanulmányt mutat be az elnevezésekről az unix fájlrendszerben.
A számítógépek a hálózati csatlakozási pontoknak nevezett helyeken csatlakoznak az adatkommunikációs hálózatokhoz. A hálózati csatolási pontokat általában két különböző elnevezési sémával nevezik el. Az első, amelyet a hálózaton belül használnak, egy fix hosszúságú mezőben lévő számokból álló névteret foglal magában. Ezek a nevek – néha állandóan, néha csak rövid ideig – a hálózat fizikai be- és kilépési pontjaihoz vannak kötve. A második, a hálózat ügyfelei által használt névrendszer egy felhasználóbarátabb, karakterláncokból álló univerzális névteret rendel az első névtér neveihez. A 4.4. szakasz a Domain Name System esettanulmánya, amely felhasználóbarát csatolási pontok elnevezését biztosítja az internet számára.
A programozó az eljárásváltozókat nevekkel azonosítja, és az eljárás minden egyes aktiválása külön kontextust biztosít, amelyben a legtöbb ilyen név feloldódik. Néhány “statikus” vagy “globális névként” azonosított név ehelyett olyan kontextusban is feloldható, amely az aktiválások vagy a különböző eljárások között közös. Amikor egy eljárást lefordítanak, a változók eredeti, felhasználóbarát nevei közül néhányat egész számú azonosítókkal helyettesíthetnek, amelyeket a gép számára kényelmesebb kezelni, de a névadási modell továbbra is érvényes.
A World Wide Web egységes forráskeresőjét (URL) egy viszonylag bonyolult algoritmus képezi le egy adott weboldalhoz, amely az URL-t több alkotóelemre bontja, és a részeket különböző névadási sémák segítségével oldja fel; az eredmény végül egy adott weboldalt azonosít. A 3.2. szakasz egy esettanulmányt mutat be erről az elnevezési sémáról.
Egy ügyfélszámlázási rendszer jellemzően legalább kétféle nevet tart fenn minden ügyfélszámlához. A számlaszám elnevezi a számlát egy egyedi azonosító névtérben, de van egy különálló névtér is a személynevekből, amelyek szintén használhatók a számla azonosítására. Mindkét nevet jellemzően egy adatbázis-rendszer hozzárendeli a számlarekordokhoz, így a számlák vagy a számlaszám, vagy a személynév alapján kereshetők le.
Ezek a példák rávilágítanak a “névadás” és a kötés közötti különbségre is. Néhány, de nem minden kontextus “megnevez” dolgokat, abban az értelemben, hogy egy nevet egy olyan objektumhoz rendel, amelyről általában úgy gondolják, hogy rendelkezik ezzel a névvel. Így a telefonkönyv nem “megnevezi” sem az embereket, sem a telefonvonalakat. Valahol máshol vannak olyan kontextusok, amelyek neveket kötnek emberekhez, és amelyek telefonszámokat kötnek konkrét fizikai telefonokhoz. A telefonkönyv az emberek neveit a telefonok neveihez köti.