2014. november 14., péntek

Skype telepítése 64 bites rendszerre

A Skype programot valószínűleg mindenki ismeri így nem kell bemutatnom. Ha az általunk használt repository-kban nem található meg, letölthetjük előcsomagolt bináris változatban és azt telepíthetjük, vagy kicsomagolás után egyből futtathatjuk a tömörített verziót. Mindezek azonban csak a 32 bites Linux változatra igazak, 64 bites rendszer esetén nem tudjuk ilyen egyszerűen telepíteni a programot.

Először engedélyeznünk kell 32 bites programok telepítését, majd a Skype for Debian 7 (multiarch) változatot letöltve lehet telepíteni. A .deb kiterjesztésű csomag telepítése azonban sikertelen lesz néhány függőség hiányában, így azokat is telepíteni kell. A teljes folyamat a következő:

$ sudo dpkg --add-architecture i386
$ sudo apt-get update
$ wget http://www.skype.com/go/getskype-linux-deb-32 -O skype.deb
## feloldatlan függőségek miatt itt még nem fog települni a Skype
$ sudo dpkg -i skype.deb
## folytatnunk kell a telepítést a függőségek telepítésével, itt már a Skype telepítése sikeres lesz
$ sudo apt-get install -f

Sok sikert a telepítéshez!

2014. szeptember 16., kedd

Crunchbang Waldorf (Debian) frissítése Sid-re

Egy ideje már fontolgattam, hogy áttérek Crunchbang-emmel a Debian Sid tárolóira, mely a Debian disztribúció instabil változatát jelöli (a kiadás neve egyben egy szójáték, mely a Still in development rövidítése). Felelőtlen lépésnek tűnhet instabil szoftverekből álló rendszert használni, de korántsem így áll a helyzet, mert például az Ubuntu disztribúció is ezekre a csomagokra épül, és meglehetősen stabilnak mondható. Legnagyobb előnye ennek a módszernek, hogy így a legújabb szoftvereket használhatjuk rendszerünkben, és azok függőségei miatt nem (vagy legalábbis ritkábban) találkozhatunk a dependency hell jelenségével. A Debian változatok csak stable és testing változatokban érhetőek el saját telepítőlemezzel, így sid-et csak a következő módszerrel telepíthetünk. A leírást a Crunchbang-re vonatkozó részekkel fogom kiegészíteni.

  1. Először is adjunk hozzá néhány csomagtárolót a szoftverforrásainkhoz. Az /etc/apt/sources.list fájl a következő sorokat tartalmazza:
# Stable
deb http://ftp.de.debian.org/debian/ stable main contrib non-free
deb-src http://ftp.de.debian.org/debian/ stable main contrib non-free
deb http://ftp.us.debian.org/debian/ stable main contrib non-free
deb-src http://ftp.us.debian.org/debian/ stable main contrib non-free

# Testing
deb http://ftp.de.debian.org/debian/ testing main contrib non-free
deb-src http://ftp.de.debian.org/debian/ testing main contrib non-free
deb http://ftp.us.debian.org/debian/ testing main contrib non-free
deb-src http://ftp.us.debian.org/debian/ testing main contrib non-free

# Unstable
deb http://ftp.de.debian.org/debian/ unstable main contrib non-free
deb-src http://ftp.de.debian.org/debian/ unstable main contrib non-free
deb http://ftp.us.debian.org/debian/ unstable main contrib non-free
deb-src http://ftp.us.debian.org/debian/ unstable main contrib non-free

# Security
deb http://security.debian.org/ stable/updates main contrib non-free
deb-src http://security.debian.org/ stable/updates main contrib non-free

# Crunchbang
deb http://packages.crunchbang.org/waldorf waldorf main
deb-src http://packages.crunchbang.org/waldorf waldorf main

# Debian Backports
deb http://http.debian.net/debian wheezy-backports main contrib non-free

# Debian Multimedia
deb http://www.deb-multimedia.org wheezy main non-free

Egy elég jó sources.list fájl generáló található itt, ha valaki magának szeretné összeválogatni a tárolókat.

  1. Növeljük meg az apt program cache-ét:
$ echo 'APT::Cache-Limit "134217728";' | sudo tee /etc/apt/apt.conf.d/99cache
  1. Adjunk prioritásokat a különböző szoftververziókhoz (ezt APT pinning-nek is nevezik), így alapértelmezetten a sid verziókat fogjuk telepíteni, de szükség esetén, ha egy program nem található, akkor fallback-elünk testing, vagy stable verziókra. Az /etc/apt/preferences fájl tartalma legyen a következő:
Package: *
Pin: release a=unstable
Pin-Priority: 700

Package: *
Pin: release a=testing
Pin-Priority: 650

Package: *
Pin: release a=stable
Pin-Priority: 600

Package: *
Pin: release a=waldorf
Pin-Priority: 550

Package: *
Pin: release a=wheezy-backports
Pin-Priority: 500

Package: *
Pin: release o=Unofficial Multimedia Packages
Pin-Priority: 450
  1. Frissítsük csomagjainkat és távolítsuk el, amikre már nincs szükségünk:
$ sudo apt-get update && sudo apt-get upgrade -y && sudo apt-get -y dist-upgrade && sudo apt-get clean && sudo apt-get autoclean && sudo apt-get autoremove

Ez a fenti folyamat sokáig eltarthat, és lehetséges, hogy valahol elakad, ekkor manuálisan kell megoldanunk a problémát, és újra lefuttatni a fenti parancsokat.

Kiegészítés Crunchbang-hez

  1. A tint2 taskbar egy grafikus konfiguráló programja miatt, lehet, hogy nem sikerül frissíteni a tint2-őt, így először távolítsuk el majd csak utána frissítsük a tint2-t.
sudo apt-get purge tint2conf
sudo apt-get install -f
  1. A Crunchbang-hez tartozó saját csomagokat telepítsük újra:
sudo apt-get install --reinstall cb-lock cb-conky cb-exit cb-wmhacks cb-pipemenus cb-configs cb-slim
  1. Ha olyan témát használtunk korábban Crunchbang-ben, ami nem támogatja a GTK3 verziót, akkor itt bemutatom a waldorf téma GTK3-at is támogató verziójának beállítását. Elsőként töltsük le a módosított waldorf témát innen. Majd csomagoljuk ki valahova a tömörített Openbox témát, állítsuk be lxappearance segítségével, és érvényesítsük a GTK3 használatát:
$ sudo tar -xvzf waldorf.tar.gz -C /usr/share/themes
## állítsuk be `lxappearance` segítségével az előbb kicsomagolt témát
$ lxappearance
## érvényesítsük a GTK3 téma beállítását.
$ mkdir -p ~/.gtk-3.0
$ ln -s ~/.config/gtk-3.0/settings.ini ~/.gtk-3.0
  1. A slim login manager program témája is átállítódik a frissítés után, így ha az alap Crunchbang-es témát szeretnénk visszaállítani, akkor az /etc/slim.conf fájlban kell a current_theme értékét waldorf-ra állítanunk.

  2. A power manager újabb verziójában van egy bug, ami miatt nem jelenik meg tint2-ben az akkumulátor töltöttséget jelző kis ikon. Ennek megoldására telepítsük fel a stable változatát a programnak:

## először távolítsuk el a korábbi változatot
$ sudo apt-get purge xfce4-power-manager xfce4-power-manager-data
## telepítsük a stable változatot
$ sudo apt-get -t stable install xfce4-power-manager
  1. Indítsuk újra a gépet, és élvezzük a friss és ropogós programjainkat!

2014. augusztus 27., szerda

A kliensoldali teljesítmény számít

Eredetileg megjelent a Kir-Dev oldalán

Sokan hallhattatok már a backend oldali skálázásról, a különböző cluster és sharding megoldásról (a témában érdemes követni a HighScalability oldalt), de valójában erre az esetek nagy részében nincs szükség egy új alkalmazás bevezetésekor a piacra. Ekkor sokkal nagyobb hangsúlyt érdemes fektetni a felhasználói elégedettségre, amit inkább az alkalmazásunk kliens oldali teljesítménye határoz meg. A határok persze nem ilyen élesek, olvass tovább!

A felhasználók számára elsőrendű kérdés, hogy mennyit kell várniuk egy oldal betöltődésére. A Google felmérései szerint 500 ms késleltetés a keresési eredmények megjelenítésében 20%-os reklámbevétel kiesést jelent, az Amazon mérései szerint minden 100 ms késleltetés 1%-al csökkenti az eladott áruk mennyiségét a webes kereskedő portálon. 2 másodperc várakozás után a felhasználók már türelmetlenek kezdenek lenni, 3 másodperc után 40%-uk egyszerűen elhagyja az oldalt.

Két számot érdemes megjegyezni a front-end optimalizációval kapcsolatban:

  • 1000 ms: ennyi idő alatt feltétlen valamilyen használható tartalmat kell mutatni a felhasználónak
  • 16,6 ms: ennyi időnként elő kell állítani egy frame-et a jó minőségű, 60 FPS sebesség eléréséhez

A bevezetőben sugalltuk, hogy a kliens oldali teljesítménynél nem csak a felhasználóhoz megérkezett adatoktól számított feldolgozási és renderelési időt vesszük figyelembe, hanem azt is, hogy a bitek milyen formában közlekednek a böngésző és a szerver(ek) között. Mielőtt elkezdenénk megvizsgálni a különböző optimalizálási lehetőségeket, nagy vonalakban áttekintjük a HTTP lekérdezések felépítését.

  1. DNS lekérdezés: A kliens megpróbálja feloldani a domain nevet, a DNS szerver válaszol egy IP címmel.
  2. Kapcsolódás: Megtörténik a háromfázisú TCP handshake, a kliens SYN csomagot küld a szervernek, a szerver SYN-ACK csomaggal válaszol, végül a kliens ACK csomagot küld és ezzel létrejött a TCP kapcsolat.
  3. Küldés: A kliens HTTP üzeneteket küld a web szervernek.
  4. Várakozás: A szerver feldolgozza a kérést, elkészíti a választ, majd elküldi a kliensnek.
  5. Betöltés: A kliens feldolgozza szerver válaszát.
  6. Lezárás: A kliens lezárja a kapcsolatot.

1. fázis: DNS lekérdezés

A DNS lekérdezés folyamatának ideje elég széles skálán mozog. DNS cache találatkor 1 ms-től kezdődően, a teljes lekérdezés esetén akár több másodperces idejéig változhat a művelet ideje. Az egyik lehetőség DNS lekérdezés gyorsítására a DNS prefetch, ahol az oldalon található linkek domainjei már betöltődés közben párhuzamosan fel lesznek oldva. Ezt a böngésző egy külön szálon végzi el. Hasznos lehet ez a funkció, ha gyakran hivatkozott más domainekre vannak linkjeink, ilyen például egy hírportál, vagy egy keresőprogram. A domain nevek előzetes feloldását manuálisan elősegíthetjük a következőképpen:

<link rel="dns-prefetch" href="//<prefetch-elni kívánt oldal címe>">

A prefetchelést ki és bekapcsolhatjuk a következő meta tag content attribútumának off vagy on értékével:

<meta http-equiv="x-dns-prefetch-control" content="off">

2. - 3. fázis: Kapcsolódás és küldés

Láthatjuk, hogy az idő jelentős részében a kliens csak hálózati kommunikációt folytat, így a DNS lekérdezések és TCP kapcsolatok létrehozása jelentős overhead-del jár. Ezen akkor tudunk spórolni, hogy ha minél inkább kötegelten, egyszerre végzünk el műveleteket, ugyanis a hálózati kommunikációt nem igazán tudjuk gyorsítani (2.-3. fázis). Ehhez kapcsolódó módszereket a kliens oldali optimalizáció részénél mutatom be.

4. fázis: Várakozás a szerver válaszára

Ez a lépés főleg a szerver oldali alkalmazás gyorsítását jelenti: a minél gyorsabb válaszidő elérését. Ennek elég terjedelmes szakirodalma van és nem is tartozik nagyon a kliensoldali optimalizációhoz, így most nem fogok bővebben írni róla. Statikus fájlok kiszolgálásakor érdemes a cachelést finomhangolni, illetve beállítani a gzip tömörítést a webszervernél.

5. fázis: Betöltés

A kliens oldali teljesítményt legnagyobb részben ez a tényező határozza meg. Itt dolgozza fel a kliens a szerver válaszát, betölti az oldalhoz szükséges erőforrásokat, előállítja a megjelenítendő oldalt, másnéven rendereli azt. Két művelet van a megjelenítés során, amelyeket meg kell érteni:

  • repaint: Egy elem kinézete megváltozott, de az oldal elrendezése nem változott. Például ilyen, ha outline, background-color CSS osztályok lettek hozzáadva egy elemhez.
  • reflow: Az elem megváltozása miatt újra kell számolni az oldal elrendezését. Ez a művelet mindig egy repaint-et is vonz maga után, így különösen drága művelet, ezért spórolni kell a használatával.

Ezek után az a kérdés, hogy mi okoz reflow-t? A rossz hír az, hogy szinte minden: például DOM műveletek, lekérdezések; stílusok hozzáadása, elvétele; görgetés, átméretezés. A rengeteg DOM műveletet végző alkalmazásoknál spórolni kell a nagy számításigényű műveletekkel, mert csak így lehet nagyobb teljesítményt elérni.

A következőkben bemutatok pár jól használható technikát, amelyekkel csökkenthetjük a fenti erőforrásigényes műveletek számát. A legfontosabb, hogy a DOM-fa minél kisebb részfáját módosítsuk. Az egyik leghasznosabb trükk, ha semmiképpen sem tudjuk elkerülni a nagyszámú DOM műveletet, ha azokat a fáról leválasztva végezzük el. CSS segítségével display:none; stílust adhatunk egy részfának, így a különböző műveletek esetén nem okoznak reflow-t a módosítások. Javascript esetén a részfákat kell előállítanunk memóriában, majd később hozzá lehet adni a DOM fához. A részfa lemásolásához használható a cloneNode() metódus. Hasznos lehet tudni, hogy a DOM műveleteket a böngészőmotor csoportosítva, kötegelten végzi el, így az olvasás illetve írás jellegű műveleteket minél inkább egyszerre érdemes végrehajtani. Erre példa lehet, amikor CSS osztályokkal alkalmazunk egy stílust egyszerre több elemre, vagy Javascriptnél próbáljuk a lekérdezés, módosítás jellegű műveleteket csoportosítani.

Erőforrások betöltése

Az egyik első dolog, amit optimalizálni érdemes az az oldal betöltődéséhez szükséges kapcsolatok számának minimalizálása. Alapesetben minden erőforrást egy külön kapcsolaton keresztül kell megszerezni, így ez rengeteg overhead-et jelent. Ennek megoldásában segíthetnek a HTTP2 / SPDY protokollok használata. A HTTP2 a SPDY protokollon alapszik, mely képes multiplexelni a kapcsolatokat, illetve tömöríti a fejléceket. Apache HTTPD modulként és NGINX modulként is szerezhető támogatás hozzá. A kapcsolatok multiplexelésével az oldalhoz szükséges erőforrások egyszerre letöltődnek, így azok nem jelentenek külön overhead-et. Azonban, ha nem a saját webszerünkön futtatjuk az alkalmazást és nem tudjuk kihasználni a fenti protokollok előnyeit, akkor más módszerek használatára is szükség van.

Egyrészt a SPDY protokoll nyújtotta előnyök egy részét mi is előállíthatjuk magunknak, ha tömörítjük és összefűzzük az erőforrásokat. CSS és JS fájloknál a tömörítés a whitespace-ek eltávolítását jelenti, illetve JS esetén az obfuszkálással (kódösszezavarással) is kisebb lesz a fájl mérete. Ezen feladatokat a múltkori cikkben is bemutatott Grunt segítségével könnyen végrehajthatjuk a concat és uglify taskok segítségével.

A nélkülözhetetlen funkciókat tartalmazó kritikus JS és CSS fájlok kiválasztása rendkívül fontos: a critical rendering path minimalizálásával a legnagyobb, sok erőforrást használó oldalt is gyorsabbá tehetjük, mint akár egy egyszerűbb weboldalt. Milyen funkciókat tartunk kritikusnak? Azokat amelyek az oldal kezdeti betöltődésekor görgetés nélkül látszódnak és alapvető funkciókat nyújtanak az oldal használatában. A görgetés nélkül látszódó tartalmat okosan kell megválasztani, ehhez úgy kell átstruktúrálni az oldal HTML kódját, hogy a fő tartalom ott helyezkedjen el és a másodlagos dolgok csak később kerüljenek betöltésre. Például egy navigációs sávot hiába feljebb helyezkedik el az oldalon a tartalom után kell elhelyezni a HTML-ben és csak ezután CSS segítségével pozícionálni. Ezzel a trükkel a felhasználóknak gyorsan tudunk tartalmat kiszolgálni.

A lehető leggyorsabb alkalmazás betöltődéshez és a minél hamarabbi használhatósághoz a kritikus funkciókat tartalmazó rövidebb JS és CSS részeket tehát érdemes inline az oldal head részében megírni, mivel azon kódrészletek futnak le a leghamarabb a HTML fájl letöltődése után. A hosszabb kritikus JS és CSS fájlokat azonban érdemesebb már külső erőforrásként betölteni, mivel azokat a böngésző cacheli. A többi fájl betöltése történhet lazy loading segítségével (azaz JavaScript-ből adjuk hozzá a script tag-et a HTML-hez), vagy használhatjuk a késleltetett betöltés technikáját.

Alapvetően háromféle módon tölthetünk be külső JavaScript-et:

  • alapértelmezett: Ebben az esetben, ha a HTML fájl parse-olása a script tag-hez ér, akkor megszakad a parse-olás, betölti a JS fájlt, lefuttatja, majd folytatja a script tag utáni HTML beolvasását.
<script type="text/javascript" src="<JS fájl elérési útvonala>"></script>
  • késleltetett: Amikor a HTML fájl parse-olása a script tag-hez ér, párhuzamosan letöltődik a JS fájl, majd csak a HTML fájl parse-olásának végén kerül futtatásra.
<script defer type="text/javascript" src="<JS fájl elérési útvonala>"></script>
  • aszinkron: Amikor a HTML fájl parse-olása a script tag-hez ér, párhuzamosan letöltődik a JS fájl, majd a parse-olás megszakad és csak akkor folytatódik, ha lefutott a JavaScript kód.
<script async type="text/javascript" src="<JS fájl elérési útvonala>"></script>

A tapasztalatok alapján azonban nem minden böngészőben működik jól az erőforrás betöltődés késleltetése (defer) így, ha a critical rendering path-ról teljesen el akarjuk tüntetni a betöltődést, használhatjuk a Google által is javasolt megoldást:

<script type="text/javascript">
  function downloadJSAtOnload() {
    var element = document.createElement("script");
    element.src = "<JS fájl elérési útvonala>";
    document.body.appendChild(element);
  }
  if (window.addEventListener)
    window.addEventListener("load", downloadJSAtOnload, false);
  else if (window.attachEvent)
    window.attachEvent("onload", downloadJSAtOnload);
  else window.onload = downloadJSAtOnload;
</script>

Ha külső domainről töltünk be erőforrást, akkor pedig mindenképp érdemes valamilyen CDN-t ( content delivery network ) használni, mely egy olyan szolgáltatás, amivel a felhasználóhoz földrajzilag legközelebb eső szerverről szerezheti meg a kívánt erőforrást. Ilyen CDN-t a Google is üzemeltet, de itt inkább csak a legismertebb library-ket találhatjuk meg, így célravezető máshol is körbenézni.

Képek

A következő nagyobb optimalizálható rész egy honlapon a képek kezelése. A critical render path-ra eső képeket a HTML-lel együtt töltsük be, az egyéb kevésbé fontos, vagy nem látszódó képeket lazy loading segítségével Javascript kódból. A megjelenítendő képeket minden esetben optimalizáljuk a webes megjelenítésre. Böngészőkből a képeket átméretezni sok számítással jár és minden esetben reflow-t okoz, így azokat minél inkább kerüljük. Minőségüket a szemmel nem látható mértékig csökkentsük, és tömörítsük őket. A tömörítésben segíthetnek a különböző fejlettebb képszerkesztő programok, vagy olyan webes eszközök, mint a Yahoo Smush.it és a PunyPNG. Egyes esetekben a képméretet más fájlok méretének rovására csökkenthetjük, például megadhatjuk a képünket base64 kódolással a CSS méretének megnövelésével, vagy ha a képeket SVG formátumban használjuk, elkészíthetjük őket akár Javascript segítségével is.

Spórolhatunk a különböző képek betöltéséhez szükséges kapcsolatokon is, ha azokat egyszerre, kötegelten végezzük el. Ebben segíthet a korábban már említett SPDY protokoll, vagy választhatjuk a korábbi módszert, a spriteokat. Sprite-ok esetén egy nagyobb képre összemásoljuk az összes szükséges képet, így azok egyetlen fájlként töltődnek le, majd CSS segítségével jelenítjük meg belőlük a szükséges részeket kivágással.

Érdekességként említeném meg a külön webre optimalizált formátumokat, mint a WebP, mely 25-34%-al kisebb mint az egyéb képformátumok. Sajnos nem mindenhol támogatott a technológia (például Firefox-ban nem használható még), így nem ajánlott az éles bevetése, de mindenképp érdemes figyelemmel kísérni fejlődésüket.

Összefoglalás, további olvasnivalók

Először is gratulálok mindenkinek, aki eljutott az olvasással idáig. Hosszú út volt, amely során láthattuk, hogy a HTTP lekérdezések egyes fázisait milyen módszerekkel lehet optimalizálni. A rengeteg lehetőség közül, amiket a leginkább kiemelnék és a Google ajánlások közül is a legfontosabbak:

  • oldal tartalmának priorizálása (critical rendering path)
  • erőforrások okos betöltése
  • képek optimalizálása

Természetesen a fenti műveletek végrehajtása után is érdemes méréseket végezni, ehhez ajánlom a Google PageSpeed Insights és Webpagetest elemzőprogramokat, melyek értékelési szempontjai alapján ezen cikk is készült. További olvasnivalónak pedig ajánlom az alábbi linkeket:

2014. február 23., vasárnap

Frontend tooling Yeoman segítségével

Minden fejlesztőnek megvan a maga kedvenc eszközkészlete, melyet szívesen használ valamilyen fejlesztéshez, jelentsen ez egy IDE-t, egy szövegszerkesztőt, verziókezelőt, build rendszert vagy bármi hasonlót. A következőkben a Yeoman eszközkészletet, vagyis még inkább egy munkafolyamatot fogok bemutatni, melyet front-end fejlesztéshez lehet használni.

Úgy tűnik az előző kicsit elméleti cikk után, mostantól néha fognak megjelenni kevésbé step-by-step leírások. A mostani is részben ilyen, hiszen egy technológiát fogok bemutatni, amely szinte módszertanként is használható a webes fejlesztések során.

Eredetileg megjelent a Kir-Dev oldalán

A Yeoman nevű programcsomag rendkívül megkönnyíti a front-end fejlesztők életét. Köszönhető ez a nagyon gazdag funkcionalitásának, mely könnyen kiegészíthető, konfigurálható, így tényleg a segédünkként tud szolgálni az eszköz. Alapvetően három, különállóan fejlesztett, de együttműködő NodeJS-ben írt alkalmazásról van szó, melyek különbözőképpen segíthetik munkánkat:

  • Yo: scaffolding eszköz
  • Bower: függőségkezelő eszköz
  • Grunt: feladatfuttató eszköz

Egyesével bemutatom mire képesek és hogyan kell őket használni. A könnyebb érthetőség érdekében egy komplett példán keresztül fogom bemutatni a Yeoman-t: egy AngularJS alapú kezdő alkalmazást fogunk készíteni.

Előkövetelmények és telepítés

Először is szükség lesz egy NodeJS telepítésére, ugyanis ez fogja futtatni a fenti programokat. Linuxon lehet csomagkezelőből, vagy forrásból telepíteni. Windows-hoz és Mac OSX rendszerre elérhetőek bináris formátumban is. Ha a NodeJS-t sikeresen feltelepítettük következhet a programok telepítése a NodeJS csomagkezelőjével.

# NodeJS letöltése
$ wget http://nodejs.org/dist/v0.10.26/node-v0.10.26.tar.gz
# kicsomagolás
$ tar -xvzf node-v0.10.26.tar.gz
# fordítás
$ cd node-v0.10.26.tar.gz
$ ./configure && make
# telepítése
$ sudo make install
# Yo, Bower, Grunt telepítése
$ sudo npm install -g yo bower grunt

Yo

Mit is jelent a scaffolding? Alapvetően ezzel a fejlesztés sebességét tudjuk növelni. Sablonokat generálhatunk, melyekből kiindulva állhatunk neki egy program elkészítésének. Ezek a sablonok sokfélék lehetnek, az egyszerű konfigurációs fájloktól kezdve, melyeket más programok használnak, egészen a saját elkészítendő programunk vázáig. Lehetnek ezek fejlesztést segítő szkriptek, komplett szoftverstack vagy más boilerplate kódok, melyeket előre generálhatunk az alkalmazásunkhoz.

Ahhoz, hogy sablonokat tudjunk készíteni a Yo-val generátorokra lesz szükség. Egyrészt vannak hivatalos és még több a közösség által készített generátorok, melyekkel teljes alkalmazás vázakat és hozzájuk tartozó környezetet tudunk generálni. Például készíthetünk teljes AngularJS környezetet (ami integrálja a Bower és Grunt eszközöket is), mobil first weboldalt, Wordpress alapkörnyezetet, RevealJS vázakat, de készíthetünk szerver oldali alkalmazás szkeletonokat is, például ExpressJS-hez. Kezdjük el tehát az AngularJS kiinduló programunkat:

$ sudo npm install -g generator-angular
$ mkdir angularapp && cd angularapp
$ yo angular example

Elsőként telepítettük az AngularJS-hez szükséges generátort, majd egy mappában legeneráltuk a teljes kiinduló alkalmazás sablont. Az AngularJS egy MVVM keretrendszer, így tudunk olyan sablonokat generálni, mint az MVC-ből is ismert Controller, vagy a View elemeket valósítják meg.

$ yo angular:controller myController
$ yo angular:view myView

Bower

Senki nem szereti az alkalmazásának a függőségeit kézzel letölteni és azok minden újabb verziójánál újra eljátszani ezt a folyamatot. Az egyszerű megoldás valamilyen függőségkezelő eszköz (dependency management tool) használata, mellyel mindezt megtehetjük. A program intelligensen feloldja és telepíti a kívánt CSS, vagy JavaScript könyvtár saját függőségeit is. Például így kereshetünk a jQuery projektek között és telepíthetjük, a jQuery UI-t, majd frissítjük az összes telepített függőségünket:

$ bower search jquery
$ bower install jquery-ui
$ bower update

Grunt

Az utolsó eszköz amit bemutatok a Grunt, mely egy parancssoros feladat futtató (task runner tool). Ez sokat nem mond el magáról, de egy elég általános célú eszköz, ezért konkrétabban nem is lehet definiálni. Legjobban JavaScript alapú fejlesztéseink során alkalmazhatjuk, és temérdek feladatot végeztethetünk el vele nagyon egyszerűen. Néhány példa a sokrétű használhatóságára:

  • JavaScript fájlok minimalizálása, kódtömörítés (minify)
  • JavaScript kód obfuszkálása (uglify)
  • képek tömörítése a webre
  • JavaScript és CSS fájlok összefűzése
  • livereload Web szerver indítása teszteléshez, melyben az alkalmazásunk fut
  • szintaktikai ellenőrzések futtatása
  • egység és integrációs tesztek futtatása (előzővel együtt használva continuous integration-re is használható)

Ezek csak a beépített és gyakran használt funkciók, az eszköz ennél sokkal többre képes és egyszerűen kiegészíthető a közösség által készített újabb taszkokkal. Példa a használatára:

## livereload webszerver indítása
$ grunt serve
## tesztek futtatása
$ grunt test
## alkalmazás buildelése (kódtömörítés, obfuszkálás, stb.)
$ grunt build

Ezzel a Yeoman bemutatásának végére értünk, remélem hasznosnak találtátok, és sikerült bemutatni, mivel tudják kiegészíteni a front-end fejlesztők eszközparkját ezek a programok.

2014. január 31., péntek

Conky: Gmail szkript

Eljött az ideje, hogy lecseréljem az ősrégi Conky olvasatlan emailszám kijelző szkriptemet, mely egy nem teljesen erre a célra készített Perl szkript volt eddig. Megírtam tehát alig pár sorban Python3 segítségével az új verziót, mely körülbelül kétszer gyorsabb, mint az eredeti Perl szkript, valamint hálózati kapcsolat nélkül sem száll el.

Telepítéséhez szükség lesz a python-requests csomagra:

$ sudo apt-get install python-requests

Majd hozzunk létre egy fájlt, és illesszük be a szkriptet:

$ mkdir -p ~/.scripts
$ touch ~/.scripts/gmailToConky.py
$ chmod +x ~/.scripts/gmailToConky.py
$ gedit ~/.scripts/gmailToConky.py

Itt a szkript:

Így használhatjuk Conky-ban:

You have ${texeci 300 python ~/.scripts/gmailToConky.py} new gmail(s).

Megjegyzés: a korábbi Conky-hoz való szkriptjeim is frissültek (The Old Reader szkript, Google Calendar szkript), használatuk kis mértékben változott a Python3-ra való áttérés miatt.

2014. január 28., kedd

Hypermedia API

A mostani cikk kevésbé kapcsolódik a Linux-hoz, viszont egyfajta tutorialként felfogható és mint egy általános paradigma platformfüggetlenül felhasználható, így itt is megjelenhet a blogon. :)

Eredetileg megjelent a Kir-Dev oldalán

Bevezetés

Az informatikai rendszerek architektúrájában egy evolúciós lépés a szolgáltatás-orientált programozás (SOA), melyet gyakran webszolgáltatások formájában implementálnak. A SOA architektúra azonban önmagában nem a webre született, így kialakult az erőforrás-orientált architektúra (ROA), mely inkább programozási paradigmának, vagy megvalósítási stílusnak nevezhető. A ROA lényege, hogy a szoftvert erőforrások formájában tervezzük meg és az alkalmazást alkotó szolgáltatások REST interfészen keresztül kommunikálnak.

Két gép kommunikációjához valamilyen protokollra és adatformátumra van szükség. Az erőforrás-orientált programozás során használt REST a HTTP protokoll webes szemantikáját terjeszti ki azzal, hogy az alkalmazás állapotát HTTP kérésekkel lehet lekérdezni, illetve módosítani. Ez webszolgáltatások esetén sokkal könnyebben használható, mint a SOA, ami sokáig egyet jelentett a SOAP-pal. A REST-ben megfogalmazott vezérelvek nem határoznak meg konkrét adatátviteli formátumokat, így webszolgáltatások esetén felhasználástól függően különböző formátumokat használnak, mint például XML vagy JSON.

Hagyományos SOA rendszereknél egy távoli lekérdezés adatokkal tér vissza, ROA esetén viszont az alkalmazás további állapotaiba vezető átmenetek is a visszatérési érték részét képezik. Az alkalmazás állapota részletesen leírható a hypermedia formátumok metaadat leíró képességével, az állapotátmenetek pedig könnyen reprezentálhatóak a hypermedia adatformátumokban meglévő linkekkel: innen ered a technológia elnevezése a Hypermedia API. Használatával a klienseknek csak linkeken keresztül kell kommunikálnia a backend szolgáltatással, így weben rendkívül jól használható. Segítségével valóban vékony kliensek hozhatók létre, amik nagyon keveset tudnak a háttérben dolgozó szolgáltatásról. A szolgáltatás részleteinek változásakor nem kell változtatni a kliensen, ezért a Hypermedia API könnyebben használható programok számára és azokat így könnyebb is karbantartani.

Adatformátumok

Lényegében bármilyen adatátviteli formátumot használhatunk, de a legelterjedtebbek, melyeket HTTP protokoll felett használnak a HTML, XML és a JSON. Más lehetséges formátumok például a CSV, YAML, Markdown, ATOM, de ezek kevésbé elterjedtek ilyen célból. Koncentráljunk a három legelterjedtebbre, és lássuk melyiknek milyen előnyei vannak.

XML

  • (+) Rendkívül kiforrott formátum és nagyon sokféle támogató technológia érhető el hozzá. Például transzformáció (XSLT), lekérdezés (XPath, XQuery), validáció (XSD, DTD).
  • (+) Szabványos és minden programozási nyelvből elérhető.
  • (-) Kliens oldalon nehezebb használni.
  • (-) Nehézsúlyú: kommunikációs overhead.
  • (-) Nincs natív állapotátmenet reprezentáció kiterjesztés nélkül.

JSON

  • (+) Kliens oldalon könnyű használni.
  • (+) Könnyűsúlyú.
  • (-) Nincs szabványos lekérdezés, validálás.
  • (-) Nincs natív állapotátmenet reprezentáció kiterjesztés nélkül.

HTML

  • (+) Kiforrott formátum, sok támogató technológia.
  • (+) Kliens oldalon használata triviális.
  • (+) Javascript segítségével módosítható.
  • (+) Natív állapotátmenet reprezentáció.
  • (+) Jól jön, ha olvashatónak kell lennie az API-nak.
  • (-) Nem mindig készíthető egyszerűen el az alkalmazás állapotának reprezentációja.

Néhány példa

Labirintus

Labirintus játék API XML felhasználásával:

  • Különféle labirintusok közül választhatunk a collection listából.
<maze>
    <collection href="...">
        <link href="..." rel="maze" />
        <link href="..." rel="maze" />
    </collection>
</maze>
  • A kiválasztott labirintusba beléphetünk, vagy visszaléphetünk a labirintus-listához.
<maze>
    <item href="...">
        <link href="..." rel="collection" />
        <link href="..." rel="start" />
    </item>
</maze>
  • Járkálhatunk a különböző cellákon (cell), újrakezdhetjük a labirintust, vagy választhatunk másik labirintust. Megjegyzés: természetesen nem mindig lehet minden irányban lépkedni, itt az összes lehetőséget felsoroltam.
<maze>
    <cell href="...">
        <link href="..." rel="north" />
        <link href="..." rel="south" />
        <link href="..." rel="east" />
        <link href="..." rel="west" />
        <link href="..." rel="exit" />
        <link href="..." rel="maze" />
        <link href="..." rel="collection" />
    </cell>
</maze>

Todo app

Todo alkalmazás API-ja JSON+Collection adatformátumot használva (itt az items tömbben vannak az adatok eltárolva és queries-ben a lehetséges műveletek):

{
  "list" : {
    "link" : {
      "href": "{collection-uri}",
      "rel": "list" 
    },
    "items" : [
      {
        "link" : {
          "href": "{item-uri}",
          "rel": "item" 
        },
        "title" : "First task",
        "description" : "start JSON implementation of the list",
        "date-due" : "2010-05-01",
        "completed" : false 
      },
        ...
    ],
    "queries" : [
      {
        "link" : {
          "href": "{query-link}",
          "rel": "today" 
        } 
      },
      {
        "link" : {
          "href": "{query-link}",
          "rel": "open" 
        } 
      },
      ...
    ]
  }
}  

Tervezés

A Hypermedia API-k tervezésének lépései:

  1. Üzleti logika vizsgálata
  2. Állapotgép készítése
  3. Adatreprezentáció készítése

Az ábrázolás részletei a választott adatformátumtól függnek, de sok közös vonás van, amik megegyeznek az egyes formátumok között, közös elnevezésük angolul H-Factors. Ezek a tényezők alapvetően két részre bonthatók: vannak a link factor-ok, melyek a kliens-szerver kommunikáció létrehozásáért felelősek; és vannak a control factor-ok, melyek a metaadatok részleteit módosítják. Lássuk hogyan épül fel belőlük egy API, mely HTML-t használ adatformátumként:

Egy adott URL-en lévő tartalmat be kell olvasni és az adott helyen megjeleníteni, más néven beillesztés.

<img alt="..." src="..." />

Egy adott URL-en lévő tartalmat ki kell olvasni és egy új nézetben megjeleníteni, más néven navigáció.

<a href="...">...</a>

Egy adott URL-en lévő tartalmat valamilyen klienstől származó információkkal paraméterezve kell kiolvasni.

<form method="get" action="http://www.example.org/">
    <input type="text" name="search">
    <input type="submit" />
</form>

vagy

<a href="http://www.example.org/?search={searchParam}"></a>

Idempotens metódusok, melyek többszöri végrehajtása ugyanazt az eredményt adja, mint az egyszeri végrehajtás. HTTP protokoll esetén ezek a PUT és DELETE verb-ekkel végrehajtott kérések. HTML-ben csak Javascript segítségével megvalósítható.

Nem idempotens metódusok, ilyenek a HTTP protokoll esetén a POST verb-ekkel végrehajtott kérések.

<form method="post" action="http://example.org/comments/">
    <textarea name="comment"></textarea>
    <input type="submit" />
</form>

Control factors

CR (Read controls)

Az adatok olvasását befolyásoló tényezők. Ilyenek HTTP protokoll esetén a fejléc (header) változók, mint például a Content-Type.

CU (Update controls)

Az adatok olvasásának befolyásolását segíti ez a tényező. Ilyen HTML esetén a formokban található enctype attribútum, mely a kéréshez tartozó Content-Type fejlécet tudja módosítani.

<form method="post" action="http://example.org/comments/" enctype="text/plain">
    <textarea name="comment"></textarea>
    <input type="submit" />
</form>

CM (Method controls)

Az adatkezelés módjának megváltoztatását segíti ez a tényező. HTML esetén a method attribútum erre szolgál.

<!-- frissítés -->
<form method="post" action="..." />
...
</form>

<!-- olvasás -->
<form method="get" action="..." />
...
</form>

Egy node annotációjával is módosíthatjuk egy URL-en található tartalom értelmezését. Ilyen HTML esetén a link tag rel attribútuma.

<link rel="stylesheet" href="..." />

Konklúzió

Egy rövid bevezető után láthattuk hogyan épül fel a Hypermedia API, megismertük a főbb jellemzőket. Láthattuk hogy:

  • hogyan csökkenti a csatolást a kliens és a szerver oldali kód között a paradigma a belső megvalósítás függetlensége miatt (nincs konkrét url-től, paraméterektől való függőség)
  • hogyan lesz könnyebben használható kliensek számára
  • hogyan lesz olvashatóbb felhasználók számára

Egy szóval linkek használata az API-ban egy jó dolog, próbáljátok ki a GitHub API-ját! Akit továbbiakban is érdekel a téma itt találhat 3 teljes implementációt XML, JSON és HTML nyelven, valamint teszt klienseket is hozzájuk.