Archive for the ‘Architektúra’ Category

Service locator pattern design kérdés

Monday, February 3rd, 2014

Sokak szerint Service Locator pattern antipattern.
Ok, ha egy ezer soros osztályban (ez már önmagában code smell) tucatnyi metódusban el vannak dugva service locator hívások, akkor a kódot olvasva nehéz meghatározni, milyen függőségei vannak, így nehéz tesztelni is (tudjuk, a kódot embereknek írjuk, nem a compilernek, az megérti a dzsuvát is). Ebben a helyzetben a konstruktor injectionnel nyilvánvalóan be lehet küldeni a függőségeket, az osztály elejét elolvasta azonnal szembeötlik, miket kell kifakelni, ha tesztelni akarjuk.
Na, de mi van a facade vagy controller jellegű osztályokkal? Ezek sok tucatnyi más osztállyal működnek együtt, pont ez a feladatuk, hogy a külvilágnak ne kelljen a belső részleteteket megérteni. Az ilyen osztályoknak tucatnyi függősége van, amelyeket viszont -szerintem- értelmetlen lenne konstrukciós időben létrehozni, főleg, ha jelentős részét nem is fogják használni a közeljövőben. Ilyenkor tudomásom szerint nem nagyon marad más, mint hogy a hívott metódusokban service locatorral létrehozni a függőséget, és belehívni.
Mindezt csak azért vetem fel, mert rossz érzésem van, amikor leírom egy kódban, hogy Di.Resolve(), de az előbbi érvelés alapján meg tudom indokolni, mikor mégis csak jogos a service locator.
Csak én csinálok ebből lelkiismereti kérdést?

REST evolúció

Friday, February 1st, 2013

Érdekes írás Fowlertől, hogyan alakult ki a REST, ami ma már inkább Hypermedia API. Nekem a vége kicsit fura, amikor már kezd beszivárogni valami interfészleírás-szerű valami, így pont az eddig egyszerűség kezd elveszni.

Test Driven Development – I like it

Wednesday, July 25th, 2012

Egyre több dolgot TDD módon írok meg. Ami szembetűnő a korábbi, először implementálok aztán ha van rá idő írok hozzá tesztet (nem fogok) módszerhez az a következő:
-Sokkal kevesebbet, nagyon sokszor egyáltalán nem debugolok. Ez eszement sok időt spóroló tevékenység, gyűlölöm, amikor 2-3 percet is nyomkodok, mire eljutok a betegnek vélt ponthoz a debuggerben. Ott aztán sokszor kilép a debugger (pont timeoutolt a web worker process), release kód miatt nem mutat változókat, továbbléptetem, aztán kezdhetem elölről (lehet mozgatni a current pointert, de ha már okoztunk mellékhatásokat hiába megyünk vissza), stb. Szeretem az advanced debuggung témát, de utálom az időt vele feleslegesen tölteni.
-A GUI-t alig indítom el, ezáltal megint nagyon sok időt takarítok meg.
-Az implementált dolgaim azonnal mennek, amikor a GUI-t is elindítom, már csak élvezni kell az eredményt.
-Hamarabb készen vagyok a feladattal. Tudom, ezt nem lehet objektíven mérni, mert nincs mihez viszonyítani. De az első két pont miatt érzésre annyi időt megtakarítunk, ami felülmúlja a tesztekre szánt időt.

Igazából a TDD nem is a tesztelésről szól. Ez komplexitás és félelem kezelés. Arról szól, hogyan implementáljuk egy bonyolult feladatot sok kicsit változaton keresztül úgy, hogy ne őrüljünk bele, ne legyen sok kudarcunk. Az már csak egy plusz, hogy sokkal jobb lesz a kódminőség.

SP vs. OR mapper

Monday, July 23rd, 2012

Az előző bejegyzésből a kommentek alapján lehet az jött le, hogy én minden dolgot OR mapperrel valósítanék meg. Csudákat, szó sincs erről.

Nézzünk egy példát. Az előző architektúra tervemben (ami prototípus majd framework is lett, nem csak terv) NHibernate és Oracle alapon készült az app. Sok más mellett tetszőleges országban használható emberneveket kellett tudni tárolni, ezért a db terv elég általános lett. Person-PersonName-PersonNamePart, ez a 3 tábla volt a fő váz. PersonNameType, PersonNamePartType, ezek enum jellegű lookup táblák.
Egy lekérdezés célja visszaadni tetszőleges név komponens alapján a beteg nevét. Azaz a PersonNamePart tábla egy oszlopában kellett keresni, ez jól indexelhető, hatékony lekérdezés. Utána jött a mókásabb rész. A PersonNamePartból vissza kellett navigálni a PersonName-re, onnan a Personre, majd a megjelenítés miatt vissza le az összes PersonName-re és onnan tovább a PersonNamePartra.
Ezt a lekérdezést először megírtam P/L SQL-ben, hogy lássam, kb. mit akarok csinálni, ez mennyire hatékony, kell-e hozzá Cluster (nem clustered, ez oracle, ez teljesen más) index az IO csökkentésére, stb.
Amikor a lekérdezéssel elégedett voltam, elkezdtem átírni az NHibernate LINQ providerére. A célom az volt, hogy a query gondolkodásmódját pontosan visszatükrözze a LINQ query, így remélhetőleg a generált sql is hasonlóan hatékony lesz. Sajnos azonban a kísérlet kudarc volt. Az NHibernate LINQ providere egyszerűen nem implementálta amit én akartam (ha jól emlékszem Take(n) után Select). Megnéztem a forrását, ott volt egy nagy büdös throw new NotImplementedException().
Mi maradt? Sp, aminek a kimeneti joinolt sorait az NHibernate alakította vissza entitásokká (ez viszont nagyon ügyes része az NHibnek.)
Azaz a lekérdezés a lehető leghatékonyabb volt, de a végén mégis a domain modellel dolgoztam, ami végül szimpatikus hibrid lett, bár jobb lett volna tisztán LINQ-ban megírni.
Mi lett volna, hogy rendesen megírták volna a LINQ providert? Megnéztem volna a generált SQL-t, és ha az megfelelően hatékony lett volna, akkor maradt volna az.
Ha nincs rá különösebb okom, én szeretem a logikákat C#-ban írni. Az objektumorientáltság miatt jól lehet szervezni az összetettebb kódokat, sokkal jobban, mint a procedurális TSQL-ben.
Lehet memóriában cache-lni dolgokat, SQL Serveren belül nem nagyon. Az appszervereket sokkal könnyebb horizontálisan skálázni mint a DB-t. Magyarul egymás mellé berakni sok azonos szervert, még ha ez marhára nem is triviális, de legalább lehetséges. Emiatt a DB-ről terhelést levenni nem kell félnetek, mindenképpen üdvös tevékenység.
Viszont, ha az adatokhoz közel kell műveleteket végezni, akkor nem fogok feleslegesen átvinni nagyszámú sort az appszerverre. Ha egy gyakran futó kritikus tranzakció hossza fontos, akkor lehet spbe rakom. Ha sok sort érint a művelet nem hozom ki őket a dbből.

Próbálok pár példát konstruálni, illusztrálandó az előbbieket.

1. Be kell olvasni 100 sort egy táblából, lefuttatni valami összetett műveletet rajta, amely kb. 1000 sornyi programkódnak felel meg, majd az eredményt visszaírni egy másik táblába, amely kb. 20 sornyi insertet jelent. OR mapper. A bonyolult logika valószínűleg erősebb érv lesz, mint az, hogy 100 sort át kell vinni a dróton, illetve, hogy 2 roundtrippel jár a művelet. Mivel a logika C#-ban lesz, könnyű lesz teszteket írni rá (a db könnyen kifake-elhető), könnyebb lesz karbantartani, ha módosítani kell.
Ha esetleg az egésznek egy tranzakcióban kell lenni, és a round tripek ideje jelentősen nyújtja a tranzakciók futási idejét, ami miatt az esetleg szigorúbb izolációs szinten futó tranzakciók elkezdenek torlódni akkor, és csakis akkor kezdenék el filózni az spn. De ezt csak méréssel lehet eldönteni, mert az sp esetén meg valószínűleg a logika lesz lassabb, így lehet többet vesztünk, mint nyerünk.

2. Be kell olvasni 5 táblából 1 sort, ezek alapján dönteni, majd visszaírni 2 táblába 1-1 sort. Az alapeset ugye az, hogy megpróbáljuk OR mapperen keresztül megoldani a dolgot, majd belátni, hogy az elég hatékony-e, ha nem akkor áttérünk sp-re. NHibernate vagy EF Extension Pack Future-ökkel az 5 select valószínűleg kiadható 1 roundtrip alatt, ha nincs közöttük függőség. Ha van, akkor lehet, hogy join-nal vagy navigácós relációkon haladva még mindig megoldható 1 roundtrip alatt. Ha nem, akkor nem. A visszaírások normális OR mapper esetén 1 roundtrip alatt végrehajthatók (batching), így 2 roundtrip alatt megvan a feladat. Valószínűleg bőven belefér, marad az OR mapper.

3. Le kell törölni sok sort, ahol a DueDate nem mai dátum. Egyértelműen sp, semmi értelme OR mapperbe behúzni a törlendő sorokat, könnyedén megfogalmazható a feltétel egy sima SQL where-ben. Hozzáteszem, NHibbel lehet delete és update műveleteket is kiadni entitás fogalmak használatával, így annál ezt se spzném, a generált sql az lenne, ami kézzel beírnék az spbe, csak direkt sqlként. Akkor meg minek sp-zzek?

4. Be kell szúrni 500 sort, nagyon gyorsan, naponta sokszor. pl. laborgépek okádják magukból az eredményeket, ezeket kell eltárolni. Ez már érdekesebb kérdés. Első körben azt mondanánk, OR mapper erre nem való. Az első gondolatom az ilyenre valamilyen bulk copy megoldás lenne, pl. SQL Server esetén SqlBulkCopy osztállyal. De pl. Oracle esetén van un. Array Binding, amivel a bulk műveletekkel közel azonos teljesítményt lehet elérni, a bulk műveletek limitációi (nem lehet trigger a táblán, stb.) nélkül. Ami meglepő, hogy a NHibernate oracle esetén kihasználja az array bindingot, és nem csak egyszerűen batcheli a műveleteket, de array bindinggel küldi be. Emiatt veszett gyorsan tud beszúrni, így NHib esetén simán OR mappert használnék erre is. Egy konkrét mérésemben 10000 sor beszúrása így nézett ki Oracle-be (fejből mondom, de a nagyságrendek jól lesznek):
1. NHibernate identity id generator (othodox SQL Serveres gondolkodásmód): 52 sec
2. ADO.NET soronkénti insert: 12 sec
3. NHibernate hilo id generátorral: 2.7 sec
4. ADO.NET Array Bindinggal: 2.2 sec
5. Direct Path Loading: 2.1 sec

Mik a tanulságok ebből a mérésből?
A. Az identity alapú ID generálás megöli az insertek teljesítményét (1. és 2. példa alapján)
B. A sok roundtrip mindenképpen káros, emiatt lett lassú 2. is, mivel itt nem volt OR mapper overhead.
C. Az NHib elképesztően gyors volt (3. példa), csak 20%-kal lassabb volt, mint az Array Binding nyersen használva (2.2/2.7).
D. Az Array Binding eszement gyors, SQL Serveren a tábla típusú paraméterekkel lehet hasonlót elérni, de ehhez nem tudok OR mapper támogatást (mivel ehhez explicit kell fogadó kódot írni, az orához NEM).
E. A bulk copy mindenhol a leggyorsabb, de az oránál ez nagyon limitált, le is van írva, hogy arra gyúrnak, hogy az array binding legyen ugyanolyan gyors, így kiválthatja azt.

Azaz, ha megfelelően optimalizált az OR mapper adatelérése, akkor még olyan esetekben is használható, ahol első körben nem jutna az eszünkbe.

5. Két tábla között kell átmozgatni sorokat, egyszerű leképezések mentén. Sp, insert-select és delete, tranzakcióban.

6. Pessimistic Offline Lock pattern implementációban volt a következő. Meg kell nézni, létezik-e lock egy erőforrásra, ez egy egy szűrt select. Ha nem, akkor beszúrni egyet, ha igen, beszúrni egy várakozó sort. Mindezt serializable izolációs szinten, mivel meg kell akadályozni fantom sorok beszúrást a select és az insert között (orának is van ilyenje, bár nem lockol mint az Sql server alapban, hanem úgy működik, mint az RCSI az SQL servernél).
Érezhetően itt észnél kell lenni, mivel ha sokszor fut le a folyamat, akkor a serializable miatt lassú lehet a dolog. Design szempontból értelemszerűen az offline lockkal védeni kívánt dolgok lekérdezése NEM a serializable tranzakcióban volt. A védendő lekérdezés előbb lefut, majd utána jön a lock fogása, és ha sikerül, megkapja a kliens az eredményt, ha nem, akkor eldobjuk a lekérdezése eredményét. Ez pazarlás, ha ütközés van, de nem számítunk sok ütközésre. Ha egy tranzakcióban lenne a két feladat torlódás lenne, ha előbb a lock, aztán a művelet, akkor meg sikertelen művelet esetén (pl. secu beint) törölni kellene a lockot, de közben már lehet más vár rá…
Ezt a feladatot OR mapperrel írtam meg. Nem tudok pontos végrehajtási időt mondani, de ha jól emlékszem kb. 20 ms volt a teljes lock vizsgálat ideje. Ha serializable szinten egy erőforráson versengenének a folyamatok, akkor másodpercenként 50-nél többet nem tudna a szerver végrehajtani. Valójában azonban szórnak a lockolandó erőforrások, így a serializable nem fog jelentős torlódást okozni (megfelelő csak indexekkel persze).
Sokan szerintem ezt kapásból SP-ben írnák meg. Mit nyernénk vele? Mit akarunk minimalizálni? Az SQL szintű tranzakció idejét. A tranzakció kb. így nézne ki:
begin tran
select …
if () insert…
else másik insert…
commit

A kérdés, ezek ideje hogy aránylik a roundtripek által megnövelt időhöz? 3 roundtrip van, 1 select, 1 valamilyen insert és egy commit. Ha a roundtrip ideje mondjuk 3ms, akkor 9 ms a roundtrip overheadje. Ha az SQL műveletek kb. 10ms-ig tartottak, akkor kétszer olyan gyors lehet az sp-s megoldás. Azaz itt elgondolkodtató a dolog, de megint, én csak konkrét mérések alapján állnék neki átrefactorolni a megoldást spre, ilyen spekulatív úton nem. Hisz ha a roundtrip valójában csak 500 usec, akkor máris 1 napig felesleges dologgal múlattuk az időt.

7. Sok id alapján kell behozni pár száz sort. Lehetsége megoldás OR-mapper future queryvel, egy batchben, de ennek hátránya, hogy pl. SQL Servernél nem lehet 1-2 ezérnél több paramétert definiálni, így a generált sql nem lesz végrehajtható. Itt spt írtunk, amely oracle collection paraméterként vette át a kulcsok listáját, belül pedig joinoltunk az alaptáblához. SQL Servernél ezt tábla típusú paraméterrel csináltam volna meg. A bemenetet elegánsan át lehetett adni, mivel az NHibben lehet saját típust definiálni, így Guid tömb típus direkben átpasszolható volt az spbe.

Más. A már említett architektúrában volt sok olyan cross-cutting concern, amit db szinten implementálni véres lett volna. Például a WCF-ből kijövő objektum gráfot módosítani kellett, mivel sor (entitás) is mező (property) szintű ACL secu miatt meg kellett metszeni a kimenete fát (gráfot, mikor-mit), property-k értékét kimaszkolni, de közben feljegyezni a maszkoltakat, szöveget nyelvi fordítását beinjektálni a gráf tetszőleges helyére, tetszőleges entitást kiegészítő adatokat belerakni a fa megfelelő részére, be kellett küldeni minden tranzakció nyitása után egy user és tran azonosítót, offline lock információt, stb. Ezek nagyon komplex feladatok voltak, amelyeket ráadásul millisecundum nagyságrendű idő alatt kellett tudni megcsinálni tízezer elem feletti gráfokra is. Ezt én dbben nem tudtam volna megcsinálni, intenzív appszerver szintű cache-eléssel, illetve kihasználva a .NET adatstruktúráit sikerrel és elegánsan (központilag implementálva, mint az AOP-ban) megoldottuk.
Ha viszont ilyen mindent keresztülvágó követelményektől hemzseg a feladat, akkor ez ember kétszer is meggondolja, hogy kilépjen az entitások, a logikai modell világából, és elkezdjen spzni, mivel az spkre ráhúzni ezeket a megoldásokat nehézkes.
Szóval az OR mapper vs. sp kérdés igen komplex, nem lehet 2 perc alatt dönteni róla, és mindkettőnek megvan a helye, feladatonként egyesével kell eldönteni, melyiket használjuk.

Ártatlan kis 1 lapos lekérdezések

Friday, July 20th, 2012

Csalóka az adatbázis. Sokan félreértik, mire való, és a 90-es évek stílusában minden vackot rábíznak, ettől persze megfekszik szegény. A félreértés onnan ered, hogy az MS akkor azt mondta, spben kell megírni az üzleti logikát (mivel a VB használhatatlan volt, a C++ meg a legtöbb ember kezében csak bug gyártásra jó). A Delphi ezért élte a fénykorát.
Na szóval, amikor szegény dbre sok üzleti logikát bíznak, akkor mivel őbenne nem lehet a hagyományos módon cache-elni mint egy appszerveren, így az összes piszlicsáré, a büdös életben nem változik de legyen a dbben mert az jó adatot is táblákból kell kiolvasni. Pl. az enumok értékét, amit azért nem szoktunk megváltoztatni a dbben, mert ehhez úgyis a programozott enum értékeket is át kéne írni, ráadásul a kettőt egyidőben szinkronban.
Így aztán a tízmilliós vasú SQL Server olyan dolgokon dolgozik, ami nem az ő feladata. 1 lapolvasás nem a világ, és különben is memóriában vannak a pici táblák, nem jelent ez nagy terhelést.
Valódi cacheből, appszerveren felolvasni egy pl. egy stringet pár nanonsecundum.

Nézzük meg ezt SQL Serveren belülről:

declare @i int = 1000000, @a varchar(200)

while (@i > 0)
begin
	select @a = s.Value from Setting s where s.Name = 'TestSetting1';
	set @i-=1;
end

A Setting tábla két soros, és rendes voltam, raktam clustered indexet a Name oszlopra. 15mp-ig tart a ciklus, a select nélkül kevesebb, mint 1 mp (kb. 800 millisec).
Azaz a select általi kiolvasás kb. 15us, míg ugyanez az appszerveren nanosec nagyságrendű. Nem mindegy.
Ha már ennyire szerelmesek vagyunk az adatbázisba, akkor még azt meg lehet tenni, hogy paraméterként adjuk át neki ezeket a well-known beállításokat.

Pl.

create proc Teszt1
as
declare @a varchar(200)
select @a = s.Value from Setting s where s.Name = 'TestSetting1';
go

create proc Teszt2
@par varchar(200)
as
declare @a varchar(200) = @par
go

declare @i int = 1000000, @a varchar(200)
while (@i > 0)
begin
	exec Teszt1;
	set @i-=1;
end
go

declare @i int = 1000000, @a varchar(200)
select @a = s.Value from Setting s where s.Name = 'TestSetting1';
while (@i > 0)
begin
	exec Teszt2 @a;
	set @i-=1;
end

28 vs 12 mp, látszólag nem nagy deal, de egy terhelt szervernél minden gramm számít.

Ps. sok cégnél láttam ilyeneket, senki ne vegye magára.

Gondolatok a queue alapú kliens-szerviz kommunikációhoz

Thursday, June 16th, 2011

Az előző post kommentjei alapján (amit nagyon köszönök mindenkinek) nem kaptam sok bátorítást az aszinkron, queue alapú, kérés-választ különválasztó gazdag kliens – szerviz kommunikációhoz, úgy tűnik senki nem csinált ilyet, így nem akarok úttörő lenni a témában.
Ehhez még hozzájárul, hogy hétvégén méregettem az MSMQ teljesítményét. Azért ezt, mert a WCF is erre épít, és pl. az NServiceBus is.

A tesztkód 1.5kByteos üzeneteket rak át egyik sorból a másikba. Az ötlet innen jött, csak többszálasítottam.

A tesztkód:

using System;
using System.Diagnostics;
using System.Messaging;
using System.Threading;

namespace MsmqTran
{
class Program
{
private const int NumberOfTests = 1000;
private const int MaxDop = 10;
private static readonly ManualResetEvent[] WaitForEmpty = new ManualResetEvent[MaxDop];

static void Main()
{
var q1 = new MessageQueue(@”.\private$\test_queue1″);
var q2 = new MessageQueue(@”.\private$\test_queue2″);

Console.WriteLine(“Filling source queue…”);
var b = new byte[1500];
using (var msmqTx = new MessageQueueTransaction())
{
msmqTx.Begin();
for (int i = 0; i < NumberOfTests; i++)
{
q1.Send(b, msmqTx);
}
msmqTx.Commit();
}

q2.Purge();
Console.WriteLine("Starting to move data from source queue to destination queue");

var sp = Stopwatch.StartNew();

for (int i = 0; i < MaxDop; i++)
{
WaitForEmpty[i] = new ManualResetEvent(false);
ThreadPool.QueueUserWorkItem(o => ProcessMsg(q1, q2, (ManualResetEvent)o), WaitForEmpty[i]);
}

WaitHandle.WaitAll(WaitForEmpty);

Console.WriteLine(“Duration: {0}ms, throughput: {1:F0} messages/s”, sp.ElapsedMilliseconds, 1000.0 * NumberOfTests / sp.ElapsedMilliseconds);
}

private static void ProcessMsg(MessageQueue q1, MessageQueue q2, ManualResetEvent w)
{
while (true)
{
using (var msmqTx = new MessageQueueTransaction())
{
msmqTx.Begin();

Message message;
try
{
message = q1.Receive(TimeSpan.FromMilliseconds(0), msmqTx);
}
catch (MessageQueueException e)
{
Console.WriteLine(e);
w.Set();
break;
}

q2.Send(message, msmqTx);

msmqTx.Commit();
}
}
}
}
}

A gépemen 50 tran/sec-kel megy 1 szálon, és 200 fölé nem nagyon megy. Jó, ez laptop, de relációs adatbáziskezelővel (sql server és oracle is fut a gépen) több ezer tran/seccel mennek a dolgok. Szóval ez elég gázosan lassú. Emellett csúnya leállásokról is írnak a blogokban, amikor beáll az msmq.

Marad a aszinkronított WCF egyelőre, csak a szerverről visszafelé hívásokat tervezem queue alapon megcsinálni, WCF msmq bindinggal. Így tudom értesíteni az appokat polling nélkül. Erre 3 okom van most:
1. Az offline (disconnected) pessimistic lock feloldódott, lehet szerkeszteni valamit.
2. Frissíteni kell a kliens cache-ben valamit.
3. Email jellegű üzenetküldés az appok között.

Köszönöm még egyszer az építő javaslatokat.

Message alapú LOB app tervezés

Saturday, June 11th, 2011

Próbálom megtörni magamban a megszokott gondolkodási sémákat. Tervezek egy nagy, többrétegű LOB alkalmazást. A szervizrétegnek elsődlegesen a WPF rich klienst kell kiszolgálni, de jó lenne, ha mobil kliensek is tudnák ezt fogyasztani.
Ha a szerviz interfész finom felbontású, sok kicsi metódussal, akkor a kommunikáció sok időt rabol el, lassú lesz az app (chatty interfész).
Ha durva felbontású (chunky), akkor megvan a veszélye, hogy a fogyasztó WPF app formjaihoz lesz illesztve, célirányosan, így akkor meg mobil kliensek nem fogják tudni hatékonyan fogyasztani.
Egy érdekes alternatívát láttam a probléma feloldására itt és itt.
Ebben az összes kliens-szerviz kommunikáció message alapú, teljesen aszinkron. Egy kitöltött form adatait elküldik egy queueba, a szerver pedig egy másik üzenettel válaszol erre. Azaz a kliens alapjaiban aszinkron, és a válaszok események formájában jönnek vissza.
A message alapú kommunikáció nagy előnye, hogy az üzeneteket össze lehet nyalábolni, és egyben elküldeni. Így a szerviz lehet finom felbontású, de a kommunikáció mégis gyors, nem sok kis darabból áll. Érthetően ezt szinkron, rpc jellegű szerviz hívásokkal nem lehet megcsinálni.
Ez a fajta queued, service bus alapú gondolkodásmód szokatlan nekem, de nagyon szimpatikus. Van valakinek tapasztalata ilyen rendszer tervezésével? Bármilyen url, pointer, könyv, személyes tapasztalat érdekelne. Úgy érzem nagy dolgokat lehet ezzel összerakni, csak meg kell alaposan értenem.

Még egy gondolat. WCF proxyk használatával az alapban message alapú, asszinkron kérés-válaszokból összeraknak egy RPC jellegű kommunikációt, úgy, hogy a kliens vár a szerver válaszára. Aztán a kliens kedvéért, hogy ne blokkoljuk le a GUIt csinálunk háttérszálat, ahol bevárjuk a szerviz válaszra váró szálat. :)
Miért nem használunk eleve aszinkron üzenetváltásokat, és akkor sokkal egyszerűbb lesz a kép. A kliens bepostázza a kérést a buszra, és megy tovább. Amikor a válasz megjön, akkor meg erről eseményben értesül. Nyilván itt is vannak háttérszálak, hisz ki fogadná akkor a szervertől jövő választ, és ki hívná vissza a kliens eseményeken keresztül, de valahogy akkor is tisztábbnak tűnik a kép, mint az erőltetett RCP-jellegű módszernél. Nem?

Alternatíva a gonosz EAV-val szemben?

Thursday, May 19th, 2011

Az üzleti igény egy olyan adatbázis struktúra létrehozása, amelyben az előre definiált táblák adatai mellé a kusztomerek saját maguk is fel tudnak venni plusz adatokat, anélkül, hogy ehhez az adatbázistáblákat és az alkalmazást módosítani kellene. Sajnos nem csak letárolják ezeket, de még keresni is akarnak egyesekre. Azaz egyfajta open schemat kellene megvalósítani. Erre jó lehet az Entity-Attribute-Value megoldás, de úton-útfélen gonosznak van kinevezve. Értem én, hogy szar belőle lekérdezni, marha nagy lehet, ha egyszerűen csinálják meg nem típusos (én minden típushoz akarok egy oszlopot létrehozni), de milyen használható alternatíva van vele szemben?
Olvastam a serialized blobot, pl. egy xml oszlopba rakjuk a plusz dolgokat. Elvileg lehet xqueryzni, meg indexelni, de érzésre ez se egyszerű, se gyors nem lesz.
A sparse colum esetén séma módosítással jár az új adat definíciója. Ez egyrészt nem tetszik secu okokból (alter table kell hozzá), másrészt elég gáz szervizelni az alkalmazást, ha 50 ügyfél saját oszlopokkal bővítheti a tábláinkat.
Szóval, mi a jó a feladatra? Nekem még mindig az EAV tűnik a legkezelhetőbbnek.

Modernizált Design Patterns tanfolyam – 2010. május 4-7

Monday, March 22nd, 2010

Szétestem az utóbbi két hónapban, annyi munkám volt (elnézést kis családomtól így nyilvánosan is), de most végre kicsit fellélegzek. Most sok időm lesz, elvégre a munkák mellé csak 6 MCP vizsgát raktam be áprilisra (.NET 4 béták). :)

Májusban viszont újra lesz Design Patterns tanfolyam, ahol az eddigi a Gof patternek mellett Unityről és általában a Dependency Injection frameworkökről, ViewModelről, Composite Application Block for WPF-ről, T4 template alapú kódgenerálásról, partial method alapú kibővíthetőségről és Entity Framework Portable Extensible Metadatáról (egyfajta DSL) is szó lesz.
Várok mindenkit szeretettel.

Aki a NetAcademiánál jelentkezéskor az alábbi C# kód által kiírt stringet bemutatja, 50e Ft kedvezményt kap az árból.

using System;

class Program
{
static void Main(string[] args)
{
Allat a = new Emlos();
a.Mozog();
}
}

class Allat
{
public virtual void Mozog()
{
Console.WriteLine(“Állat vagyok, és mozgok”);
}
}

class Emlos : Allat
{
public virtual void Mozog()
{
Console.WriteLine(“Emlős vagyok, és mozgok”);
}
}

ViewModelek kérdésköre

Wednesday, March 3rd, 2010

Mostanában oktatok és prototípust írok, közben ezer design kérdést tisztázok a fejemben. Az egyik ilyen pl., hogy a ViewModel DependencyProperty vagy INotifyPropertyChanged módon közvetítse a változásokat a GUI-ra?
Én az INotifyPropertyChanged-re szavaznék, mert így a ViewModel és nem függ a GUI technológiától, eleve nekem fura a modellben pl. WPF fogalmakat látni.

Infók a kérdéskörben.

Általános áttekintés:
INotifyPropertyChanged vs. DependencyProperty in ViewModel

Egy POCO szavazat:
View Models: POCOs versus DependencyObjects

Én Expressionnel oldom meg, hogy ne legyenek property name stringek a kódban, ő nem, de az objektum pool ötlet tetszik benne, átveszem, de szemeteljünk.
A base class which implements INotifyPropertyChanged

Nagyon dicsérik a videót, még nem volt időm megnézni.
Jason Dolinger on Model-View-ViewModel

Jó kép az MVVM rétegekről.

Egyféle Validation megközelítés.
Using a ViewModel to Provide Meaningful Validation Error Messages

Jó Entity Framework architektúra cikkek

Tuesday, January 19th, 2010

Hogyan építsünk EF-re többrétegű appot?
1. Anti-Patterns To Avoid In N-Tier Applications
2. N-Tier Application Patterns
3. Building N-Tier Apps with EF4

Jó cikkek.

Hacktivity előadásom

Tuesday, September 15th, 2009

Hétvégén lesz a Hacktivity konferencia, ahol NEM arról fogok beszélni, ami ki van írva.
Gál Tamással ketten kaptunk 45 percet, amiben GT a VPN Windows7/R2 új alternatíváiról beszél, én pedig arról, hogy egy akkora cég, mint az MS hogyan képes felzárkózni a hekkerek generálta biztonsági kihíváshoz. Az előadásom fele érdekességekkel, történetekkel lesz tele, belső infók, mit tesz az ms a jobb kódminőség érdekében, a másik felében pedig konkrét példákat mutatok be, amelyek demonstrálják, hogy a különböző támadási típusok esetén (privilege escalation, stb.) hogyan zárkóztak fel a termékek, mint a Windowsok vagy az IIS.
Szeretettel várok mindenkit, aki ráér hétvégén hekkerkedni.

Előadásom az Architect Akadémián – SQL Server architect szemmel

Sunday, April 12th, 2009

Kicsit későn szólok, de ha valakit érdekel, még jelentkezhet, április 15-én lesz.
3×1 órában beszélek arról, hogyan lehet bevetni az SQL Serverek (2000-2008) okosságait egy új alkalmazásarchitektúra kidolgozása során. A cél nem annyira mélységi, mint szélességi bemutatása annak, mit lehet kihozni az SQL Serverből. Igyekszek olyan dolgokról is beszélni, amiről ritkán esik szó (pl. Query Notification, Service Broker), világnézet tágítás végett. Szeretném megmutatni, hogy az SQL Server nem egy egyszerű CRUD adatbázismotor, ahogy sajnos nagyon sokan használják.

Design Patterns tanfolyam – újra, kibővítve .NET 3.5-tel

Thursday, February 12th, 2009

Marcival újra összeállunk pár akcióra, ennek első megnyilvánulása, hogy újra lesz Design Patterns tanfolyam.
Már írom át az anyagot, a 3.5-ös .NET Fw. tele van szebbnél-szebb design példákkal, illetve az utóbbi 2 év gyakorlati programozása során jó pár dolog tovább formálódott, tisztult a fejemben, ezeket is beépítem az anyagba.

A referenciáim között megtekinthető, hogy volt, amikor cégek szinte összes programozója részt vett a tanfolyamon, felismerve a dolog hasznát a fejlesztési folyamatok minőségére.

És végül, aki bemásolja a következő kódot a jelentkezési lapjára, 20% kedvezményt kap a tanfolyam árából:

public class DP: Course, ISupportDiscount
{
public HappyStudent GiveMeThisDirtyGoodCourseCheaply() { }
public string Author { get { return “soci”; } }
public string Trainer { get { return “soci”; } }
public DateTime ActionTime { get { return DateTime.Parse(“2009.03.09″); } }
}

Szeretettel várok mindenkit.

Szaktanácsadó születik :-)

Tuesday, October 14th, 2008

Örömmel és nagy reményekkel közzéteszem, hogy 2009. január 1.-től független szaktanácsadóként folytatom a szakmai pályafutásom. Ennek megfelelően év végére átalakítom a website-om főlapját is, a megfelelő üzleti, kontakt, stb. információkkal kiegészítve.
A blogom változatlanul fog üzemelni, sőt, várhatóan több időm lesz rá, és jóval több témával is fogok foglalkozni (WCF, WWF, Windows Internals, DP újult erővel, stb.).

Ha .NET-alapú fejlesztéssel, tervezéssel vagy SQL Serverrel kapcsolatban tudok valakinek segíteni, januártól szabad vagyok. Az utóbbi két évben jó pár felkérést utasítottam vissza, jövőre erre már nem lesz szükség.

Részletek később, most igen sok intéznivalóm van…

SQL Server 2008 Analysis Services Windows Server 2008-on vs. Windows Server 2003-on

Thursday, July 17th, 2008

Habár nem értek az Analysis Serviceshez (még, az SSIS után ez a következő falat), de ez a cikk igen érdekes. Nem annyira az SQL-es, inkább az operendszeres vonatkozásai miatt.
Az átlagfelhasználó az új Windowsokból csak az új shellt tapasztalja meg, meg, hogy több ram kell nekik. Ennek ellenére a háttérben keményen fejlesztik a rendszer magját, csak az nem annyira látványos, még, ha igen hasznos is.
A cikkben arról beszélnek, hogy a Windows 2008-ban új memóriakezelő van, ami sokkal jobban kezeli a sok, apró memóriafoglalást. Ez azonnal látszik, ha az Analysis Services-szel dolgoztatunk fel jelentős mennyiségű adatot, a 2008-on kapásból dupla olyan gyors lett a feldolgozás (tudom, minden teszt csal, de nem hiszem, hogy nagyot hazudnának).
A szerviznek meg lehet mondani, hogy előre allokálja le a memóriát, így 2003-on is hasonló teljesítményt érhetünk el, mint 2008-on.

Az egészből számomra az az érdekes, hogy gyorsabb Windows 2008-ban a memóriakezelés, amiből bármilyen app profitálni fog. Megvettük. :)

Supervising Controller pattern

Tuesday, April 24th, 2007

Architektúra kedvelőknek egy jó kis cikk a Supervising Controller pattern használatáról ASP.NET-ben.