MySQL Dump git hook-ból

Készítettem egy kis futtatható git hook-ot, ami a MySQL adatbázisom tartalmát teszi be egy sql fájlba. Azt ajánlják, hogy az adatbázis szerkezete és a tartalma külön fájlokban legyen, de én ezzel annyira most nem törődtem... Igazából ha a séma változik, akkor a tartalom is, ha a tartalom változik, akkor már mondjuk nem igaz ugyanez. Azért nem tartom fontosnak külön fájlba szedni ezeket, mert úgyis leírom a szerkezetváltozásokat a commit szövegébe...

#!/bin/sh
cd "$(git rev-parse --show-toplevel)"
rm -f "backup.sql"
exec "absolute/path/to/mysqldump.exe" --skip-comments -u myuser --password=mypass mydb |sed 's$),($),\n($g' > "backup.sql"
exit
(Sajnos a google syntax highlighter nincs a helyzet magaslatán, az & gt; helyett képzeljetek oda nagyobb jelet.)

A hook-ban az első sor a shell-t tölti be. Erre azt hiszem nincs szükség, mert a bash ezt alapból megteszi nekünk. Nem tudom, hogy van e lehetőség az ilyen futtatott fájloknál környezet betöltésre, ezt még ki kell tapasztalnom a későbbiekben.

A második sorban a git rev-parse --show-toplevel az aktuális repo root-ját adja. Ehhez előtte egy olyan útvonalat kell beállítanunk a cd-vel, ami benne van az aktuális repo-ban. A kezdő útvonal valószínűeg a git bash alapértelmezett útvonala, tehát a felhasználói könyvtár, ahol megoszott képek meg dokumentumok vannak, szóval az előző blog bejegyzésben leírt bat fájlt majd ki kell egészíteni az útvonal beállítással is, amennyiben ez lehetséges.

A harmadik sorban töröljük a régi sql fájlt. Erre azt hiszem nincs szükség, ahogy kitapasztaltam a .bat fájlokban a > azt jelenti, hogy felülírjuk a régi fájlt, a >> pedig azt, hogy hozzáfűzzük a tartalmat a régi fájl végéhez. Az eredeti kódban, amit átalakítottam erre a formára, benne volt az rm, ezért hagytam meg ebben is.

A negyedik sorban az új sql fájlt hozzuk létre az adatbázis aktuális állása alapján. A --skip-comments -re azért volt szükség, mert a commentek között szerepel többek között a készítés dátuma, ez pedig azt eredményezné, hogy minden egyes dump híváskor megváltozna a fájl függetlenül attól, hogy az adatbázis változott e. A user, password, database részek, illetve a dump fájl megadása evidensek, a sed-es rész pedig azt csinálja, hogy az egy sorba betömörített multi insert-et szépbontja több sorba, így minden egyes rekord-nál külön sorban jelenik meg az esetleges változás. Ennek hasznosságát azt hiszem nem kell hangsúlyoznom...

Nem sokára megpróbálkozom még extrémebb dolgokkal, mint például wsh-ban írt deploy kód futtatásával, és hasonlókkal, egyelőre azonban elég ennyi a parancssorból. :-)

Git - hook fájlok társítása és futtatása

A git hook-ok a .git/hooks/ könyvtár alatt található állományok. A tartalmuk a git shell által értelmezhető parancsokból áll, és esemény kezelőként szolgálnak. Nem valami fejlett az esemény kezelési modell, viszont attól még működik. Például a pre-commit hook a commit előtt fut le, mint azt a neve is mutatja, és képes megakadályozni a commit lefutását. Ez körülbelül a HTML 10 évvel ezelőtti esemény moddeljének felel meg, ahol szintén a visszatérési értékkel lehetett az eseményt semmissé tenni...

A git hook-ok egyébként nagyon hasznosak tudnak lenni pusztán ettől a funkciótól is, hiszen a deploy kódot lehet hívogatni velük... Például a pre-commit-ban elhelyezhetünk unit test-eket, vagy osztályokból nagyobb fájlok összeállítását, esetleg fájlméret optimalizálást, de akár a commit után is elvégezhetőek ugyanezek, sőt a committál fájlok teszt majd éles szerverre történő másolása, és még sok dolog ugyanígy megoldható velük. Gyakorlatilag egy egész build rendszert lehet erre építeni, ahogy már meg is tették mások a maven és az ant esetében. Ennek a hook-os megoldásnak az előbbiekkel szemben annyi az előnye, hogy nincs feleslegesen túlbonyolítva...

A git hook-ok egy nem túl standard felhasználási módja a parancsfájlként történő futtatás. Nekem erre azért volt szükségem, mert windows alatt szerettem volna unix-os parancsokat használni, és ezek bent vannak a shell-ben. Persze ugyanezt cygwinnel is megoldhattam volna, dehát minek tegyek fel egy új rendszert, amikor már van egy használható?!

Az alap problémám az volt, hogy volt egy pre-commit-om, amit szerettem volna parancsfájlba áttenni. Próbálkoztam bat fájllal, wsh-js fájllal, de egyik sem volt igazán nyerő, mindegyik elbukott, vagy a szóközös fájlnevek, vagy a unix függvények miatt. Végül úgy döntöttem, hogy megpróbálom a git-tel lefuttatni az eredeti kódot valahogyan. Persze először itt is wsh-val próbálkoztam, de nem jött össze a sok egymásba rakott idézőjel miatt megzavarodott az egész.

Végül úgy döntöttem, hogy jobb hagyni a wsh-t, és a windows-os cli-t a lehető legkisebb mértékben érintő kódot írni. Ez gyakorlatilag azt jelenti, hogy meghagyom a hook fájlt, és megpróbálom a tartalmát lefuttatni valahogyan a git shell-ben. Keresgéltem elég sokat, de nem találtam szinte semmit. Ezután megpróbáltam a hook fájlt társítani valamelyik git exe-hez, de ez sem vezetett eredményre. Végül felfedeztem, hogy a git bash-ben akár txt fájlokat is le lehet futtatni pusztán a fájlnév beírásával, és a bennük lévő parancsok ugyanúgy végrehajtásra kerülnek, mint az automatikusan hívott hook-oknál. Ebből kiindulva csináltam egy kis bat fájlt, ami a megadott fájlt a git bash-ben végrehajtja.

if not exist %1 exit
set bash=C:\Program Files (x86)\Git\bin\bash.exe
"%bash%" --login -i -c "exec "%1""

Ezek után a .hook kiterjesztésű fájlokat ehhez társítottam, és így megszületett a git shell parancsfájl. Elég vicces a munkatempóm ennél a kódnál, minden sorra pontosan egy nap jut. Három nap keresgéléssel, és windows script hosttal történő szenvedéssel jutottam el eddig, de azt hiszem megérte... :-)

Fejlesztői környezet kialakítása: IIS7 + PHP + MySQL

A következőkben az általam használt fejlesztői környezet kialakításáról lesz szó Windows operációs rendszer alatt. A fejlesztői környezet kialakításához szükség lesz rendszergazdai jogosultságra, enélkül bele se kezdjünk. A fejlesztéshez NetBeans IDE-t használunk majd, a http szerver a Windows-ba épített Internet Information Services lesz, az adatbázist pedig a MySQL Workbench fogja kezelni. A fejlesztői környezet kialakítását két részre oszthatjuk: egyrészt fel kell telepíteni a szervert, másrészt létre kell hozni rajta egy vagy több új projektet. Természetesen ezek a részek sok lépésből állnak, a következőkben ezekről a lépésekről lesz szó.

Szerver telepítése
A szerver telepítéséhez először létre kell hoznunk a mappaszerkezetet, ami majd az adatokat fogja tárolni. Ez nagyon egyszerű, válasszunk egy mappát, ahol az adatokat szeretnénk tárolni, ez nálam a: D:\creation\software developer. Ebben a mappában hozzuk létre a databases mappát az adatbázisoknak és a projects mappát a projekteknek. Ennyi. :-)

Alkalmazások telepítése
Ahhoz, hogy működjön a szerverünk, illetve tudjunk fejleszteni szükség lesz néhány alkalmazásra, kezdjük ezek telepítésével.

NetBeans telepítése
A NetBeans-hez szükség van java-ra, szóval ha még nincs fent a gépünkön, akkor töltsük le a java.com-ról és telepítsük. Ezek után szedjük le a NetBeans IDE legfrissebb verzióját Windows-hoz a projekt letöltési oldaláról, majd telepítsük azt. Lehetőleg azt a változatot válasszuk ki, ami alkalmas PHP kód szerkesztéséhez:

A NetBeans-hez érdemes feltenni a Git plugint, vagy valamelyik másik verziókezelő plugin-jét, kinek mi a szimpatikus. Ezt a Tools\Plugins alatt tehetjük meg.


IIS telepítése és konfigurálása
Az IIS alap esetben a Windows-al jár, és kikapcsolt állapotban van. Ha ez mégsem lenne így, akkor a telepítéséhez szükség lesz a Microsoft Web Platform Installer-re. Ebben sajnos nem tudok többet segíteni, nálam Windows 7 Ultimate alatt csak be kell kapcsolni a szolgáltatást. Ez az aktiváció a következőképp zajlik:
  1. Menjünk a Vezérlőpult\Programok  szekcióba, és válasszuk ki a Windows-szolgáltatások be- és kikapcsolását.
  2. Keressük meg az Internet Information Services illetve a Internet Information Services üzemeltethető webmagja részeket, és pipáljuk ki őket.
  3. A PHP fastCGI módban történő futtatásához még szükség lesz az Internet Information Services\Webszolgáltatások\Alkalmazásfejlesztési szolgáltatások\CGI bekapcsolására is.
Ha jól csináltuk, akkor valami ilyesmit kell, hogy lássunk:

A szervert az IIS Manager-rel lehet beállítani, amelyet a C:\Windows\System32\inetsrv\InetMgr.exe alatt találunk. Hozzunk létre egy parancsikont az asztalon ehhez az alkalmazáshoz, majd indítsuk el azt. Amit jelenleg benne találunk az a localhost-hoz tartozó DefaultAppPool és a DefaultWebSite. Az Application Pool alkalmazások gyűjteménye, amelyeket az adott Pool-t használó oldalak tudnak igénybe venni. Minden új Application Pool örökli a DefaultAppPool tulajdonságait. Szóval ha létrehozunk egy PHP feldolgozót ebben a Pool-ban, akkor az hatással lesz az összes többire. Ezért NE TEGYÜK. Próbáljuk meg inkább kitakarítani ezt a Pool-t, amennyire csak lehet, hogy a lehető legkevesebb hatása legyen a későbbiekre. A továbbiakban az a terv, hogy minden egyes WebSite külön Application Pool-t fog használni külön PHP feldolgozóval. Ezzel a felállással a PHP verziója és beállításai tetszés szerint módosíthatóak minden projektnél.

Tegyünk fel még két kiterjesztést az IIS-hez:
  1. PHP Manager for IIS - a php.ini beállítását segíti
  2. URL Rewrite Module - a .htaccess-hez hasonló  web.config fájl írását segíti
 Ezekről még szó lesz a későbbiekben.

MySQL telepítése és konfigurálása
A MySQL telepítéséhez először töltsük le az aktuális telepítőt majd indítsuk el azt. Válasszuk ki a custom setup-ot, és ott az úrvonalaknál állítsuk be a Server data files helyét databases\mysql-re.

Lépjünk tovább, pipájuk ki a launch config wizard checkbox-ot, és lépjünk tovább. A következő lépésekben konfiguráljuk a MySQL szervert:
  1. Detailed Configuration kiválasztása
  2. Developer Machine kiválasztása
  3. Multifunctional Database kiválasztása
  4. InnoDB Tablespace Settings: databases\mysql\innodb
  5. Decision Support (DSS) / OLAP kiválasztása
  6. Enable TCP/IP Networking bejelölése, port: 3306; Strict mode bejelölése
  7. Manual Selected Default Character Set / Collation kiválasztása, charset: utf8
  8. Install as Windows Service kiválasztása, nevezzük el aminek tetszik
  9. Modify Security Settings, állítsuk be a jelszót
  10. Finish
Ezek után Windows Service-ként futnia kell a MySQL szervernek, viszont jelenleg nem tudjuk GUI-n keresztül elérni azt. Ehhez telepítenünk kell a MySQL Workbench-et.

A Workbench telepítéséhez (legalábbis a jelen verziónál) szükség lesz a következőkre:
Ha ezek megvannak, akkor szedjük le az aktuális telepítőt és indítsuk el azt. Ha megvagyunk a telepítéssel, akkor indítsuk el az alkalmazást, és adjunk hozzá egy kapcsolatot.

Ha ezzel megvagyunk dupla kattintással tesztelhetjük, hogy fut e vagy akár úgy is, hogy az adminisztrációs részhez hozzá adunk egy új szerver példányt, és elindítjuk az adminisztrációs modult.

Ezzel készen vagyunk a szükséges szoftverek telepítésével, most nézzük meg hogyan tudunk létrehozni projekteket.

Projektek létrehozása
A projektjeink a projects mappában kapnak helyet, itt minden projektnek van egy-egy almappája. Hozzuk létre a test project mappát hasonló nevű almappákkal, mint ami az alábbi ábrán látható:
A document root-ban kapnak helyet a php fájljaink, valamint a .htaccess és a web.config fájlok, a logs-ban a log fájlok, a sessions-ben a munkamenetek fájljai, az upload-ban a fájlfeltöltő űrlapokhoz küldött fájlok kapnak helyet ideiglenesen, a php-x.x.x-ben pedig a felhasznált php verzió.


Projekt regisztrálása a hosts fájlban
A hosts fájlhoz még nem nyúltunk ezelőtt. Ez a C:\Windows\System32\drivers\etc\hosts útvonalon érhető el, a módosításához adminisztrátori jog szükséges. A legegyszerűbb a kezeléséhez, ha NetBeans-ben hozzáadjuk a Favourites-hez, így nem kell minden egyes alkalommal kikeresni, amikor módosítani akarjuk. Ehhez futtassuk a NetBeans-t rendszergazdaként (jobb gomb \ futtatás rendszergazdaként), válasszuk ki jobb oldalt a Favourites fület (vagy a Windows\Favourites menüpontot), majd jobb klikk, és kattintsunk a megjelenő Add to Favourites feliratra. Keressük ki a hosts fájlt, és adjuk hozzá. Ezek után mindig megtaláljuk majd a Favourites-ben ezt a fájlt.

Most nyissuk meg a hosts fájlt (rendszergazdaként), és adjuk hozzá a következő sort:
127.0.0.1 test.project.loc
majd mentsük azt. Ezzel a http://test.project.loc url-t az IIS szerverünkhöz irányítottuk.

Projekt hozzáadása az IIS szerveren
Persze ahhoz, hogy valami tartalmat is lássunk ezen az url-en be kell állítanunk az IIS szerverünket. Ehhez indítsuk el az IIS manager-t.


Ahhoz, hogy minden egyes projektnek egyedi PHP verziója lehessen, és ezeket egymástól függetlenül tudjuk konfigurálni szükséges az, hogy minden Webhelyhez (WebSite) külön Alkalmazáskészlet (AppPool) tartozzon. Először tehát adjunk hozzá egy új alkalmazáskészletet. Ezt az alkalmazáskészletek\alkalmazáskészlet hozzáadása alatt tehetjük meg.
Nevezzük el az alkalmazáskészletet, nálam a test project php 5.3.8 nevet kapta. Így a későbbiekben egyszerűbb lesz majd új php verziót feltenni, egyszerűen csak alkalmazáskészletet kell váltani. (A másik lehetőség erre a modultársítás megváltoztatása.)


Ha megvan az alkalmazáskészletünk, akkor adjuk hozzá a webhelyet a rendszerhez. Ehhez menjünk a Helyek\Webhely hozzáadása pontra, majd töltsük ki az űrlapot. Fontos, hogy kijelöljük az imént létrehozott alkalmazáskészletet. Ha nem hoztunk létre alkalmazáskészletet, akkor az alapbeállításokkal automatikusan létrejön egy ugyanolyan néven, mint amilyenen a projektünk van.

A fizikai elérési útnál a document root-ot adjuk meg, az állomásnévnek pedig állítsuk be a test.project.loc-ot. Ha most elindítjuk a webhelyet, akkor látnunk kell utána a böngészőnkben a http://test.project.loc alatt a document root-ot. Tegyünk be egy index.html-t, és próbáljuk ki.


Php telepítése a projekthez
Ha használni szeretnénk a php-t a projektünknél, akkor először le kell szednünk a megfelelő php verziót. Csomagoljuk ki a php-x.x.x mappába.

Ezek után be kell állítanunk a szervert, hogy használja a php-t az ilyen kiterjesztésű fájlokhoz. Ehhez indítsuk el az IIS Manager-t. Válasszuk ki a weboldalt, majd a Kezelőtársítások\Modultársítás hozzáadása alatt rendeljük hozzá a *.php-hez a php feldolgozót.

 Ehhez adjuk meg a Kérelem elérési útja mezőben a *.php-t, a Modul-nál válasszuk ki a FastCgiModule opciót, a végrehajtható fájlnál pedig a php-x.x.x\php-cgi.exe-t. Végül nevezzük el a modult. (Ha esetleg már létezik öröklött modul az ApplicationPool-ban, akkor azt mindenképpen töröljük, mert nem fogjuk tudni társítani hozzá az aktuális projekt PHP feldolgozóját. Hiába változtatjuk meg benne az elérési utat, mivel öröklött újra visszaáll majd a korábbi értékre.)

Ezzel még nincs vége a történetnek, a php-t konfigurálnunk kell ahhoz, hogy fastCGI módban megfelelően fusson, illetve be kell állítanunk, hogy milyen mappákat használhat, és hozzá kell adnunk a kiterjesztéseket. Ehhez nevezzük át az egyik php.ini mintát a php-x.x.x-ben, hogy legyen ini fájlunk, majd az IIS Managernél válasszuk ki a weboldalt, és menjünk a PHP Manager-re. Menjünk a Manage all settings-re, majd jobb oldalt az Open php.ini-re, és másoljuk be a következő kódot az ini fájl végére:
[Pathes]
extension_dir = "ext"
error_log = "..\logs\error.log"
doc_root = "..\document root"
session.save_path = "..\sessions"
upload_tmp_dir = "..\upload"
include_path = "..\document root"

[FastCGI]
cgi.force_redirect = 0
cgi.fix_pathinfo = 1
fastcgi.impersonate = 1
fastcgi.logging = 0

[Timezone]
date.timezone = "Europe/Budapest"

[Extensions]
extension=php_mbstring.dll
extension=php_pdo.dll
extension=php_pdo_mysql.dll
extension=php_mysql.dll
extension=php_mysqli.dll
extension=php_gd2.dll

Erősen ajánlott a  php-x.x.x-hez viszonyított relatív útvonalakat megadni az ini fájlban, mert így a beállításokat újra fel lehet használni. Ezután indítsuk újra az IIS-t, hogy érvénybe lépjenek a beállítások. Ezt a Kezdőlap\újraindítás-nál tehetjük meg.

Készen vagyunk a projekt konfigurálásával, már csak a tesztelés maradt. Hozzunk létre új php projektet a NetBeans-el a document root-ban, és teszteljük php kóddal, hogy minden megfelelően működik e. Ha mod rewrite-ot szeretnénk használni, és az éles környezet Apache szerveren van, akkor az Url Rewrite kiterjesztés segítségével importálhatjuk a .htaccess fájlt, majd generálhatunk ezek alapján egy tartalmilag megegyező web.config fájlt.

Az összes további projekt hozzáadása ugyanígy zajlik. Ezzel tehát végére értünk a fejlesztői környezet kialakításának. Az itt bemutatott módszer tökéletesen megfelel webfejlesztéshez, az éles környezet beállítását és felügyeletét meg szerintem jobb, ha szakemberre bízza mindenki. Nem régóta használom az IIS-t, de ez alatt a rövid idő alatt is nagyon pozitív véleményem alakult ki róla (előtte WampServer-t használtam itthonra, de csak nyűg volt vele). Szeretem, ha valamit GUI-val be lehet állítani, és nem kell állandóan konfig fájlokban turkálni, meg parancssorozni. Azt hiszem ezzel nem vagyok egyedül, remélem, hogy sokatoknak hasznos volt ez a cikk.

Webalkalmazások felépítése és az absztrakciós szintek

Ebben a cikkben a webalkalmazások céljáról és általános felépítéséről lesz szó, majd kicsit foglalkozunk az absztrakciós szintekkel és a clean code-al.

Először nézzük meg, hogy a webalkalmazásokban hogyan zajlik egy-egy kérés feldolgozása. Ennek szemléltetésére csináltam egy szép színes ábrát:
1. ábra: Webalkalmazás felépítése
(PHP esetében a Bootstrap is beleszól a kérés kezelésébe)

Színek jelentése:
  • lila - felhasználó (magas absztrakciós szint)
  • zöld - erőforrások (alacsony absztrakciós szint)
  • kék - kérés az alkalmazás felé (csökkenő absztrakciós szint)
  • piros - válasz a felhasználó felé (növekvő absztrakciós szint)



Az ábrán világosan látszik, hogy egy a webalkalmazás igazi célja, hogy a felhasználók és az erőforrások között kapcsolatot teremtsen. Így persze indirekt módon lehetőség van az erőforrásokon keresztül az egyes felhasználók között is kapcsolatot teremteni. Ez történik például akkor, amikor az ügyfél felad egy rendelést a webshopon keresztül, és az megjelenik az eladónál.
 
Természetesen a felhasználók és az erőforrások nem ugyanazt a nyelvet beszélik. A felhasználók kérései írásban megfogalmazhatóak: például: "kész vagyok a vásárlással, fizetni szeretnék", az erőforrások válasza erre meg csupa nulla és egyes. Ezt a kis kommunikációs zavart hivatott feloldani a számítástechnika. A beszélt nyelvet magas absztrakciós szintűnek nevezzük, a számítógépek nyelvét pedig alacsony absztrakciós szintűnek. A felhasználók kéréseit tehát alacsonyabb absztrakciós szintre kell transzformálni, az erőforrások válaszát pedig magasabb absztrakciós szintre, hogy mindkét fél megértse egymást. Ezt a transzformációt a böngésző, a webalkalmazás, és a programnyelvek végzik el.

Jelen esetben a webalkalmazásokkal foglalkozunk, tehát nézzük meg, hogy náluk milyen transzformációs lépések vannak a kéréseknél és a válaszoknál. Ha újra megnézzük az ábrát, látszik, hogy a szerver oldalon öt nagy felelősségi kört különíthetünk el a kérések feldolgozásával kapcsolatban:
  1. Bootstrap - alkalmazás előkészítése a kérések fogadására
  2. Routing - kérések elosztása az url és a jogosultságok alapján
  3. Input validation - kérések helyességének ellenőrzése
  4. Business logic - erőforrások írása és olvasása
  5. Output creation - weblap generálás az erőforrásoktól kapott válasz alapján

Itt kell megemlítenem, hogy a kódnak ugyanúgy van absztrakciós szintje. Ha belegondolunk ez két dologból is nyilvánvalón következik. Az egyik, hogy a kód milyen absztrakciós szintű adatot transzformál, a másik, hogy a programozási nyelvnek, amin a kód íródik is van egy absztrakciós szintje. Ennek bizonyítására nézzük meg, hogy hogyan megy a fájlok olvasása java és assembly nyelveken.

java:
FileInputStream streamToTextFile = new FileInputStream("C:/Users/jakash3/ab.txt"); 

assembly:
xxxx:0100 jmp 012b
xxxx:0102 db "C:\Users\jakash3\ab.txt",00 ;filename to read from
xxxx:011A db 00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,24 ;'$' terminated 10 byte buffer
xxxx:012B mov ah,3d     ;Open file function
xxxx:012D mov al,00     ;Read-Only file access
xxxx:012F mov dx,0102   ;Points to filename
xxxx:0132 int 21        ;Do it
xxxx:0134 mov bx,ax     ;Move retrieved file handle into BX
xxxx:0136 mov ax,3f00   ;Read from file function
xxxx:0139 mov cx,10     ;Read the first 0x10 bytes of file
xxxx:013C mov dx,011a   ;Address of buffer to store bytes read
xxxx:013F int 21        ;Do it
xxxx:0141 mov ax,0900   ;Print string function
xxxx:0144 mov dx,011a   ;Points to '$' terminated string to print
xxxx:0147 int 21        ;Do it
xxxx:0149 mov ax,4c00   ;Exit function (AL=Errorlevel to return)
xxxx:014C int 21        ;Do it
xxxx:014E
-rcx
CX 0000
:004e
-n readfile.com
-w
Writing 0004E bytes
-q

A java egy kicsit ember közelibbnek tűnik... :-)

A kódunkban az absztrakciós szintet mi is tudjuk növelni. Ez nagyjából annyit jelent, hogy hogyan tegyük a kódunkat átláthatóbbá. Ez a Clean Code témaköre, aminek a részletes tárgyalása nem fér bele ennek a cikknek a kereteibe. Ami most fontos nekünk ezzel kapcsolatban, hogy a felelősségi köröket osztályok és azokon belül metódusok között kell felosztanunk, ezeknek pedig beszélő neveket kell adnunk. Így a nagyobb felelősségi körrel rendelkező osztályokban szereplő kódok lesznek a magasabb absztrakciós szinteken. Ezek az osztályok további osztályok között osztják fel a felelősségi körüket, és így tovább, ahogy az alábbi ábrán látható:
2. ábra: Felelősségi körök megoszlása osztályok és metódusok között
(az absztrakciós szint a lefelé csökken)
Az alacsony absztrakciós szinten lévő osztályok metódusai a programnyelv beépített elmeit használják fel a feladatuk ellátására. A kód tehát mindig a programnyelv feletti absztrakciós szinten van, az pedig a programnyelv sajátságaitól és tőlünk függ, hogy mennyire magasan.

A webalkalmazásaink kódját érdemes úgy kialakítanunk, hogy minél folyamatosabb legyen az átmenet a magasabbtól az alacsonyabb absztrakciós szintek felé. Ezt úgy érhetjük el, ha minél kisebb felelősségi köröket alakítunk ki egy-egy osztálynak, és azon belül egy-egy metódusnak. Így kis osztályaink lesznek, és rövid; néhány soros metódusaink lesznek. Ha ezeknek képesek vagyunk beszélő nevet adni, akkor pusztán az osztályok és metódusok neveiből meg tudjuk mondani, hogy mi a felelősségi köre az adott kódrészletnek, magának a kódnak az olvasásából pedig részletesen ki fog derülni, hogy az hogyan látja el a feladatát.

Ha már kész kódunk van, és azt szeretnénk refaktorálni (újraépíteni), akkor sem kell kétségbe esni, bármilyen rossz is a helyzet. A kód képes elmondani, hogy milyen absztrakciós szintre szeretne kerülni, nekünk csak meg kell hallgatnunk. Ha kódismétlődés van, akkor a kód azt mondja, hogy nem vagyok megfelelő absztrakciós szinten, tegyél át alacsonyabb, vagy magasabb szintre. Ha egy új blokk nyitását látjuk, akkor a blokkon belüli tartalom alacsonyabb absztrakciós szintre kívánkozik, szóval emeljük ki nyugodtan egy új metódusba. Ha egy osztályban túl hosszú a tulajdonságok listája, vagy túl sok a metódus, az azt jelenti, hogy a kód egy része új osztályba kívánkozik. Ha commenteznünk kell a kódot, akkor az azt jelenti, hogy nincsenek beszélő neveink, rossz a kód olvashatósága. És így tovább...

Most nézzük meg az öt nagy felelősségi körünket, hogy hogyan lehet őket felosztani az osztályok között. Ha PHP kódról van szó, akkor először fel kell építenünk a megfelelő környezetet ahhoz, hogy kezelni tudjuk a kérést. Ezért először a Bootstrap osztály egy példányához kerül a kérés.

A Bootstrap felelősségi köre: az alkalmazás előkészítése a kérések fogadására, kérések továbbadása a Routingnak. Az előkészítés gyakorlatilag az alkalmazás konfigurálását jelenti. Ezt is további lépésekre oszthatjuk fel. Először szükség van egy ClassLoader-re, ami betölti az osztályokat, amelyeket használunk. Utána be kell olvasni a konfig fájlokat a ConfigLoader-rel, majd ezek alapján fel kell építeni a környezetet, kapcsolódni kell az adatbázishoz (Database), el kell indítani a munkamenetet (Session), létre kell hozni magát a kérést reprezentáló objektumokat, aztán a  Distributor-t, és legvégül átadni neki a kérést.

A Routing felelősségi köre; hogy megmondja ki fogja kezelni a kéréseket. Ehhez a Distributor a neki megadott mintákra (Route) ellenőrzi az url-t, és ha egyezést talál, akkor megkérdezi az Auth-tól, hogy megvan e a felhasználónak a joga a Route-hoz tartozó Controller, és azon belül a megfelelő action meghívására. Ha nincs egyezés, vagy nincs meg a jogosultság, akkor a ControllerFactory a hibákat kezelő Controller-t példányosítja, ha azonban egyezést talál a Distributor, akkor az annak megfelelő Controller megkapja a kérést.

A Controller validálja a kérésben érkező adatokat, ehhez a Validator osztályt használja fel. A Validator kapcsolatba léphet a Model-el, bizonyos esetekben. Ilyen eset például: ha regisztrációkor meg kell nézni, hogy létezik e már az email cím az adatbázisban. Attól függően, hogy a Validator mit mond a Controller a megfelelő Model és View osztályokat példányosítja, majd az esetleges transzformációk után továbbadja a kérést nekik.

A Business logic felelősségi köre: az erőforrások írása és olvasása, ehhez azonban még át kell alakítania a megfelelő formára a hozzá érkező kérést. A megfelelő Model osztály megkapja a kérést, és átalakítja azt például a relációs adatbázisok által beszélt SQL nyelvre. Ehhez többek között felhasználhat ORM rendszereket, melyek szintén elég sok osztályból állnak... A Model az adatbázistól kapott adatokat megfelelő formára hozza, majd válaszként visszaadja őket a hozzá kérést intéző objektumnak.

Az Output creation felelősségi köre: weblap generálása az erőforrásoktól kapott válasz alapján. Ehhez a View osztály megkapja a Model-től a kérésre érkező választ, és azokat további adatokkal egészíti ki, hogy az emészthető legyen a kliens böngészője számára. A View rengeteg féle választ képes generálni ugyanabból az adatból attól függően, hogy azt milyen formában akarjuk eljuttatni a felhasználóhoz. A skála a mozgóképtől egészen a HTML oldalig terjed. Ha csak a HTML oldalt nézzük, akkor azon belül is elkülöníthetünk részeket. A weblapoknak általában van egy alap elrendezésük, aminek a HTML kódják Layout osztályok használatával tudjuk legenerálni. Ebbe a vázba különböző tartalmakat tehetünk bele, ezeket a Panel osztályok generálják. Többek között betehetünk űrlapot is mondjuk a FormPanel segítségével. A HTML kódok generálásához ezek az osztályok sablonokat használhatnak fel. A sablonokat a Template osztály kezeli, ami szintén több osztályt felhasznál...

Végül a válasz megfelelő formában visszajut a kliens böngészőjéhez, a böngésző pedig megjeleníti azt a felhasználó által emészthető formában.

Azt hiszem ennek a néhány osztálynak a felsorolása is bőven elég volt ahhoz, hogy érzékeltessem, hogy mennyire nagyok ezek a felelősségi körök, és mennyire sok osztály között kell felosztani őket ahhoz, hogy átlátható kódot kapjunk...

Ebben a cikkben tehát megismerkedtünk az absztrakciós szint fogalmával, a webalkalmazások céljával, és alapvető felépítésével, illetve azzal, hogy hogyan növelhetjük a kódunk absztrakciós szintjét. Az hiszem már az assembly vs. java fájl olvasásos példából is látszott, hogy miért éri meg minél magasabb absztrakciós szintű kódot írni, azonban a következő cikkben erről egy kicsit részletesebben is szó lesz, illetve példákon keresztül arról is, hogy ezt hogyan tudjuk megvalósítani.

Könyvajánló - Robert C. Martin

Szeretnék írni hamarosan egy clean code-ról szóló cikket, viszont előtte még van pár könyv, amit mindenképp elolvasok, hogy növeljem a tudásom a témában.

Ez egy alapmű Robert C. Martin tollából, a clean code elvét mutatja be. Ennek a könyvnek a legfontosabb alapvetése, hogy mi programozók szerzők vagyunk, az olvasóink pedig azok az emberek, akik a mi kódunkat felhasználják, átalakítják. Akár még az is előfordulhat, hogy mi térünk vissza ugyanahhoz a kódhoz huzamosabb idő elteltével. Ezért nagyon fontos, hogy az általunk írt kód átlátható legyen, és pusztán az osztály-, metódus- és változónevek áttekintésével meg tudjuk mondani, hogy mit csinál a program, aminek a forrását olvassuk. A könyv számos olyan technikát tartalmaz, melyek nagy segítségünkre lehetnek az átláthatóság fenntartásában.


Szitén egy Robert C. Martin könyv. Egyelőre kevesebbet tudok róla, mint a Clean Code című könyvéről, mivel még nem kezdtem bele az olvasásába. Ez a könyv számomra azért érdekes, mert elég keveset tudok arról, amit úgy neveznek, hogy programming principles. A tervezési mintákkal már tisztában vagyok, viszont ezek közül a tervezési alapelvek közül csak a single responsibility az, amit ismerek, és próbálok átültetni a gyakorlatba. Érdemes ezekkel az alapelvekkel megismerkedni, mert a későbbiekben, ha jobban ráfekszik az ember a TDD-re, akkor biztosan nagy hasznuk lesz.

Syntax highlight test

Gondoltam tesztelem kicsit a syntax highlight-ot mielőtt nekikezdek.
(function ()
{
 function test()
 {
  alert("Highlight this!");
 }
 test();
})();
Itt található egy gyönyörű szép leírás arról, hogy hogyan kell blogspot-on beüzemelni a kódszínezőt...