ugrás a tartalomhoz

Bábeli zűrzavar I.

Bártházi András · 2005. Ápr. 30. (Szo), 22.00
Bábeli zűrzavar I.
Ha webfejlesztésre szánja magát az ember, felmerül a kérdés, vajon milyen nyelven kezdjünk neki, melyik lesz nekünk a legjobb? Figyelembe vehetjük saját ismereteinket (programozóinkét), a választandó nyelvek lehetőségeit (nyelvi tulajdonságok és modulok, általában a támogatottság) és további paramétereket is. A most induló cikksorozat azt mutatja be, hogy ha valamiért nem tudtunk dönteni, és két (vagy több) nyelvet is használnunk kell, nem kell elkeserednünk, mert számos lehetőségünk van a nyelvek közötti együttműködésre. Első alkalommal a nyelvfüggetlen megoldások kerülnek górcső alá.

Mielőtt nekikezdenénk, szeretném leszögezni, hogy nem biztos hogy jó ötlet több nyelvet választani. Ha egy teljes projekt, vagy több munkánk ugyanarra a programozási nyelvre épül, akkor azzal mélyebben meg tudunk ismerkedni, sokkal inkább elsajátíthatjuk a trükköket, több lehetőség tárulhat fel benne, s a fejlesztői környezet kialakítását tekintve is könnyebb dolgunk van: sok specializált fejlesztőkörnyezet létezik, mely egy adott nyelvre kínál nagyon jó megoldást. Ha csapatban dolgozunk, a helyzet hasonló: a fejlesztők akkor tudják egymást a legjobban támogatni, ha "egy nyelven beszélnek".

Ha a feladat komplex, az informatika, a webfejlesztés több ágát is érinti, akkor azonban nem biztos, hogy találunk egy olyan nyelvet, mely minden feladatra a legjobb megoldást tudja kínálni. Lehet, hogy egy feladatra az egyik nyelv a jó, lehet, hogy egy feladatra a másik. Ha csapatmunkáról van szó, lehet, hogy az egyik fejlesztőnk az egyik nyelvhez ért jobban, s lehet, hogy a másik fejlesztő egy másikhoz. Ez utóbbi nyilván nem általános a webfejlesztő cégeknél, hiszen specializálódni szoktak egy nyelvre, de ekkor is könnyedén előfordulhat, hogy valamelyik fejlesztő a múltból hozott magával egy nyelvet, amivel egyszerűbb megoldást tud kínálni. Itt mindjárt fel is hoznám a Weblabor példáját, ahol egy elég komplex megoldás áll jelenleg a szolgáltatások mögött: PHP, Perl, Python és ki tudja milyen nyelveket használunk még (C, C++ - mint a futtató környezet biztosan) a működtetéshez, az általunk hatékonynak gondolt megoldáshoz (ahol a szakmai ismeretek, s a rendelkezésre álló emberi erőforrások a leginkább döntőek).

Említtessék meg érdekességként: nem feltétlenül igaz, hogy a különböző nyelveken történő fejlesztés inkompatibilitást szül. Létezik ugyanis egy platform, mely már bizonyított, s fejlesztés alatt áll egy másik, mely nagyot dobbanthat. Az előbbi a .Net, az utóbbi a Parrot. Mind a két esetben egy virtuális gépen futnak az alkalmazások, mely egy egységes alapot teremtve "bármely" nyelven megírt programot képes futtatni (leginkább azokat, melyekhez készült fordító), s mely lehetővé teszi azt is, hogy az egyik nyelvből elérjük a másik nyelvben írt kódunkat: eljárásokat, rutinkönyvtárakat használhassunk, vagy egyszerűen változókat érhessünk el. A .Net-hez létezik Python, Perl, Java fordító, alapból támogatja a C#-ot és a Visual Basic-et, s további nyelveket is, melyeket most nem említettem. A Parrot-hoz készül a Perl 6, Perl 5, Python, Ruby, Java fordító (és még vagy egy tucat másik), s a tervek szerint képes lesz más virtuális gépek kódját is futtatni. A Java virtuális gépről se feledkezzünk el, mint egy lehetséges közös platform - bár ehhez nem olyan népszerűek az alternatív nyelvek. Nos, ebben a cikksorozatban nem ezekről a lehetőségekről lesz szó, hanem egy más szempontot fogunk megvizsgálni, avagy: Mit tehetünk, ha nem áll rendelkezésünkre egy közös alap?

A cikkben először azt nézzük meg, hogy melyek azon lehetőségek, melyek alapvetően egyszerűbbek, de általánosabbak, s szinte minden nyelv esetén használhatóak (főként a Perl és PHP nyelveket középpontba állítva, de nem ez lesz a lényeg).

Általános megoldások

Azzal talán nem fogok újat mondani, hogy van jópár lehetőségünk két különböző nyelven futó program közötti kommunikációra, bár ezek egy része minden bizonnyal fapados. Ez nem jelenti persze azt, hogy ne lenne potenciálisan jó, sőt, kiváló egy ilyen megoldás, hiszen ha például a repülést nézzük, "fapados" járatokkal emberek milliói utaznak elégedetten világszerte, s hazánkban is egyre népszerűbb lesz az ily módon történő közlekedés. Arra azonban figyeljünk, hogy a fapados megoldások bár egyszerűségüknél fogva kiválóak lehetnek, de könnyen átcsaphatnak "gányolásba" is, ha nincsenek megfelelően megtervezve. Mielőtt kiválasztunk egy megoldást, nézzünk körül, hogy milyen lehetőségek vannak!

Közös fájlrendszer - fájlformátumok

Ha egy közös gépen fut a projektünk két része, talán az egyik legegyszerűbb és legkézenfekvőbb megoldás, ha a közöttük zajló kommunikáció a fájlrendszeren keresztül, egyszerű fájlokban folyik. A PHP program létrehoz egy fájlt, a Perl olvassa, illetve a Perl ír egy fájlt, és a PHP annak függvényében tesz valamit. Ez így jól hangzik, de általában a webes programozásnál sem a Perl, sem a PHP programok nem futnak állandóan (jó esetben is csak a Perl programunk fut valamilyen szerverként, a PHP pedig webet szolgál ki), így sok lehetőségünk nincs, ha szinkronizáltan, egymást használva szeretnénk a programjainkat futtatni. Ez persze nem biztos hogy baj, sokszor egy ilyen statikus kommunikáció is elég lehet.

Egy ilyen szituáció akkor fordulhat elő, ha például a szerverre történő levelek beérkezését szeretnénk elkapni, majd feldolgozni, s a weben PHP-vel megjeleníteni az eredményeket. Bár se a levelek feldolgozása, se a megjelenítése ma már nem akadály a PHP-nek sem, de ha nekünk már például megvalósított Perl rutinkönyvtárunk van a feladatra, vagy pedig éppen a CPAN-on levő modulok szimpatikusabbak (van egy jópár), a fájlrendszeren történő kommunikáció is megoldást jelenthet.

Itt alapvetően nincs szükségünk azonnal PHP futásra, nem kell a PHP-nek feldolgoznia semmit sem, így problémamentesen megoldható lehet a két nyelv együttműködése. A kommunikáció történhet valamilyen egyszerű szöveges formátumra építve, vagy a Perlből már régóta, a PHPből pedig az 5.0-s verzió megjelenésével egyre jobban támogatott XML alapú megoldásokat használva. A lényeg, hogy egy olyan formátumot találjunk, melyet a Perlből egyszerűen tudunk írni (illetve ha komplexebb adatokról van szó, akkor olvasni, módosítani), a PHP pedig lehetőséget biztosít az egyszerű feldolgozására.

A szövegfájl egy kitűnő megoldást adhat a problémára. A beérkezett levelet feldolgozzuk, kiolvassuk és a különböző megoldásokkal kódolt adatokból visszanyerjük a feladót, tárgyat, vagy a csatolmányokat, majd ezeket - például levelenként külön-külön - kiírjuk egy szövegfájlba. Minden sor egy bizonyos adatot jelöl, "és kész". A PHP megnézi, milyen fájlok vannak például egy könyvtárban, megnyitja, s megjeleníti azokat. A szövegfájlkezelés, egy szöveges fájl betöltése a legegyszerűbb feladatok közé tartozik. Az egyszerű szövegfájllal egy bökkenő van: nem igaz támogatja az adatformátum bővülését, ha bejön egy új adatmező (pl. kiegészül a szövegfájl egy dátum mezővel), akkor mind a két oldalon módosítani kell. A szövegfájl nem önleíró. Két lehetőségünk van: vagy kitalálunk egy megoldást saját magunk, vagy pedig építünk egy meglévőre, ilyen lehet az XML. Ezek a lehetőségek közül kétségkívül amihez a lehető legtöbb kész megoldást fogjuk találni az az XML lesz.

Az XML egyik tulajdonsága, hogy önleíró, azaz nem csak az adatot tárolja, hanem megmondja azt is, hogy mi az az adat. Az előző példánál maradva, ha bejön egy új mező a forrás oldalon, a célkörnyezet, azaz a program, ami olvassa, nem érzékel ebből semmit sem (ha jól van megírva), egyszerűen figyelmen kívül hagyja ezt a mezőt - nincs gond a különböző formátum változatok közötti különbséggel. Ahogy a céloldalon implementáljuk a dátum formátum megjelenítését, fel tudjuk viszont dolgozni a bejövő adatot. Az XML ezen tulajdonsága akkor is jól jöhet, ha a bemenő formátumok között régebbi, korábbi adatok is vannak, melyekből még hiányzik egy újdonság. Nem lesz szükség (feltétlenül) migrációra, sokkal kisebb a rizikó a fejlesztés közben.

Mindennapi feladat lehet egy naponta lefutó "konzolos" program, mely valamilyen adatokat gyűjt be valahonnan, feldolgozza azokat, és előkészíti valamilyen gyorsan megjeleníthető formátumban. A feladat itt is két részre bontható, az egyik a feldolgozás, a másik pedig az aggregált tartalom webes megjelenítése: a feladat csak egy közös formátum megtalálása, az egyiket a például Perl, a másikat például a PHP tudja kiválóan elvégezni.

Ehhez hasonló, de mégis teljesen más feladat során végül az XML-t hívtam segítségül. A probléma a következő volt: egy cég belső intranetjén futó webes játék (ki mivel, mikor, milyen eredménnyel játszott) adatainak a szinkronizálását kellett megoldani egy külső céggel, akik a játékhoz a supportot kínálták, illetve offline játékok (fényképbeküldés, stb.) eredményeit rögzítették. A webes részét a dolognak Perlben valósítottam meg, a külső cégnél futó program pedig (ismereteim szerint) Visual Basicben lett elkészítve az ő programozójuk által, megjegyzem, én azt a programot sohasem láttam, mivel nem volt rá szükség. A helyzetet nehezítendő, a külső cégnek nem volt állandóan futó gépe, állandó netkapcsolattal, továbbá az intranet (ahol a játék futott) sem volt elérhető (biztonsági okokból) az internet felől. A megoldás: az intraneten futó Perl alkalmazás titkosított kapcsolattal minden éjjel feltölti az adatait egy központi szerverre az interneten, ezt a külső support cégnél futó program reggel letölti, feldolgozza, majd pedig a munkaidő végén feltölti a központi szerverre, ahonnan az intraneten futó Perl alkalmazás le tudja tölteni, s a saját adatbázisával történő összefésülés után újra feltölteni. Az íly módon történő szinkronizálás - bár lehet, hogy elsőre bonyolultnak hangzik - kiválóan működött a teljes játék során.

Az adatok fájlokban történő tárolására nem csak a szövegfájl, s nem csak az XML kínál egyedüli és kizárólagos megoldást. Az XML bizonyos helyeken történő leváltását tűzte ki maga elé a YAML, mely emberek számára jobban olvasható, szerkeszthető megoldást kínál, mint elődje. Használhatunk egy a célnak megfelelően kialakított bináris fájlformátumot is, bár (hacsak nem vagyunk helyszűkében) ez nem biztos hogy célszerű: a szövegfájlok hátrányaiként megismert tulajdonságok ezeknél is felmerülnek. Létezik a szerializáció lehetősége is, mely adatstruktúrákat alakít át valamilyen bináris adatfolyammá, a PHP (és más nyelvek) például ezzel a módszerrel oldja meg a munkamenetekben történő változó tárolást.

Biztos vagyok benne, hogy több olvasóban is felmerült már a kérdés: minek foglalkozunk itt fájlokkal, amikor sokkal hatékonyabb (ez nem egyértelmű!) megoldást is választhatunk, tároljuk egy közös adatbázisban az adatokat! Bár van, amikor egyszerűbb lehet egy közös fájlrendszer használata, a közös adatbázisszerver, főként ha a két program nem egy gépen fut, mégis több előnyt is kínálhat. Az adatbázisban történő tárolásnál, illetve a következőkben bemutatott megoldás esetén az eddigiek során bemutatott adattárolási módszerek nagyrészt használhatóak maradnak - csak a tárolási hely változik, a mód nem feltétlenül.

Közös adatbázis

A közös adatbázis jó megoldás lehet, sőt, sokszor rugalmasabb megoldást kínál, mint a fájlrendszer használata. A programozási nyelvek legtöbbje manapság már kínál adatbáziskapcsolatra lehetőséget, s nem is csak egy adatbázisszerverhez, a legnépszerűbbekhez el szoktak készülni az interfészek. Az előző leveles példát említve: a beérkező leveleket tehetjük egyből az adatbázisba is, így a webes program közvetlenül is elérheti azokat. Milyen előnyökkel járhat ez? Nyilván egy adatbázisból ha az adatokat nem lineárisan szeretnénk lekérdezni, könnyebb dolgunk van, lekérhetjük a teljes listát, egy bizonyos szempont szerint csoportosíthatjuk, rendezhetjük adatainkat, vagy csak lekérhetünk egy konkrét levelet is. Az adatbáziskezelés a tranzakciókezelésre is jó megoldást kínálhat. Nem fordulhat elő, hogy egy szövegfájl írásának még csak a felénél járunk, s a másik program már elkezdené feldolgozni azt, stb. Nem kell nekünk a zárolással foglalkozni (vagy legalábbis nem úgy, ahogy a fájloknál), az atomi műveletek sokkal jobban megoldottak lehetnek.

TCP/IP alapú kommunikáció

Egy korábbi projektem során a feladat egy kereső motor készítése volt. Az adatok indexelését Perl program végezte, a keresés interfészét pedig PHP-ból kellett megvalósítani, úgy, hogy később más nyelvekből is lehetséges legyen. A megoldás egy kereső szerver kialakítása volt, ahol az indexelés mellett a szerver funkciókat is a Perl látta el. Egyszerűen (authentikáció után) TCP/IP-n keresztül, egy socket megnyitásával lehetett hozzá csatlakozni, kérdéseket feltenni, majd pedig lekérni az eredményeket. Az előző adatbázisszerveres megoldáshoz hasonlít a dolog - azzal a különbséggel, hogy itt egy kereső logika is a képbe került, melynek a kapcsolatot biztosító szerver rétegben kellett helyet biztosítani. A TCP/IP alapú kommunikáció nyelvek között akkor tud jól működni, ha valamely nyelv vagy eszköz (akár egy harmadik nyelv) lehetőséget tud teremteni szerverként való működésre, s az adatok megosztására. Bár az adott, konkrét esetben mind a két alkalmazás egy gépen futott, azóta már többszerveres környezetben is kiválóan vizsgázott a megoldás.

Webes kommunikáció

Webes kommunikáció alatt sokmindent érthetünk. Mind az XML-RPC, mind a SOAP, mint a REST protokollok webes felületen, vagy ahhoz hasonló módon használhatóak (mindegyik a HTTP protokollt használja), s egyedi megoldásokat is kialakíthatunk. Összefoglalva: távoli eljáráshívásról van szó mindegyiknél. Létezik egy kliensprogram, s egy szerverprogram, s a kliens egy távolról elérhető eljárást tud meghívni, majd annak eredményét visszakapni. Az XML-RPC és a SOAP a kommunikációhoz XML-t használ, a REST pedig azt mondja, hogy egy lekérdezést, illetve az adatok visszakapását nem kell feltétlenül ennyire elbonyolítani. A konkrét megoldásokat tekintve a web egy jó forrás lehet, kedvenc keresőnkkel keressünk rá a betűszavakra további információkért!

Bármely megoldást is használjuk, az egyik programnak egy webszerveren keresztül elérhetőnek kell lennie a másik számára, vagy pedig magának kell webszerverként is funkcionálnia. Ez, hasonlóan a TCP/IP alapú megoldáshoz, valamilyen szempontból állandóbb működést feltételez, mint az egyébként teljesen különálló megoldások: az egyik félnek folyamatosan és biztosan a másik szolgálatára kell tudnia állnia.

Összefoglalás

A mai cikkben számos megoldást bemutattunk a nyelvfüggetlen kommunikációra, s több - helyszűke miatt - ki is maradt. Ilyenek az operációs rendszertől függő megoldások, melyek szignálokra, eseményekre, vagy más, speciális lehetőségekre építenek (a betűszavakat lehetne sorolni), de más, a bemutatottakhoz hasonló lehetőségek (például nem közös fájlrendszeren, hanem FTP-n keresztül történő adatcsere). Ha valaki ismer valamely további megoldást, ossza meg velünk!

A következő alkalmak során azt fogjuk megvizsgálni, milyen lehetőségeink vannak Perl nyelvből PHP-ben létrejött adatok elérésére, legyenek azok adatbázisban, weben, fájlrendszerben, majd megnézzük ennek fordítottját is, azaz azt, hogy hogyan érhetjük el PHP-ből a Perlben létrejött adatokat. A tervek szerint más nyelvekre is sort kerítünk majd, ez az összegyűlő információk, illetve az általam ismert lehetőségektől függ. Szívesen fogadunk cikkeket, melyben a szerző valamely két nyelv kommunikációját lehetővé tevő kommunikációs lehetőségeket járja körül!
 
Bártházi András arcképe
Bártházi András
Az Emarsys-nál dolgozik vezető fejlesztőként, és az API-ért, integrációkért felelős termékmenedzserként. Szeret profi csapatban profit alkotni.
1

Már régóta vártam egy

tiny · 2005. Május. 1. (V), 09.58
Már régóta vártam egy ilyen cikkre. Amíg nem ismertem az XML-t, sokat keresgélem, hogyan lehetne 2 gép közt adatokat cserélni, de csak korlátozottan. Nem is tudtam más technológiákról, de most legalább van, amin el tudok indulni (keresőszavak :)). Nagyon várom a következő részt, érdekes volt amit eddig olvastam, csak így tovább!
Mr.Tiny
2

Összefoglalás

Bártházi András · 2005. Május. 1. (V), 11.50
Egy kicsit másképp megfogalmazva a cikk mondanivalóját: két nyelv/program közti kommunikáció kapcsán az adatformátumot és a kommunikáció módját kell megfelelően megválasztanunk. Ez utóbbi lehet szinkron, azaz mikor a két program egyszerre fut, s "élő" kapcsolaton keresztül cseréli ki az adatokat, illetve aszinkron, mikor külön-külön futnak le. Nincsen "legjobb" megoldás, ha a legjobb megoldást szeretnénk választani, mindig a helyzetet elemezve dönthetünk.

-boogie-