Monthly Archives: október 2007

SVN: alapok

Az SVN-ről ahogy időm engedi, több bejegyzést is szeretnék majd írni. Most írok egy bevezetőszerűséget arról, hogy mire jó, s megosztok pár trükköt is, amit az utóbbi években sikerült összeszednem vele kapcsolatosan.

SVN - Subversion

Az SVN, hosszabb nevén Subversion egy verziókezelő rendszer. Olyan, mint a CVS. Aki még egyiket sem próbálta, annak mindenképpen érdemes az SVN-t választani, mivel történelmi okokból sokkal bugmentesebb.

A verziókezelő rendszerek lényegét valószínűleg sokféleképpen el lehet mesélni. A legegyszerűbb egy olyan háttértárként felfogni ezeket, mint egy átlag bármilyen FTP, amely emlékezik a rá másolt fájlok korábbi állapotára is. Egy SVN tárhelyet “repository”-nak, egy vagy több fájl rendszerbe tételét “commit”-nak, a rendszerben levő fájlok lekérését pedig “checkout”-nak hívjuk. Minden commit után a rendszer egy új számot rendel a fájlok aktuális állapotához (egy commit után simán nő egyet ez a szám), amit “revision”-nek nevezünk. A commitokhoz egy rövid szöveges leírást lehet és érdemes rendelni, így később megtalálhatóak az egyes változtatások (pl. “hozzáadtam az xyz-t”, “töröltem xzy-t mert elavult volt”, “elgépelés javítása”, stb.). Az egyes állapotokra ezután ezekkel a számokkal lehet hivatkozni: “a 1129-es revisionban”, “a 231-es commitod után bedöglött a rendszer”, “visszaáltam a 42-es revisionre”, stb. Azt a műveletet, amikor kikérjük a rendszerből az aktuális legfrissebb állapotot (miután mások változtattak valamit), egyszerűen “update”-nek hívjuk.

A verziókezelő rendszereket csoportmunkára találták ki, de sokmindenre használhatóak. Érdemes lehet akkor is használni, ha egyedül dolgozunk fájlokon, mivel backupolásra is jól használható. Ha például a Dokumentumok mappát minden nap végén commitoljuk, akkor az egyes szerződések korábbi állapotához is hozzá tudunk férni, illetve ha elveszik az egész mappa, és a verziókezelő rendszerünk egy másik gépen van, könnyedén visszaállíthatunk mindent.

A klasszikus verziókezelő alkalmazás mindazonáltal forráskódok tárolása. A fejlesztéshez sok kényelmi lehetőséget biztosít, kezdve azzal, hogy ha valaki ugyanazon fájl különböző soraihoz nyúl, akkor lehetőséget biztosít összefésülésre: “merge”. A commitok “atomiak”, azaz nem fordulhat elő olyan, hogy két vagy több fejlesztő egyszerre commitol valamit, és felülírják egymás változásait. Valaki előbb fog commitolni, és a rendszer jelzi, hogy nem volt friss a helyi változata a fájlnak, előbb egy update-et kell lefuttatni. Az update során ha a rendszer el tudja intézni, akkor összefésülésre kerülnek a fájlok, és nekünk csak annyi dolgunk lesz, hogy becommitoljuk azokat. Ha ugyanazokon a sorokon történt a változtatás, akkor az automatikus összefésülés nem fog sikerülni, de kapunk négy fájlt, egy olyat, amiben jelölve vannak a helyi és a másik commitoló(k) által végzett változtatások, továbbá megkapjuk a verziókezelő legfrissebb fájlát, azt a változatot amit legutoljára kiszedtünk a rendszerből és a mi fájlunk is megmarad. Ez egy nagyon kényelmes szolgáltatás.

A verziókezelőből sok információt ki lehet nyerni, amellett hogy az egyes régebbi változatokhoz is hozzáférünk, ha valamit nagyon elrontottunk, vagy csak meg akarunk nézni egy régebbi változatot. Például le tudjuk kérdezni, hogy egy adott fájlhoz ki nyúlt utoljára, vagy hogy mi az adott fájl története, “history”-ja. Az adott állapotok közötti változások lekérhetőek, akár az egész rendszert, akár egy adott fájlt illetően.

A modern verziókezelők egyik lehetősége, és emiatt például érdemes az SVN-t választani az átláthatósága miatt, a commitok előtt és után lefuttatható scriptek lehetősége. A Weblabor fejlesztése a kezdetekben úgy zajlott például, hogy commit után az SVN csinált egy update-et a webszerveren, odamásolva a legfrissebb változásokat (alapból volt ott egy checkout, amit csak frissítenie kellett). Ez megoldotta az FTP-s szívásokat, amikor felülírtuk egymás változásait. A jelenlegi rendszer ezen is túlmegy, van egy fejlesztői URL, ahol a friss fejlesztések megjelennek, tesztelhetőek, és egy “piros gomb”, amit megnyomva a legfrissebb változatra frissíteni lehet az éles rendszert is. Érdemes lehet egy undo gombot is bevezetni, amivel vissza lehet állni a korábbi verziók bármelyikére, de erre a Weblabor esetén nem volt szükségünk, nagy változtatásokat ritkán csináltunk. Ezt a folyamatot nevezem “automatikus deploy” folyamatnak. Elég jól bevált a dolog.

Egy másik “deploy” folyamatot raktunk össze az egyik korábbi munkahelyemen, ahol például az volt a különbség, hogy sokkal biztosabban kellett működnie a rendszernek, és több éles szerver is volt (terheléselosztás kapcsán). A lényeg itt annyi, hogy több szerveren kell lefuttatni az update parancsot az éles rendszer frissítésekor, és ezt érdemes lehet egy kis scripttel elvégeztetni. A script belép a különböző szerverekre, lefuttatja mindenhol az update-et, és dolga végeztével szól, hogy készen van. Ilyen környezetekre egyébként kiváló eszköz lehet a Capistrano, melyet a Ruby on Rails-hez terveztek, de általánosan is kényelmesen használható. Most tanulgatom saját weblapom kapcsán.

Még egy trükk amit az SVN segítségével meg lehet oldani – azt automatizált minőségbiztosítás. Ha a projekt során különböző követelmények vannak például a forrásfájl formázását illetően, akkor a commit folyamatba beiktathatunk egy scriptet, ami leellenőrzi, valóban dupla szóközt használtunk-e tabulálásra (esetleg kijavít minket), nincs-e az adott forrásban syntax error. Lehet olyan scriptet írni, ami (pl. C-s fejlesztés esetén) csinál egy builded, s ha hibát talál a build során, akkor megakadályozza a beküldést, vagy a frissen beküldött forráson lefuttat előre elkészített teszteket, és küld egy emailt a teszteredményekkel. Vagy egy kis script segítségével az is megakadályozható, hogy megjegyzés nélkül küldjünk be egy commitet. A Weblabornál egy olyan scriptet raktam össze, mely a változtatásokról küld egy emailt az összes szerkesztőnek – lehet látni, hogy ha valaki dolgozik valamin, illetve hogy pontosan miket csinál. Több szem többet lát alapon könnyű kiszúrni más változtatásaiban a kis hibákat, és akár korrigálni is azokat (van erre egy jobb megoldás felkiáltással).

Végül, de nem utolsó sorban, a hibajegykezeléssel is össze lehet drótozni egy verziókezelő rendszert. Az egyik projektemben ha “fixes #1234″ üzenettel küldünk be egy változtatást, akkor a rendszer lezárja az adott hibajegyet a beküldő nevében, majd küld egy értesítést a tesztelő csapatnak, hogy ki lehet próbálni a változtatást. Iszonyat kényelmes. :)

Ha valaki használ SVN scriptelést, kiváncsi lennék rá, hogy mire lehetnek jók még a gyakorlatban ezek a kis scriptek.

Mozilla Prism

A webes alkalmazások és az asztali alkalmazások lassan, de biztosan közelednek egymáshoz. Míg az utóbbi években a levelezőprogramtól a hírolvasóig minden felköltözött a webre, most elkezdtek a webes alkalmazások visszaköltözni, legalább részben. A fejlesztőkörnyezetek készülnek, az egyik ilyen lehetőség az Adobe Air, míg egy újabb a Mozilla által készített WebRunner. Ezt nevezte át most a Mozilla, az új neve lett a Mozilla Prism.

Mozilla Prism (Google Calendar)

A Mozilla Prism és az Adobe Air filozófiájukban hasonlóak, bár míg az Air inkább helyben levő, és az infókat jellemzően a webről szedő alkalmazásfilozófiát jelent, addig a Mozilla Prism a webalkalmazások, weblapok asztali alkalmazásokká alakítását segíti elő. Ez utóbbival könnyebb is a helyzet egy kicsit, “simán” megadhatjuk a webalkalmazás URL-jét, és ebből egy alkalmazást tud létrehozni. További információkért lásd a weblapokat, jobban leírják, mint én.

A Mozilla Prism-et egyelőre egy kicsit butának gondolom, bár konkrét webalkamazásokat ezzel lehet a legkönnyebben átalakítani. Az Adobe Air-t inkább asztali alkalmazások készítésére használhatják azok, akik platformfüggetlen programokat szeretnének készíteni, és jobban preferálják a HTML+CSS+Flash+Flex platformot.

A gyorsabb weblapért

Részben egyik Netvibes-os kollegám (elég régi) írását szeretném ajánlani, részben pedig egy kicsit elmélkedni arról, hogy vajon mivel is tehetjük gyorsabbá oldalunk betöltődését. Azt tudjuk, hogy az oldal betöltődése fontos szempont ahhoz, hogy a látogatóink ne lépjenek le rögtön, de fontos áttekinteni a szempontokat is, melyek mentén érdemes optimalizálni.

Két mindenekelőtt: egyrészt nem biztos, hogy minden oldalt optimalizálni kell. Ez nem azt jelenti, hogy nyugodtan tegyünk ki egy 1GB-os PNG képet háttérnek, mert az fasza, hanem azt, hogy általában jól felépített oldalon, normál nagyságú képekkel, szervezéssel nem kell tovább mennünk, és szétoptimalizálni az oldalt. Optimalizálni főként híroldalakat, webalkalmazásokat, stb. kell, amit sokan látogatnak, és ahol a látogatók nem a két szép szemünkért jönnek, és nem hajlandóak kivárni 10 másodpercet.

A másik mindenekelőtt: két része van az optimalizációnak. Az egyik a weblap első betöltődése, a másik pedig a weblap ezutáni betöltődése. A két optimalizáció között a határt a böngésző, illetve a közbeiktatott különböző proxy-k gyorsítótárazása húzza meg.

Vegyük az első oldalbetöltődést. A legfontosabb szempont, hogy minél kisebb adatmennyiséget kelljen a böngészőnek letöltenie, és minél kevesebb fájlt. Nem véletlenül divat a minél kevesebb grafikai elemet tartalmazó, puritán oldal – ugyanis nem csak jobban átlátható lehet valószínűleg egy így felépített design, de jóval gyorsabban is töltődik be. Sokáig a divatnak tudták be a táblázatos oldalszerkezet mellőzését is, azonban a számos érv közül az egyik, hogy a CSS-sel felépített oldalszerkezetet gyorsabban kezdi el megjeleníteni a böngésző. További fontos tipp, hogy a grafikai elemeket, avagy a kis ikonjainkat, grafikus gombok, menük több állapotát a lehetőségek szerint vonjuk össze, és pakoljuk minél kevesebb képbe. Nem csak azt érjük el így, hogy nem kell különböző trükkökkel előtölteni a hover állapotokat, de a kis ikonok egyszerre jelennek meg, a gombok hoverje nem fog villogni, amikor betöltődik a második képe. Fontos az is, hogy a képek összevonása nem csak a szerver felé indított kérések számát csökkenti, de jellemzően az összméretet is.

Az optimalizálás második feladata a különböző cache-ek minél jobb kihasználása. Ennek érdekében a JavaScript és CSS kódjainkat minden esetben különítsük el a HTML-től. Ha a szerver felépítésünk engedi, ezeket külön szerverre is tehetjük, így a böngészők “egyszerre két fájlt töltünk le max. egy szerverről” limitjét is ki tudjuk játszani. Arra figyeljünk, hogy a JavaScriptek domainjét az egyes böngészők különbözőképpen kezelik le, és előfordulhat, hogy az AJAX-os adatlekéréseket blokkolják a domain korlátok miatt.

A JavaScript és CSS fájlokat nem árt tömöríteni sem. A méretcsökkentés kapcsán három dolog jöhet szóba. JavaScriptnél “valódi” tömörítést tudunk elérni úgy, hogy egy JavaScript csomagolót, kicsomagolót használunk, mely az oldal betöltődésekor kicsomagolja, majd eval-lal értelmezi a kicsomagolt JavaScriptet. Egész jó méretcsökkenéseket lehet ezzel elérni, de ne csodálkozzunk, ha az oldalletöltésünk ideje ezzel nem csökken, hanem nő, ugyanis a kicsomagolás szignifikáns időbe is telhet, közben jól leterhelve a böngészőt. Másik tömörítési mód, hogy a felesleges részeket eltávolítjuk a kódokból, értem ezalatt a white space-eket, a megjegyzéseket. CSS esetén összevonásokkal, “white” helyett “#fff” használatával, pontosvesszők elhagyásával is lehet mahinálni. Ezeket sohase csináljuk kézzel, használjunk valamilyen automatizált megoldást. Végül, de nem utolsó sorban, a szerveren kapcsoljuk be a gzip tömörítést. Minden modern böngésző támogatja, de a szerver képes azt is észlelni, ha egy böngésző nem támogatná. Emlékeim szerint egyedül az Internet Explorer 6.0 előtti verzióival volt gond anno, de ezekre még véletlenül se optimalizáljunk ma (értsd: legrosszabba esetben is minimum ötszörös díjért hangos ellenkezések után). A képet kisebbé tételére is vannak jó programok, igyekezzünk értelmes méretekre csökkenteni a képeket úgy, hogy a látható minőségük még nem romlik.

Fontos lehet azt is látni, hogy vannak olyan trükkök, melyek bizony pénzbe kerülnek. Egy különálló statikus tartalmakra optimalizált szerver, egy a Föld különböző szervertermeibe telepített elosztott kiszolgálóhálózat nem az olcsó megoldások sajátja. A kezdeti lépéseket ettől függetlenül megtehetjük, az általam írtak ugyanis csak egy kis időbe kerülnek.

Jó barátunk a Firebug, mely segítségével sokmindent ki tudunk deríteni az oldalról, az optimalizálás kapcsán azt, hogy mi mennyi idő alatt töltődik le, de lehet vele JavaScript teljesítményt is mérni, optimalizálni. Azt ne feledjük, hogy a JavaScript sebesség elég eltérő lehet különböző böngészőkben, és JavaScriptet intenzíven használó oldal esetén IE6, IE7 alatt gyakran ellenőrizzük a sebességet, működést (különben sohasem találjuk meg az egyes hibákat).

Végezetül megint ajánlani szeretném Alex kollegám a bevezetőben említett írását, nálam részletesebben és mélyebben is kifejtett egyes témákat.

MySQL akadémia

A MySQL (mint cég) elég jó anyagokat tett közzé eddig is a neten, például a MySQL dokumentációt egy igen jó (bár sajnos néhol hiányos) olvasnivalónak gondolom, de ezen kívül is jó dolgokat lehet találni, ha körbenéz az ember. Most egy MySQL University nevű sorozatot indítottak útjára, mely gyakorlatilag egy online előadássorozatot jelent.

Az előadások minden héten csütörtökön, magyar idő szerint délután 3-kor vannak, és 1-2 órásak. Hangot sugároznak, a hallgatók IRC-n tudnak aktívan résztvenni az előadások alakításában. A sorozat már márciusban elindult, de nem maradt le senki semmiről, ugyanis minden előadás utólag is hozzáférhető a weblapon.

Widgetek, JavaScript, UWA, stb.

A Twitteren/Turulcsiripen kezdtünk el Német Ádámmal beszélgetni a widgetekről, a Netvibes ezirányú általánosnak megcélzott UWA keretrendszeréről, és arról, hogy a JavaScript-e a megoldás erre a kérdésre. Talán itt folytatjuk. :)

A widgetek különböző platformokon futó kis mini alkalmazások – talán ez a legegyszerűbb definíció. Widgetek vannak a Netvibes, az iGoogle oldalain, a Mac OS X DashBoardjában, a Vista SideBarjában, a WordPress oldalsávjában, az Adobe Air letölthető alkalmazásaiban (részben), de a mobiltelefonokon, sőt, lassan már az ébresztőórában is. Az egyik jellemző példawidget az időjárásról szóló doboz, de a twitter klienstől a videókeresőig kb. mindent bele lehet paszírozni egy dobozkába. A Netvibes egy olyan általános, XML alapú leírónyelvet fejlesztett ki, mely képes számos platformon futni – egyszer kell megírni a kódot, és a legtöbb helyen működni fog anélkül, hogy akár ismernénk az adott platformot.

A widgetek alapját én a JavaScriptben képzelem el, szerintem a JavaScript egy olyan közös nevező, mely egy könnyen tanulható programozási nyelvet biztosíthat a widgetekhez, vagy bármi máshoz. Nem véletlenül szinte kivétel nélkül ez az előbb felsorolt platformok programozási nyelve is. A widgetek megjelenését pedig – legfőképpen a Netvibes UWA megoldásában – nagyrészt HTML-lel írhatjuk le, a legtöbb platform szintén ezt támogatja, mint könnyen tanulható általános megoldást.

Beszélgessünk erről a kérdésről!

Web.Miner.hu

Talán a legtöbben most a http://web.miner.hu/-n keresztül juttok el hozzám, de akkor is úgy gondolom, hogy a potenciális célközönségből viszonylag kevesen ismerik az oldalt, így egy kicsit promózom.

A Web.Miner.hu egy a Miner.hu (blog)kereső motorjára épülő aggregátor, magyarán szólva különböző webfejlesztésről, webkettőről és kapcsolódó témákról író blogok bejegyzéseit gyűjti össze. Jelenleg 20 feletti a blogok száma (bár nem mindegyik aktív), egyes blogoknál az összes, míg más blogoknál pedig egy adott kategória bejegyzését gyűjtjük. A gyűjteménybe bárki bekerülhet, aki jó színvonalon ír csak a fent jelzett témákban, vagy pedig tud olyan RSS-t biztosítani, mely a fenti témákra szűkít. Jelentkezni az oldalon jelzett címen lehet. Aki RSS-en keresztül szeretné olvasni az aggregátor bejegyzéseit, az pedig a http://web.miner.hu/rss címen iratkozhat fel.

Az aggregátornak vannak testvérei is, a http://marketing.miner.hu/, http://gasztro.miner.hu, http://foto.miner.hu/ és http://orvos.miner.hu/ címeken. Jó olvasgatást!

MySQL telepítése 7 másodperc alatt

Az automatizmusok, avagy néhány ügyes script nagyon sokat segíthetnek egy rendszergazda munkáját illetően (is). David Axmark, a MySQL egyik alapítója mondta az egyik vele készült interjú során, hogy az egyik háziszabályként azt tűzték ki, negyed órával a letöltés után már működőképes állapotban is lehessen a szerver. Egyszerű konfigurációt és gyors telepítőt készítettek – s mint a legnépszerűbb ingyenes adatbázisszerver, úgy tűnik jól tették dolgukat. Most egy olyan blogbejegyzéssel találkoztam, ami pár a telepítést megkönnyítő scriptet mutat be: Introducing the 15 seconds rule. Érdemes megnézni, és elgondolkodni azon, hogy mivel és mennyit tököl el feleslegesen az ember, ami kiváltható lenne pár scripttel.

A “block” és “inline” elemekről

A HTML nyelv két elemtípus kategóriát definiál a legtöbb elem számára, a “block”-ot és az “inline”-t. Például “block” típusú egy bekezdés, egy címsor, míg inline típusú egy link, egy kép. Ezek azok az információk, melyet elvileg mindenki tud, azonban azt már kevésbé, hogy például milyen típusú egy táblázat, felsorolás – és hogy pontosan mit is jelentenek ezek a kategóriák. Nézzük végig!

A “block” kategóriába tartozó elemek jellemzően más “block” és “inline” elemeket tartalmaznak, tartalmazhatnak, és vizuális megjelenítésükkor jellemzően egy új sorban kezdődnek. Az “inline” kategóriába tartozó elemek csak és kizárólag “inline” elemeket tartalmazhatnak. A kiemelések nem véletlenek, és nagyon fontosak, több okból is.

Kezdjük azzal, hogy a HTML egy szerkezetet leíró, és nem egy megjelenést meghatározó nyelv. Ez sokmindent jelent, esetünkben azt, hogy egy “block” elem csak jellemzően jelenik meg úgy, hogy új sorban kezdődik, ezek a kategóriák ugyanis nem a megjelenésről szólnak. A legegyszerűbb ellenpélda az, amikor egy linket style=”display: block” CSS stílussal blokk megjelenésűre állítunk. Azonban ettől még a link nem lesz “block” kategóriájú elem, és ez semmiképpen sem fogja befolyásolni a HTML forrásban elfoglalt szerepét! Ezt nagyon fontos megérteni, mert sok szívástól menthet meg minket.

Másik fontos gondolat, hogy minden “block” elem esetében definiált, hogy tartalmazhat-e más “block” típusú elemet, vagy nem, még konkrétabban pontosan definiált, hogy mely elemeket tartalmazhat (jellemzően három kategória van: csak “block” elemet tartalmazhat, csak “inline” elemet tartalmazhat, mindkettőt tartalmazhatja). Például a bekezdést jelölő P elem nem tartalmazhat másik “block” elemet, így táblázatot, felsorolást, címsort, HR-t, FORM-ot sem. Tudtad?

Itt jelezném, hogy azt illetően, hogy egy elem pontosan milyen elemeket tartalmazhat, a HTML 4-en belül is létezik a “Transitional” és a “Strict” mód. Én az utóbbit preferálom, mivel jóval könnyebben felfedezhetőek a hibák, elgépelések, illetve ebben az üzemmódban sokkal szabványosabban is működik a böngésző. A “block” és “inline” elemek megítélését tekintve nincs különbség.

Nézzük, mely elemek “block” típusúak:

  • ADDRESS – cím
  • BLOCKQUOTE – blokkos idézet
  • DIV – általános “block” elem
  • DL – definíciós lista
  • FIELDSET – kérdőívek mezőit csoportosítja
  • FORM – kérdőív elem
  • H1, H2, H3, H4, H5, H6 – Különböző szintű címsor elemek
  • HR – Elválasztó elem
  • NOFRAMES – Alternatív tartalom, ha a böngésző nem támogatná a frame-eket
  • NOSCRIPT – Alternatív tartalom, ha a böngésző nem támogatná a script-eket
  • OL – Rendezett (számozott) lista
  • P – Bekezdés
  • PRE – Formázott szöveg
  • TABLE – Táblázat
  • UL – Rendezetlen lista (egyszerű felsorolás)
  • DD – Meghatározás leírója
  • DT – Meghatározás címe
  • FRAMESET – Keret befoglaló elem
  • LI – Lista elem
  • THEAD – Táblázat fejlécét jelölő elem
  • TBODY – Táblázat tartalmi részét jelölő elem
  • TFOOT – Táblázat láblécét jelölő elem
  • TD – Táblázatcella adatok számára
  • TH – Táblázatcella címek számára
  • TR – Táblázat sor

Pár egzotikus elemet kihagytam, de ezek a legfontosabbak.

Nézzük meg az “inline” elemeket is. Róluk azt kell tudni, hogy “block” elemeket semmiképpen nem tartalmazhatnak, másik “inline” elemet pedig a definíciójuk szerint igen. Íme a lista:

  • A – Link (főként)
  • ABBR – Rövidítés
  • ACRONYM – Betűszó
  • B – Vastag szöveg (ne használjuk, helyette STRONG)
  • BR – Sotörés
  • CITE – Idézet
  • CODE – Számítógépes kód
  • DFN – Definíciós kifejezés
  • EM – Hangsúlyozás
  • I – Dőlt szöveg (ne használjuk, helyette EM)
  • IMG – Kép
  • INPUT – Kérdőív beviteli mezője
  • KBD – Begépelhető szöveg
  • LABEL – Kérdőívelem címkéje
  • Q – Rövid idézet
  • S – Áthúzás (ne használjuk, helyett DEL)
  • SAMP – Példa kimeneti szöveg (amit program ír ki)
  • SELECT – Kérdőív választó eleme
  • SPAN – Általános “inline” elem
  • STRIKE – Áthúzás (ne használjuk, helyett DEL)
  • STRONG – Hangsúlyos kiemelés
  • SUB – Felső index
  • SUP – Alsó index
  • TEXTAREA – Több soros szövegmező
  • TT – Írógépelt szöveg
  • U – Aláhúzott szöveg (ne használjuk)
  • VAR – Változó

Végül vannak kaméleon elemek is, melyek “block” elemeken belül “inline” elemként kezelendőek, amúgy pedig maguk is “block” elemek:

  • APPLET – Java applet (kihalt)
  • BUTTON – Gomb (használjuk)
  • DEL – Törölt szöveg
  • IFRAME – Beágyazott keret
  • INS – Beszúrt szöveg
  • OBJECT – Beágyazott speciális objektum
  • SCRIPT – Kliens oldali kód

A teljes HTML definíciót nem fogom ide másolni, de nézzünk pár érdekességet, melyeket nem árt tudni.

Talán a legfontosabb: ha megszegjük ezeket a szabályokat, akkor a böngésző megpróbálhatja a hibát korrigálni (böngészőfüggő). Egy paragrafusba (P elem) helyezett lista (mondjuk UL) elem esetén az kikerül a paragrafusból, és az eredetileg egy paragrafusból P-UL-P hármas lesz a megjelenítés során. Lehet, hogy ezt senki sem fogja észrevenni, és minden úgy jelenik meg, ahogyan szeretnénk, de ilyenkor – értelemszerűen egy p ul li { … } nem fog működni, mivel a HTML kód értelmezése után az UL elem nem a P elemen belül lesz.

A helyes HTML kód egy felsorolást, táblázatokat tartalmazó oldal esetén az tehát, hogy a paragrafus elemeken kívülre helyezzük a felsorolás elem külső elemét (UL, OL), a táblázat befoglaló elemét (TABLE), az idézeteket (BLOCKQUOTE), a formokat (FORM), ésatöbbi. Ekkor gondolkodik el az ember azon, hogy csakazértis megkerüli a dolgot, és paragrafus elemek helyett akkor majd használ DIV-eket. Sokszor tettem ilyet én is, de nem tartom szép megoldásnak.

Azt megtudtuk, hogy a táblázatoknak paragrafuson kívül van a helyük, de azt még nem, hogy a táblázatok celláiban lehet-e paragrafus, felsorolás, vagy bármilyen más block elem. Lehet. A TD és TH elemek tartalmazhatnak más “block” elemeket, de lehet beléjük egyből “inline” elemeket is elhelyezni.

A következő kérdés, ami felmerülhet az emberben, hogy mi a helyzet a képekkel, hova kell őket tenni? A szabvány szerint egy kép (“inline” elem) lehet mind “block”, mind pedig “inline” elemen belül. Ez első ránézésre azt jelenti, hogy édesmindegy, hogy hova tesszük a képeket. Azonban ha megnézzük, hogy a BODY elem tartalmazhat-e képet, akkor azt fogjuk látni, hogy nem. Ennek értelmében egy képet inkább egy paragrafus, felsorolás vagy hasonló “block” típusú elemen belülre célszerű elhelyezni. Ide egy távolabbra vivő gondolatmorzsa: az IMG elemet mindenképpen a szöveges tartalom részeként kezeljük! IMG elemet ne használjunk díszítő elemként, logóként, hanem illusztációként szolgáljon, egy szövegfolyamon belül. Erre van. A miértet itt most nem részletezném.

Maradva a képeknél, egy jó gyakorlat nekik valamilyen általános osztályt definiálni (class-t), mely azt szabályozza, hogy balra, vagy jobbra legyenek illesztve a szövegfolyamon belül (jellemzően class=”left”, class=”right”). A CSS-ből értelemszerűen pedig bal és jobb oldali margókat definiálni, attól függően, hogy melyik oldalra van éppen az adott kép illeszve a float-tal. Ezt sokan is használják így. Akkor kell elgondolkodni, főként a fentiek függvényében, amikor a megrendelő szeretne képaláírást is. Az első gondolata ilyenkor az embernek, hogy akkor nekünk most egy képdobozra van szükségünk, használjunk tehát egy DIV elemet a kép körül, és annak adjuk meg a “left” és “right” class-okat. Azonban paragrafus elem nem tartalmazhat DIV elemeket! Tovább bonyolítva a kérdést, mi a helyzet akkor, ha a megrendelő egy paragrafuson belülre szövegdobozt szeretne? Paragrafuson belüle mint tudjuk, nem lehet másik P, BLOCKQUOTE vagy hasonló elem.

Két használható megoldást ismerek.

A kép esetében az egyik megoldás – ha a paragrafushoz kapcsolódónak érezzük a képet -, hogy SPAN elembe tesszük a hozzá tartozó képaláírással együtt, majd a SPAN elemet float-oljuk. Ugyanezt tehetjük a szövegdobozzal is – ha egy idézetről beszélünk, akkor tegyük egy Q elembe, és floatolhatjuk bátran. Ez utóbbi esetben viszont nem állhat több paragrafusból a szövegdoboz. A BR-t mint megoldást, vagy paragrafust jelölő SPAN elemeket felejtsük el.

A másik megoldás, mely képek esetében inkább valamilyen nem egy paragrafushoz, hanem általános kép beszúrására, szövegdoboz esetén pedig hosszabb, kiegészítő, akár több bekezdésből álló szöveg beszúrására alkalmas, hogy ezeket a tartalmakat a paragrafuson kívülre helyezzük – ahogy azt maga a szabvány is sugallja. Ha egy bekezdés elejére szeretnénk egy szövegdobozt, képet elhelyezni, akkor tegyük a dobozt/képet a bekezdés elé, és egyszereűen float-oljuk.

Még egy problémás HTML használatot emelnék ki, mégpedig azt, amikor egy UL elembe tesz valaki UL elemet. A HTML elem szerint több szintű listánál az LI elembe kell helyeznünk egy az az alá az elem alá tartozó további szintet. Egy ilyen szabványos többszintű listát mondjuk nem triviális feladat programból előállítani, de szintén csak bonyodalmaink lehetnek a böngészők automatikus korrekciója miatt, ha szépen szeretnénk formázni az ilyen listákat.

Ne vigyük túlzásba a DIV elemeket és olvasgassuk a szabványt (ez egy kivonatos változata) – érdemes.

Iframe magasságának “automatikus” állítása

Amikor egy iframe objektumot az oldalba ágyazunk, gyakran merül fel igényként hogy az iframe-be töltött oldal magasságának függvényében az iframe dobozának magassága is változzon. Ez azonban biztonsági okokból nem lehetséges – tartja a hit. Ez azonban nem teljesen van így, megoldható ugyanis a dolog. Olyan – vagy hasonló – viszont nincs, hogy <iframe height=”auto” src=”"/>

Mindenekelőtt, a biztonsági probléma csak akkor merül fel, ha nem ugyanazon domainről került a másik oldal beágyazásra, mint a beágyazó oldal. Persze ez legtöbbször fennáll.

Egy iframe elem az oldalba helyezésekor valójában egy másik böngésző ablakot helyezünk el arra a pontjára az oldalnak – legalábbis régebben a böngészők így oldották meg a dolgot, és a viselkedés azóta nem is változott. Biztonsági szempontból ha két különböző domainen van a két oldal, azok nem tudnak hozzáférni egymás elemeihez, így a szülő nem tudja lekérdezni azt sem, hogy mekkora a beágyazott oldal magassága. Ha ezt megtehetné, lehet, hogy egyéb érzékeny adathoz is hozzáférhetne, sőt, extrém körülmények között maga az oldal magassága is érzékeny adat lehet. Van azonban egy trükk, amivel mégis meg lehet oldani a kommunikációt, ráadásul biztonságosan.

A trükk egy másik iframe, esetleg egy kép. A konkrét megoldást az iframe-en keresztül magyarázom el, a képes és egyéb megoldás házi feladat. A beágyazott iframe-be húzzunk be egy másik iframe-et, a szülő oldalról. Így most már három oldalunk van, a legkülső, az iframe-et beágyazó, a középső, aminek a magasságát meg szeretnénk tudni, és a legbelső, amit a középső töltött be. Mivel a legkülső és legbelső oldalak azonos domainen vannak, tudnak kommunikálni egymással, és el tudják érni egymás adatait. Tehát ha megoldjuk, hogy a középső oldal/iframe átadja a benne levő oldal magasságát a legbelső oldalnak, egy ott levő JavaScript már tudja módosítani a beágyazott iframe magasságát eszerint. Persze a középső és legbelső oldalak, a két iframe sem egy domainen van, azonban a középső oldal többféleképpen át tud azért adni a legbelsőnek információkat, vagy annak URL-jén keresztül GET, vagy elküldve egy formot POST, vagy pedig az URL-ben található hash (#) rész segítségével. A belső oldalban lehet egy kis JavaScript, ami átveszi ezt az információt (GET és POST esetén generálhatjuk a JavaScriptet, GET-es és hash-es kommunikáció esetén az oldal maga lehet ugyanaz a kód, de limitáltabb az átvihető adattartalom), és átadja azt a legkülső oldalnak, akár közvetve beállítva az ott található iframe magasságát, akár meghívva egy függvényt onnan.

Egyszerű? Talán sem megérteni, sem elsőnek kivitelezni, azoban ha végiggondoljuk, nem olyan nagyon ördöngős a megoldás. Más megoldás nem nagyon ismert, lehet még a háttérszínekkel játszani, hogy ne tűnjön fel, hogy meddig tart az iframe, s elég nagy magasságúra beállítani. Ha valakinek van egyéb trükkje, azért kiváncsi lennék rá. :)

Lábjegyzetként érdemes lehet megjegyezni, hogy ennek a biztonsági megoldásnak köszönhető, hogy például a Netvibes biztonságosan képes futtatni UWA kódokat, mivel azok nem tudnak a felhasználó egyéb beállításaihoz semmilyen módon hozzáférni, ha nem az eredeti, hanem egy nem netvibes.com domainről lettek behívva. Más hasonló oldalak is használják ezt a trükköt a biztonság érdekében.

MySQL Proxy

Kicsit hezitáltam, hogy mivel álljak neki a blog lényegi részének, aztán úgy gondoltam, hogy belecsapok a lecsóba, aztán majd megtalálom a hangot. Az egyik dolog, ami mostanában eléggé foglalkoztat, bár a kipróbálás részét egyelőre még halogatom, az a MySQL Proxy. Röviden összefoglalva a lényegét, nem másról van szó, mint a konkrét MySQL szerver előtt egy a kérdéseket és válaszokat feldolgozni, átalakítani képes csodaeszközről.

A Weblaboron egy blogbejegyzésben (Újdonságok a MySQL háza táján) már kifejtettem, hogy körülbelül miket tud, ezek alapján gondolkodom, hogy a napi eszköztáramban vajon mire lehetne használni. Egy elvileg könnyen tanulható scriptnyelvvel, a Lua-val programozható. Az ottani listán az alábbiakban végigmegyek, de előtte pár általános gondolat megfogalmazható.

Egy új szint

A MySQL Proxy valójában nem más, mint egy új szint/layer bevezetése. Ezt a layert egy jól felépített keretrendszerrel, vagy okos tárolt eljárásokkal, triggerekkel körülbelül most is fel tudja építeni bármely webprogramozó. Vannak azonban esetek, amikor egy jól programozható layer egy kényelmesebb, ügyesebb megoldást kínálhat. Ilyen lehet, amikor nem a programozó, hanem egy db admin próbálja meg az adatbázis viselkedését, a program működését monitorozni, vagy a programozók felé valamilyen extrább lehetőséget kínálni. Ha maga az alkalmazás a Proxy jelenlétére épít, az a hordozhatóságot csökkenti, de ez akár előny is lehet, hogy valamilyen szinten kötni szeretnénk a programozót, vagy a programot a mi platformunkhoz. Lehet kiegészítés szerű funkciókat is a MySQL-hez adni, ami egy nagyvállalati környezetben kényelmes lehet, hiszen független attól, hogy valaki PHP-ből, Java-ból, Perl-ből, .Net-ből éri-e el az adatbázisunkat.

Nézzük azonban a konkrétan felsorolt lehetőségeket, és az azokkal kapcsolatos gondolataimat.

Logolás

A MySQL Proxy logolni képes a teljes forgalmat, vagy annak csak egy programból meghatározott részét. Néhány alkalmazásomnál jó lenne látni, hogy honnan, milyen kéréseket teljesít, és azokat mennyi idő alatt hajtja végre – lehet, hogy elég szépen tudnám optimalizálni a lekérdezéseket ezzel. Ezt a MySQL csak nehézkesen támogatja alapból. Persze ezt elvileg önmagában a (PHP, Perl) alkalmazásban is meg tudnám valósítani, de ha vegyes a környezet, akkor jóval egyszerűbb lehet a MySQL Proxy segítségével (és hát vegyes). Esetleg a triviális, vagy cache-elhető lekérdezéseket egyből le tudná kezelni a Proxy is konkrét lekérdezések nélkül, ami azért javíthat a teljesítményen…

Elgépelések javítása

Ez az egyik dolog, aminek nem látom értelmét mint indok a MySQL Proxy mellett (MySQL Proxy segítségével lehet ugye olyan megoldást szülni, hogy az adatbázisnak egy “SLECT” se okozzon gondot, korrigálja azt “SELECT”-re). Sőt, néhány cikk ezzel is demózza a lehetőségeket. Míg egy ilyen demóból tényleg jól tanulható lehet az, hogy hogyan kell programozni a Proxy-t, addig nem hiszem el, hogy ez valódi segítség lehet valakinek. Elég kevés alkalommal építem fel úgy a lekérdezéseimet, hogy előtte parancssorból kipróbálom azokat, viszont a végeredményben nem szeretnék elgépeléseket látni. Ez a felhasználási mód azoknak lehet hasznos, akik gyakran tesznek fel gyors kérdéseket az adatbázisnak parancssorból, de nem ismerek olyan mazochistát, aki ezt nem egy kódszínezős, vagy legalábbis valamilyen emberibb felületről tenné.

Parancsok és adattartalmak megszűrése

Nem gondolom, hogy a biztonsági feladatokat, vagyis hogy ki milyen utasításokat adhat ki, milyen válaszokat kaphat vissza, azt a MySQL Proxy-ra kellene bízni, maga a MySQL és a rajta kívül felállított policy-k szerintem egy biztonságosabb, és jobban átlátható, egyszerűbb megoldást nyújthatnak. Azt viszont látom, hogy néhány esetben előfordulhat, hogy egy bonyolult feltételrendszert melyet a MySQL maga nem támogat, egyszerűbb lehet MySQL Proxy-val leprogramozni. De ez attól még nem segítség számomra.

Válasz üzenetek megváltoztatása, extra parancsok beillesztése

Na, ez egy komoly ügyesség lehet, hiszen vannak olyan válaszok, melyeket standard SQL-lel elég nehezen lehet a MySQL-ből (de más adatbázisból is) kicsiholni. Gondolok itt arra, amikor simán szeretném hogy egy lekérdezés eredményénél az egyik oszlop az adott válasz sorszámát tartalmazná, de beszélhetünk valami komolyabbról is, mint amikor szeretnénk pár sort összevonva, különböző szempontok szerint összegezve, valamilyen irányba transzponálva látni. Ez is egy dolog, ami kliens oldalon ugyanúgy megvalósítható, sőt, akár magában a MySQL-ben különböző tárolt eljárásokkal összehozható, de a tárolt eljárásoknál egyszerűbb, a kliens oldali megoldásnál pedig általánosabb lehetőséget kínálhat a Proxy használata. A Weblaboros cikkben elég jó példát hoztam fel, pl. minden INSERT után a beszúrt autoincrementes id-t adja vissza az SQL, egy mysql_insert_id-t (vagy SQL utasításként kiadását) megspórolhatjuk, ezzel eggyel kevesebb kört futva az SQL szerver felé. Ez a példa gyakorlatilag az extra parancsok beillesztését is lefedi, de a Proxy egyik érdekes felhasználási módja lehet, hogy kényelmesen tudunk például minden adott táblát érintő lekérdezés eredményéhez egy extra sort hozzátoldani, mely egy másik táblából szerez be információkat. Erre lehetőséget teremthet a tárolt eljárás is, kivéve ha valami SQL idegen, vagy a MySQL által “csak” nem támogatott dolgot szeretnénk megvalósítani.

Teljesítmény monitorozás

Ez gyakorlatilag a logolás egy másik módja, amikor szeretnénk megtudni az egyes lekérdezéseink hatékonyságát, sebességét.

Új parancsok, SQL-en kívüli világ

Valójában ez mozgatja meg leginkább a fantáziám. SQL felé kiadott parancs segítségével e-mail küldés, egy adott INSERT hatására például jelszóemlékeztető automatikus kiküldése. Vagy például hoszting környezetben a felhasználók a már bejáratott MySQL felhasználójuk segítségével le tudják kérdezni, hogy mekkora helyet foglalnak, hozzáférnek az egyébként nem MySQL-ben levő adataikhoz, stb. Könnyen tudunk egy olyan interfészt kínálni, melyen keresztül információkat tudunk átadni bármilyen meglévő rendszerünkből. Mi az egyszerűbb? A programozóknak egy általuk ismeretlen API-t átadni, vagy megmondani nekik, hogy ha egy ilyen és ilyen lekérdezést adnak ki, ezekhez és ezekhez az adatokhoz férnek hozzá? A válasz az lehet, hogy attól függ, de például egy közös MySQL-re épülő interfész leprogramozása sokkal költséghatékonyabb lehet, mint a cégnél/ügyfeleknél előforduló két-három nyelvre megírni és ledokumentálni egy egységes API-t, bugok nélkül.

Terhelés elosztás (és hasonlók)

Ez az, ami szintén eléggé megmozgatja a fantáziámat. Egyik nagy probléma a MyISAM táblákkal, hogy nem lehet fájdalommentesen élesben manipulálni őket, hiszen addig jellemzően blokkolva vannak a sima lekérdezések is feléjük, nem beszélve a módosításokról. Össze lehet azonban hozni egy olyan scriptet, ami átmenetileg puffereli mondjuk a változtatás jellegű kéréseket, vagy a backup adatbázis felé indítja el azokat, amíg az adatbázis szerver el van foglalva a dolgával. Vagy szeretnénk x táblával csinálni valamit, és készítünk róla egy másolatot, amit átmenetileg használunk, amíg be nem fejezzük x-szel a műveleteket. A címben levő terhelés elosztás, lekérdezések véletlenszerű vagy programozott szétosztása, a módosító műveletek pedig a fő szerver felé irányítása is elég egyszerű a MySQL Proxy segítségével.

Killer

A fentiek egyikét sem gondolom egyébként killer lehetőségnek, melynél a “best practice” az lenne, hogy a Proxy-t használjuk, bár ez változhat, ahogy egyre stabilabb rendszer lesz, és egyre többen fogják használni. Valószínűleg azonban a mindennapi munkánkat segítő kis scriptek tömkelege fog elérhetővé vállni, mint például a tesztelést segítő, makrók felvételét lehetővé tevő kis Proxy script, vagy hasonlók. Hogy általánosan elfogadott, az alap környezet részévé váló eszköz lesz-e a Proxy, vagy csak a saját szerverrel rendelkezők kiváltsága, azt még nehéz megmondani. Látok benne nagy fantáziát és kiaknázásra váró lehetőségeket, ha ezek bejönnek, akkor jó dolog lesz belőle minden bizonnyal. :)