2005-11-11

Ajaxos fejtegetés

Kezdetben volt a HTML, ami az SGML egy változata. A céljának -hogy olvasható legyen a gazdag dokumentumok forrása- megfelelt, viszont ahogy rájöttek a programozók a fastruktúra előnyeire kijött az XML -az SGML egy szigorúbb válfaja- és a HTML-nek is változnia kellett. Ebből lett az XHTML. Az XHTML-t könnyű kezelni a sok XML eszköz miatt. Dinamikusan lehet szerveroldalon DOM-ot összerakni, parse-olni is könnyebb, stb stb. Olvashatóbb is egyébként.

Ezzel párhuzamosan fejlődött a kliensoldali scriptelés is. Az XHTML elterjedésével a script-ek is egyre merészebben módosítgatják a DOM-ot és az XmlHttpRequest megjelenésével már a lap újratöltése nélkül is tudnak kliens-szerverinterakciót kezdeményezni ami esetleg a lap (DOM) csak egy részének megváltoztatását eredményezi.

Abszurd az eset, mert az először letöltött dokumentumnak esetenként látszólag egyáltalán nincs köze a browserben ténylegesen megjelenő oldalhoz. Az oldal forrása pedig már nem igazán átlátható. Tehát az (X)HTML szerepe teljesen megváltozott. Az egyszerű szövegszerkesztő már rég nem elég egy oldal szerkesztéséhez és most az XmlHttpRequest -és így a fokozott kliens-szerver kooperáció- megjelenésével a mostani kérés-válasz modellre épülő eszközök (asp.net, jsp, szervletek, php) túl primitívek a feladat megoldásához.

Éppen ezért fogott neki több szervezet is a különféle AJAX frameworkok fejlesztésének. Na majd meglátjuk melyik a "jobbik"...

2005-11-04

Active Record antipattern

Update 2009.05.22: Szerencsére ma már vannak jól kialakult perzisztencia framework-ök (a JPA-ról nem is beszélve) és a kultúrált programozók DAO-kkal dolgoznak, de nemrég találkoztam olyan emberrel aki éles projektben komolyan használni akarta ezt a design pattern-t. Ráadásul egy másik postban más okból is linkeltem erre a rövid kis agymenésre, szóval kicsit megcizellálom.

Szóval az Active Record design pattern dióhéjban arra épül, hogy az objektum maga tudja, hogyan kell őt beolvasni vagy legalábbis kimenteni valami adatbázisba. Tehát van save metódusa, ilyesmik.

Első probléma, hogy rögtön kell az objektumba injektálni valami adatbázisközeli logikát, ami másrészről nem jó helyen van ott, hiszen fölösleges függőséget hoz be a domain modell entitásaiba. Ha nem elég flexibilisre van megcsinálva ez a logika akkor a hordozhatóságnak annyi, pl. nem lehet kicserélni alatta a perzisztencia réteget. Van erre két megoldás: egyik hogy örököljük ősosztályból a logikát, nade ekkor is felülről (még rosszabb) betámadnak az implementációs részletek a domain modellbe. Ebben az esetben ráadásul el kell lőni az egyetlen öröklési lehetőséget (Java, C#) az implementációs részletek miatt. Na és mi van ha még a domain modell miatt is kéne örökölni? Pech. Másik megoldás a logika delegálása. Igen, ez működhet csak ügyelni kell rá hogy az objektumokhoz hozzá legyen cuppantva a logika ami kimenti őket.

Második probléma, hogy ha ezeket az objektumokat neadjisten másra is használni kell, felbugyoghatnak a szervíz rétegből a GUI logikába, félreeső modulokba. Például valaki véletlenül mond ott egy delete-et és szevasz aktív rekord - automatikusan mindenki számára publikálja a műveleteket. Egy jól leválasztott szervíz réteg esetén jól meg lehet határozni, hogy melyik modul milyen interfészt kap meg.

Hozhatnék még fel ilyen kérdéseket, hogy vajon minden adatbázis rekordhoz van egy aktív rekordunk a memóriában? Pazarlás. Minek? Stb.

A régi posthoz még annyi bevezető, hogy néha (ez már WTF kategória) a konstruktor meghívásával generálják az adatbázis rekordot, tehát a new Person('pcjuzer') valóban adatbázis műveletet von maga után. Csakhogy...

Innen pedig a régi post:

A konstruktornak van egy olyan tulajdonsága, hogy a lefutása után csakis egy újonnan inicializált objektum referenciáját tudja visszaadni. Tehát sem null-t, sem a hívás előtt létező objektum referenciáját nem tudja visszaadni.

Bevett gyakorlat, hogy egy objektumpéldányhoz egy adatbázis rekord tartozik. (Egyébként nagyon okos neve van a megoldásnak: Active Record. Annyira okos, hogy még céget is elneveztek róla.) Ha ezt az objektumpéldányt a konstruktorral akarjuk kiolvasni az adatbázisból, akkor több konstruktorhívás több példányt fog eredményezni ami ugyanarra a rekordra mutat. Ez egyrészt erőforrászabáló másrészt inkonzisztens állapotot lehet előidézni vele, ha a két példányt megváltoztatjuk és ezután visszaírjuk az adatbázisba.

Ehelyett factory metódust vagy osztályt kell használni, ami egy pool-ból kiveszi a már egyszer feltöltött rekordok objektumait. Legalábbis az a.r. design pattern-en belül.

2005-09-08

res.exe

Van nekem egy ősrégi CF kártyás DIVA mp3 játékosom ami sokáig kitűnően működött, mostanában viszont (jó sok minden változott a gépen, szervíznyirbálás is volt meg minden) nem ismerte fel a windows, csomószor fagyizott is. Másik USB-s eszközöket felismert, csak a DIVA-val volt gondja. Más gépen pedig szintén működött a DIVA, úgyhogy egyértelmű hogy az én gépemen volt a szoftveres hiba.

Próbálgattam visszaindítgatni a service-ket, párszor drivert installálni, jó sok idő elment, de az üdvözítő megoldást az adta, hogy a task managerben kilőttem az automatikusan induló res.exe nevű programot, ami akkor telepedett a gépemre amikor installáltam a külső USB-s HDD keretet.

Szemét res.exe.

(2007.05.05) A történet nem ért véget. Azóta jó sok pendrive járt a gépben, biztos jó sok driver installálódott. Mostanában nagy tömegű adatot akartam rámásolni a külső USB-s HDD-re és irtózatosan lassan ment a dolog. Az első néhány perc rendben ment, de aztán a másolás nagyon lelassult (párszáz byte / másodperc), a processzor kihasználtság pedig felugrott 100% közelébe. A task-ot nem is tudtam rendesen kilőni, vagy miután kilőttem, a processzorkihasználtság magas maradt. A megoldást ismét az adta, hogy lelőttem a res.exe programot. Ezután a másolás ismét a megszokott tempóban működik.

Még egy gondolat az USB-s HDD kerettel kapcsolatban: elvileg előnyösebb FireWire-t venni, mert a FW meghajtásához nem kell szoftveres segítség, az USB pedig lefogja némileg a processzort. Eredetileg én is FW-set akartam venni, csak vagy nem volt vagy ilyet sikerült adniuk.

2005-08-25

Music XP

Mostanában az XP agyalapi működésének tanulmányozásával ütöm el az időt. Az a helyzet hogy van egy TASCAM US-122 USB-s audio (ASIO, 2 XLR mikibemenet fantomtáppal, direkt out, 24 bit, midi in/out, szóval valamivel több mint egy soundblaster) interfészem amit Cubase mellett hangkártyának használok és az utóbbi időben (mióta az SP2-t felraktam) néha ugrik a visszajátszás ami felvétel közben igencsak használhatatlanná teszi a rendszert, úgyhogy most nézegetem a fórumokat az www.absolute.hu -n és a tippeket a www.musicxp.net -en az XP turbózásával kapcsolatban. Majd meglátjuk mi alakul ki. Ha kiirtom a fél service parkot akkor kezd jobb lenni a dolog és kevesebbszer ugrik, de még ki kell kísérletezni.

Melóban meg aspx-es webkontrolokkal, xsl trafóval, transact-sql tárolt eljárásokkal foglalkozom. Még jó hogy javasemberként regeltem be...

2005-08-09

C# dátumkezelés

A dátumokkal mindig van valami zűr, úgyhogy ha valamit megtudok ide beírom, és ha újra kell akkor itt megnézem.

A DateTime először is value típus úgyhogy nem lehet neki null-t beállítani. Ezt legegyszerűbben úgy szokták kiküszöbölni hogy DateTime.MinValue-t állítanak be neki ami 1970.01.01-es dátumnak felel meg. Nem kell mondanom hogy ennek mi a hátránya.

Dátumformázás C#-ban:


string s = "2005-03-28 06:50";
try {
//see DateTimeFormatInfo for patterns
DateTime d = DateTime.ParseExact(s, "yyyy-MM-dd HH:mm", null);
Console.WriteLine(d.ToString("yyyyMMddHHmm"));
} catch(FormatException ex) {
Console.WriteLine("wrong date format.");
}

A DateTime value típus tárolja ugye a dátumot. A DateTime.Now adja rögtön vissza az aktuális dátumot, a DateTime Ticks propertyje pedig 100 nanosecundom "pontossággal" az óraütések számát. (Értsd.: 1 tick = 100 nanosec.) Ha a ticket megszorzom 10000-rel, akkor jön ki a milliszekundom. Loggolásnál hasznos.

Ha a mai nap kezdetére vagyunk kíváncsiak, akkor hasznos a:
now.Subtract(now.TimeOfDay);

Update 2008.07.23: Cikk a softwareonline-on a témában.