\

Školení Návrhové vzory, OOP a UML


 Monday, August 16, 2004
TMO a vyřizování reklamace, tohle mi můj oblíbený operátore nemáš dělat:(

V příspěvku není diakritika, protože text jsem původně posílal do konference gsm@sh.cvut.cz , do které se zásadně přispívá bez diakritiky.

Tak dnes me TMO pekne vytočil. Respektive jedna jeho pracovnice na infolince jmenem Richterova Petra.

Volal jsem, protože na cervencovem vyuctovani jsem nasel nesmyslne polozky za GPRS. Jak k tomu doslo?

30.7. Priblizne ve 22:30 jsem menil tarif GPRS Unlimited na GPRS Basic. Zmena probehla bez problemu.

31.7. Rano mi prisla SMS, ze mam aktivni tarif GPRS Basic.

Na podrobnem cervencovem vyuctovani se 30:7 objevily polozky, ktere byly uctovany tarifem Basic a /*mezi nimi*/ byly nezauctovane polozky.

Takto vypada muj podrobny vypis

GPRS prenosy z 30.7

O7:41 - 370 kB - cena 0,00

11:38 - 4 kB - cena 0,00

18:06 - 2517 kB - cena 151, 20

21:06 - 38 kB - cena 0,00

21:10 - 2 kB - cena 0,00

21:10 - 2 kB - cena 0,00

21:12 - 1780 kB - cena 106,80

22:45 - 45 kB - cena 0,00

22:01 - 2 kB - cena 0,00

22:02 - 10 kB - cena 0,00

22:03 - 381 kb - cena 0,00

Jak je patrne z vypisu, TMO si nauctoval 30.7. 2 datove prenosy, ostatni ne.

Nejprve jsem na infolince narazil na ochotnou slecnu, ktera rychle chapala, v cem je problem, a sdelila mi, ze v jejich systemu je zaevidovan datum zmeny tarifu 31.7 a ze jeste proveri vypis. Pak mi bohuzel spadlo spojeni s infolinkou (moje vina).

Pri druhem volani jsem mel potize vysvetolit operatorce zminene vyse, o jaky problem se vubec jedna, pak me nechala 2x nekolik (desitek) minut cekat, protoze pry "jeste neco overi".

Pote na me ale vytasila argumenty, ktere me dost konsternovaly a otrasly mou virou v kompetentnost TMO, se kterym jsem az do dneska nemel zadny problem - asi proto ze jsem nikdy nemusel zadnou fakturu reklamovat.

Mam pry byt rad (!), ze faktura je takova jaka je, protoze TMO se spletl ve svuj neprospech. Jak se to mohlo stat? Pry i kdyz jsem zadal o zmenu tarifu 30.7 nekdy kolem 11 hodiny vecer, tak cely den s datem 30.7 je uctovan jiz s tarifem Basic. Udajne toto pravidlo plati i pro hlasove tarify. Kdyz jsem slecnu pozadal, aby me odkazala na konkretni clanek ve Vseobecnych podminkach TMO nebo v jinem smluvnim dokumentu, ve kterem je toto pravidlo zmineno, slecna opacila ze "nema ted ani pozdeji moznost neco dohledavat, ale ze to tak urcite je".

Dale jsem se ji ptal, zda si nemysli, ze i kdyz by to bylo tak, jak rika, tak ma TMO chybu v systemu, protoze mi nebyly zapocitany vsechny polozky. Slecna rekla, ze s timhle nema co do cineni, ze to pro ni neni zajimavy, ze uz nedohleda, jestli vypadla databaze (sic!) a ze ja mam vlastne stesti, takze se o to nemusim dal starat, ale jestli chci, tak muzeme sepsat stiznost (minena reklamace?), ale ze pak doplatim zbytek prenosu za cele datum 30.7. Tak jsem rekl, ze me ta zbyvajici castka nevytrhne a ze bych rad vedel, na ci strane je pravda, takze stiznost sepiseme.

Slecna rekla, ze tak ucini a ja jsem se jeste zeptal, jak dlouho bude vyrizovani asi trvat. Jeji odpoved opet zachovala bodrou atmosferu celeho rozhovoru : "To vam nereknu, tohle se vyrizuje v jinem oddeleni v jinem meste a nikdo nevi, jak to muze dlouho trvat". Asi na doruceni stiznosti TMO z duvodu uspor pouziva postrelene holuby, protoze nechapu, jak se ve veku informacnich systemu muze tak velka firma jako TMO vymlouvat na to, ze ma nejake oddeleni v jinem meste. Pokud vim, TMO se ve Vseobecnych podminkach navic zavazuje, ze reklamace vyresi do 30 dnu. To opravdu slecny na infolinkach nemaji prehled ani o zakladnich smluvnich dokumentech?

Takze krome stiznosti se chci zeptat.

1) Je tu v konfere nekdo z TMO, koho zajima, jak pracuji jejich billing systemy a dokazal by proverit, v cem je opravdu zadrhel? Kdyz budete chtit podrobnosti, ozvete se mi prosim soukrome.

2) Nevite nekdo, jak je to opravdu s uctovanim po zmene tarifu?

3) A jedna polemicka. Tusite nekdo, proc operatori zamestnavaji tak neprofesionalni operatorky?



Monday, August 16, 2004 7:30:00 PM (Central Europe Standard Time, UTC+01:00)       
Comments [11]  Mobilitky


Jedna špatná zpráva a dvě dobré ze světa PDA

Včera moje milované a hýčkané :) MDA II při vyjímání z pouzdra spadlo na zem a kryt, který je snad u všech prvních kusů MDA II (moje bylo koupeno 9.ledna - první den prodeje :) ) u vypínacího tlačítka od počátku naprasklý, se odlomil. Takže dnes jsem jej nesl do značkové prodejny TMO, kde mi sdělili, že tak 14 dní budu bez něj a že s 99% pravděpodobností mi závadu neuznají jako záruční. Na PDA jsem tak zvyklý, že se u mě jedná o malou tragédii, o jejíž tíhu jsem se musel podělit na blogu;).

Na serveru PocketGear se objevila informace o MDA IV. MDA III mě neláká, protože vestavěná liliputánská klávesnice ani podpora Wi-Fi nejsou dostatečným důvodem k výměně PDA.

MDA IV ale vypadá na jedno z "must have" zařízení příštího roku. Společnost HTC se pochlapila a hlavní vlastnosti MDA VI, které by nás měly donutit vybrat si právě tento model jsou:

  •         VGA displej (640x480) - na čtení e-knih ideální
  •         Processor XScale 624 MHz - současná špička v mobilních procesorech
  •         Quad-Band GSM
  •         Podpora UMTS
            

MDA IV by mělo být uvedeno v první polovině roku 2005, po zkušenostech s oddalováním dodávek MDA II odhaduji, že si radost udělám nejdříve o vánocích roku 2005.

Dalším špičkovým zařízením s Windows Mobile Phone Edition je Motorola MPX, která snad bude na trhu dříve než MDA IV.

Vybrané technické parametry:

  • Procesor ARM OMAP 733 195 MHz      
  • Integrovaná klávesnice
  • Unikátní skládací konstrukce (To se nedá popsat, koukněte se raději na obrázky)
  • GSM Tri-Band ((900/1800/1900)
  • Vestavěné Wi-Fi

     

Komu nečiní problémy francoužština, může si přečíst výbornou recenzi Motoroly MPX. na serveru Mobinaute.



Monday, August 16, 2004 6:33:00 PM (Central Europe Standard Time, UTC+01:00)       
Comments [4]  Mobilitky


 Sunday, August 15, 2004
Windows služba pro pravidelné stahování souborů z Visual Source Safe databáze

I když je Visual Source Safe na mém soukromém žebříčku mizerných programů zcela zaslouženě na nelichotivém prvním místě a jeho programátory podezřívám, že byli do Microsoftu infiltrováni konkurenčními firmami a plní zde (nutno přiznat, že ale velmi úspěšně :) ) roli Trojského koně, musel jsem se smířit s tim, že ve firmě VSS stále používáme, byť všichni s kletbami na rtech. Protože ve VSS nemusí být ukládány jen zdrojové kódy, ale i dokumentace a analytické artefakty, o něž mají zájem i lidé*, kteří s VSS jinak nepracují a které nemá smysl nutit, aby instalovali a používali VSS klienta, rozhodl jsem se, že pro DIGI TRADE napíšu Windows službu, která vybrané projekty z VSS databáze v pravidelných intervalech uloží do adresáře v souborovém systému.
A protože se služba bude asi hodit více lidem, betu Windows služby si můžete zdarma stáhnout a otestovat.

Po rozbalení archivu musíte službu nainstalovat nástrojem InstallUtil.
installutil.exe DigiTrade.VSS.VSSService.exe


V konfiguračním souboru DigiTrade.VSS.VSSService.exe.config změňte cestu, kam má být ukládán "trace" log (hodnota atributu initializeData). Jestliže budete reportovat chyby, přiložte vždy prosím i "trace" log.


Účet, pod kterým běží služba, musí mít právo zapisovat do souboru s " trace" logem!
<add name="VSSListener"
type="System.Diagnostics.TextWriterTraceListener"
initializeData="c:\LOGS\VSSService.log"/>

Když chcete používat jiný soubor s VSS konfigurací (viz dále), změňte v souboru hodnotu klíče IniFile.
<add key="IniFile" value="VSSManagerConfig.xml"/>

 Soubor s konfigurací VSS manažera (VSSManagerConfig.xml) má následující strukturu:

Element vssManager - kořenový element.
Povolený obsah - Elementy generalSettings, commonProjects a exactProjects

Element generalSettings - základní nastavení VSS služby.
Povolený obsah - žádný

Atributy

  • vssIniFile - Cesta k ini souboru VSS databáze, se kterou má služba pracovat.
  • userName - Jméno uživatele ve VSS, pod kterým se bude služba přihlašovat.
  • password - Heslo uživatele ve VSS (v Betě není kryptováno!).
  • saveAllItems - Pokud má atribut hodnotu true, tak se ignorují sekce commonProjects a exactProjects a dojde ke stažení všech projektů z VSS databáze.
  • saveDirectory - Adresář, do kterého budou uloženy soubory z VSS.
  • checkerInterval - Interval v minutách, po jehož uplynutí jsou stahovány soubory z VSS databáze.

Element commonProjects - projekty, které budou staženy vždy bez ohledu na jejich místo v hierarchii projektů ve VSS. Tuto sekci využijete například tehdy, když ve většině projektů máte podprojekty se stejným názvem.(například adresář DOC s dokumentací projektu).
Povolený obsah - element project

Element exactProjects - Projekty určené absolutní cestou (začíná znakem $), které mají být staženy z VSS.
Povolený obsah - element project

Element project - element reprezentující projekt ve VSS.
Povolený obsah - žádný

Atributy

  • name - Název projektu


Služba využívá přes interop COM knihovnu SSAPI.dll dodávanou s VSS.
Po instalaci doporučuji vytvořit pro službu nový Windows účet, pod kterým poběží a který bude mít přidělen jen nejnutnější práva - přístup k souboru s "trace" logem, přístup k VSS databázi a právo zapisovat do adresáře určeného atributem saveData. Vhodné je také vytvoření nového uživatelského účtu ve VSS.

Pro úplnost jen podotýkám, že vím o existenci konzolového nástroje ss.exe s desítkamí neintuitivních přepínačů, který je součástí VSS, ale správa desítek nebo stovek řádků v BAT souboru mě nelákala, a proto vznikla tato služba.

*Pro účely tohoto spotu jsem se rozhodl zjednodušeně považovat projektové manažery a obchodníky za lidi, i když u některých členů těchto kast mám o jejich pravé podstatě kvůli jimi bezskrupulózně projevované deficitní intelektuální potenci důvodné pochybnosti:)



Sunday, August 15, 2004 12:07:00 PM (Central Europe Standard Time, UTC+01:00)       
Comments [9]  .NET Framework | VSS Windows Service


 Tuesday, June 08, 2004
Projekt Kamilka uveden v život
Ve 22:20 se nám s Petrou v porodnici v Benešově  narodila krásná dceruška Kamilka. Měří 50 cm a váží 2, 95 kg. Takže jsem otcem a že k rodičovství přistupuji zodpovědně svědčí to, že jsem našemu dítěti už před měsícem vybral mobilní telefon, dát mu ho ale ještě prý nesmím ;)

Tuesday, June 08, 2004 7:23:00 AM (Central Europe Standard Time, UTC+01:00)       
Comments [20]  Ostatní


 Sunday, June 06, 2004
Synchronizace stavových automatů. Rozumíte návrhovému vzoru Mediator?

Návrhový vzor Mediator  zamezuje těsným vztahům mezi objekty zavedením  prostředníka (mediatora), který jejich interakci zapouzdří. Tak praví strohá, ale výstižná definice. Řečeno jinak, Mediator snižuje přímé i nepřímé zatížení třídy jinými třídami.

Vzor Mediator je většinou vykládán na příkladu interakce komponent v uživatelském rozhraní, které spolu komunikují přes prostředníka, jímž je formulář.  Listbox se seznamem zemí neví nic o Listboxu se sezamem měst - po výběru jiné země je vyvolána událostní procedura formuláře, v níž je kód pro naplnění druhého Listboxu městy ve vybrané zemi. Každý ovládací prvek spolupracuje jen s formulářem, který notifikuje o změně ve svých vlastnostech, a na formuláří je kód propagující změny do dalších prvků. Na způsobu chování nezáleží, formulář může být u prvku zaregistrován jako Observer (v terminologii jazyka JAVA Listener), jehož metoda je zavolána po změně stavu prvku, nebo v .NET zaregistrujeme u ovládacího prvku delegáta s obslužnou metodou, jejíž signatura se shoduje se signaturou události. Komplexního chování prezentační vrstvy není dosaženo přímou spoluprací mnoha objektů,  ale zavedením inteligentní mezivrstvy, která je recipientem heterogenních notifikačních zpráv objektů a současně  autorem a distributorem nových aktualizačních zpráv pro další objekty, jež po jejich přijetí změní svůj stav a přitom mohou prostředníkovi odeslat další notifikační zprávy. Zdůraznil bych, že prostředník je autorem zpráv, takže informaci o notifikaci nemusí jen přeposlat, ale také dokáže argumenty původní notifikační zprávy před odesláním kreativně pozměnit, filtrovat,  anebo dokonce rozešle události v jiném pořadí. Jak uvidíme, všechny tyto charakteristiky jsou klíčové pro mediatora koordinujícího synchronizaci stavových automatů business objektů.

Kdyby ovládací prvky mezi sebou komunikovaly přímo, tak i jednoduchá  změna chování prezentační vrstvy roztočí spirálu sisyfovského dohledávání a ošetřování dopadů změny v kódu všech prvků.

Použití vzoru Mediator ale není omezeno na prezentační vrstvu a jeho  kvality se plně projeví až při řízení složité interakce stavových automatů tříd v business vrstvě.

Představte si systém pro nábor zaměstnanců na různé pozice. V systému jsou evidovány nabízené pracovní pozice a uchazeči. Když uchazeč projeví zájem o pozici, je vytvořen nový objekt pro relaci mezi uchazečem a pozicí, v němž jsou uložena data o průběhu procesu výběru jednoho uchazeče. Platí pravidlo, že v jednom okamžiku může být Uchazeč přiřazen jen k jedné Pozici. Pozice,  Uchazeč  i Relace  mají své stavové diagramy. Uveďme si příklady stavů.

Pozice může být ve stavu:

 Nová - Zahájení životního cyklu pracovní pozice.

Přiřazen alespoň jeden uchazeč  O pozici se zajímá alespoň jeden uchazeč. Tento stav je důležitý pro manažery, kteří jsou odpovědni za obsazení pozice a zajímá je, zda například týden po vypsání místa je o pozici zájem, nebo je třeba investovat více peněz do propagace.

Přijat alespoň jeden uchazeč – K pozici se může vázat více volných míst, tento stav manažery náboru informuje, že již byl vybrán alespoň jeden vhodný zaměstnanec.

Obsazená – Pozice byla obsazena. Počet nabízených míst je roven počtu přijatých uchazečů.

Zrušená – Pozice byla zrušena. Pozici je možné kdykoli zrušit, což značí, že k ní již není možné dále přiřadit uchazeče a přiřazení uchazeči, kteří ještě nebyli přijati, jsou ihned odmítnuti.

Stavy uchazeče

Nový – Založení uchazeče.

 

Zajímá se o pozici Uchazeč byl přiřazen k pozici a prochází různými zkouškami. Nelze mu přiřadit další pozici.

 Přijat – Uchazeč byl přijat na pozici. Pozice musí být notifikována o přijetí uchazeče.

 Odmítnut – Uchazeč byl odmítnut, to znamená, že je ho možné přiřadit k jiné pozici.

 Propuštěn – Uchazeč (zaměstnanec) byl propuštěn. Opět ho je možné přiřadit k jiné pozici.

Zrušen – Uchazeč byl zrušen. Zrušit lze jen uchazeče ve stavu Nový, Odmítnutý a Propuštěný. Je nutné notifikovat aktivní relaci mezi Uchazečem a Pozicí.

Stavy relace mezi uchazečem a pozicí

Nová Nová relace mezi uchazečem a pozicí založena. Je nutné notifikovat pozici i uchazeče, že byla mezi nimi vytvořena relace.

Uchazeč prošel psychotesty – Uchazeč úspěšně prošel psychotesty.

Uchazeč odmítnut po psychotestech –Uchazeč neprošel psychotesty, notifikovat pozici a uchazeče o odmítnutí.

Uchazeč splnil všechny požadavky – Notifikovat pozici o přijetí dalšího uchazeče, notifikovat uchazeče.

Zrušena – Došlo ke zrušení relace, důvodem může být to, že uchazeč o pozici ztrati zájem nebo je zrušena pozice. Notifikovat uchazeče a pozici o zrušení.

Jde sice jen o reprezentativní množinu tříd a jejich stavů, ale i mezi takto malým počtem tříd existuje poměrně složitá spolupráce.

Například při zrušení pozice musejí být notifikovány všechny aktivní Relace, ty přejdou do stavu zrušena . Je notifikován Uchazeč, že byl odmítnut. Relace zpětně notifikuje o svém zrušení i Pozici, protože důvodem zrušení může být jindy ztráta zájmu ze strany Uchazeče.

Další příklad. Když relace přejde do stavu Uchazeč splnil všechny požadavky, tak musí být notifikována pozice, u níž dojde ke změně stavu jen tehdy, když se jedná o prvního přiřazeného uchazeče. Dále je notifikován uchazeč, který přejde do stavu Přijat.

Představme si nyní, že třídy Uchazeč, Pracovní pozice a Relace informaci o změně svého stavu nabídnou okolí ve formě událostí. Každý objekt z jedné třídy si přihlásí odběr událostí asociovaných objektů z dalších tříd  a pak všichni spustí divokou událostní přestřelku se zběsilými kulkami v podobě vzájemných notifikací.

Když Pozice přejde do stavu zrušena, informuje první relaci, ta změní svůj stav na zrušena, relace svoji změnu stavu zašle uchazeči, ten přejde do stavu „Odmítnut“ a vyvolá svoji událost „Změna stavu“, tu odchytí Relace, která na stav „Odmítnut“ u uchazeče nereaguje. Relace informaci o svém zrušení zasílá vždy recipročně objektu Pozice. Pozice pod dokončení kolečka s první Relací notifikuje další Relaci a kolečko s mírně obměněnými aktéry proběhne znovu. Všechny objekty jsou při tomto vzájemném přeřvávání kandidáty na slušivou svěrací kazajku.

V čem je ale hlavní problém? Události nemusí být zpracovány ve správném pořadí. Představme si, že u Pozice z nějakého důvodu zavedeme další tranzientní stavy „Vyžádáno zrušení pozice“, „Pozice je rušena“ a teprve finálním stavem je náš původní stav „Zrušena“. Do stavu „Vyžádáno zrušení pozice“ přejde pozice ihned po žádosti uživatelem (přesněji po volání metody Cancel), do stavu „Pozice je rušena“ , když je zpětně notifikována první Relací o jejím přechodu do stavu Zrušena. Pozice přejde do finálního stavu  „Zrušena“ až po obdržení potvrzení o svém zrušení od všech dalších relací. Tady ale narazíme – když Pozice přejde do stavu „Pozice je rušena“, tak začne tuto událost rozesílat všem Relacím.

To znamená, že Relace2 a následující obdrží nejdříve informaci o přechodu Pozice do stavu „„Pozice je rušena“ a později o ( již nepravdivém)  přechodu do stavu  „Vyžádáno zrušení pozice“. Když se zkomplikují i stavové automaty dalších objektů, staneme se nechtěnými svědky rozhovoru bandy otrlých lhářů.:)

Pořadí při rozesílání událostí není sekvenční,  a i když bychom mohli do objektu Pozice a dalších dopsat logiku, která se o sekvenční distribuci postará, nepůjde o šťastné řešení. Aby třída konvenovala svému okolí, dosadíme do ní znalost, jak si okolí komunikací představuje, a porušíme tak princip zapouzdření. Třída svému okolí sděluje, jaké změny v ní nastaly, ale nesmí se starat o reakce okolí. Třída musí být vždy nonkonformní a kašlat  na své sousedy, jež ji nutí, aby se adaptovala na jejich způsob komunikace a chování.  (BTW: Zjsitil jsem, že  miluji OOP a návrhové vzory, protože k sousedům mám stejný postoj :) )

Odpovědnost za sekvenční rozesílání událostí přidělíme nové třídě Mediator. Po svém vytvoření budou objekty zaregistrovány v Mediatoru, který si přihlásí odběr jejich událostí. Třídám Pozice, Relace a Uchazeč přidáme metody, které budou volány mediátorem, když nastane událost. Například objekt Pozice bude mít metodu „NotifikujUchazečOdmítnut“, která bude mediátorem zavolána, když Relace přejde do stavu „Uchazeč odmítnut po psychotestech“ nebo do stavu  „Zrušena“.

Aby mediátor nebyl příliš komplikovaný a nepřehledný, vytvoříme pro každou třídu jednoho zpracovatele události. Každý zpracovatel událost bude implementovat rozhraní s jedinou metodou „ZpracujUdálost“, které přijímá dva argumenty. Prvním argumentem je odkaz na objekt, který událost vyvolal, a druhým jsou parametry události. Zpracovatel „ví“, jaké metody musí u objektů volat pro každou jedinečnou kombinaci argumentů události. (Když zpracovatel objektu Relace obdrží událost „Přechod do stavu Zrušena“, tak zavolá u asociovaného objektu Pozice metodu NotifikujUchazečOdmítnut“ a u Uchazeče metodu „ZůstávášNezaměstnaným“:) )

Jak zajistíme sekvenční zpracování?

V událostních metodách mediátor odchytne událost a zavolá vždy jen obecnou metodu handleEvent, které kromě odesílatele a argumentů události přijímá odkaz na zpracovatele (m_JobHandler), jenž reaguje na danou událost. Objekt m_JobHandler zpracovává událost „StavZměněn“ třídy Pracovní pozice.

handleEvent(sender, e, m_JobHandler);

 

Metoda handleEvent

 

private void handleEvent(object sender, EventArgs e, BProcessEventHandlerBase processor)

                        {

                                   EventStateHolder holder = new EventStateHolder(e, sender, processor);

                                   m_eventsQueue.Enqueue(holder);

 

                                   if (!m_inEventBubbling)

                                               initEventBubbling();

                        }

Metoda handleEvent nejdříve uloží všechny informace o události do nové instance naší třídyEventStateHolder. Zde mimochodem vidíte kouzlo polymorfismu, protože naše třída EventStateHolder se nestará o detaily událostí, ale vyžaduje jen, aby argumenty události byly odvozeny z třídy EventArgs a zpracovatelé událostí z třídy (rozhraní) BProcessEventHandlerBase. Poté je událost zařazena do fronty (v .NET třída Queue) a jestliže se jedná o první událost, je zavolána metoda initEventBubbling, která se postará o předání události do zpracovatele. Tento kód je důležitý –  bublání událostí je zahájeno jen při první události, všechny další události libovolných business objektů, které jsou přímou nebo nepřímou reakcí na první událost, jsou jen zařazeny do fronty a k novému  spuštění distribuce událostí realizovaného metodou initEventBubbling nesmí dojít.

private void initEventBubbling()

{

                                   Debug.Assert(m_eventsQueue.Count > 0, "BMediator events queue is empty!");

                                   m_inEventBubbling = true;

                                   while (m_eventsQueue.Count > 0)

                                   {

EventStateHolder eh = (EventStateHolder) m_eventsQueue.Dequeue();

eh.Processor.ProcessEvent(eh.Sender, eh.EventArguments);

                                   }                                 

m_inEventBubbling = false;

                        }

V metodě initEventBubbling se nejdříve ujistíme, že fronta událostí není prázdná. Pak nastavíme privátní proměnnou m_inEventBubbling na true, aby metoda handleEvent již při zpracovávání návazných událostí metodu initEventBubbling nevolala. V jednoduchém cyklu while zpracujeme sekvenčně všechny události postupně přidávané do fronty po rozeslání každé události.

Mediatora můžete vylepšit. Ke každé události mohou být registrovány preprocesory, kteří například zalogují všechny události a postprocesory, odesílající manažerovi informaci o provedených změnách. Když budeme chtít rychle změnit chování aplikace bez zásahu do existujícího kódu, můžeme napsat nový preprocesor, který událost zpracuje zcela jinak, a protože z metody vrátí true (nepokračovat v distribuci událostí, již jsem vše udělal), tak se originální zpracovatel události nedostane ke slovu. Preprocesory načteme dynamicky při startu aplikace  s využitím reflection API.

private void initEventBubbling()

{

                                   Debug.Assert(m_eventsQueue.Count > 0, "BMediator events queue is empty!");

                                  

                                   m_inEventBubbling = true;

                                   while (m_eventsQueue.Count > 0)

                                   {

                                               EventStateHolder eh = (EventStateHolder) m_eventsQueue.Dequeue();

                                               bool continueEventBubbling = distributeEventToPrePostProcessors(eh.Sender, eh.EventArguments, m_preProcessors);

                                               if (continueEventBubbling)

                                               {

                                                           eh.Processor.ProcessEvent(eh.Sender, eh.EventArguments);                                                        distributeEventToPrePostProcessors(eh.Sender, eh.EventArguments, m_postProcessors);

                                               }

                                   }

                                   m_inEventBubbling = false;

                        }

 

                        private bool distributeEventToPrePostProcessors(object sender, EventArgs e, ProcessorCollection processors)

                        {

                                   bool result = true;

                                   foreach (IProcessor processor in processors)

                                   {

                                               if ((processor.ProcessEvent(sender, e)))

                                               {

                                                           result = false;

                                                           break;

                                               }

                                              

                                   }

                                   return result;

                        }

Také můžete přes mediátora řídit distribuci událostí transakčně s potvrzováním a  vracením jednotlivých kroků a ukládat změny ve všech participujících objektech na konci úspěšné transakce do databáze.

Vzor Mediator je nepominutelnou dominantou každého návrhu aplikace, jež vyžaduje komplexní komunikaci mezi stavovými automaty různých tříd.

 

 



Sunday, June 06, 2004 7:53:00 PM (Central Europe Standard Time, UTC+01:00)       
Comments [4]  Analytické drobky | Návrhové vzory | UML


 Wednesday, June 02, 2004
Hledají se vývojáři v .NET Frameworku aneb pojďte dělat kvalitní SW bez kompromisů:)

Jak stálí členové konference EMWAC vědí:), ve společnosti DIGI TRADE stále přijímáme vývojáře pro .NET Framework. Protože informace v emailovém podpisu je velmi strohá, chci v tomto spotu popsat, jak probíhá výběr vhodného kandidáta a co uchazečům nabízíme.

Samozřejmě, že konkrétní detaily smlouvy jsou individuální a odvíjejí se od pozice, na kterou je člověk zařazen.

Poté co mě kontaktujete na emailu rstein at digi-trade.cz,vám zašlu podrobný popis nabízené pracovní pozice. Ideální bude, když ke kontaktnímu emailu přiložíte životopis. Jestliže se vám bude pozice líbit, smluvíme si s vámi termín osobní schůzky. Můžete si vydechnout, s žádným personalistou se nesetkáte.:) Pohovoru je přítomen vedoucí týmu vývoje na platformě Microsoft Štěpán Krejcar a já. Nejdříve se dozvíte něco o nás a firmě, pak vás požádáme o shrnutí vašeho profesního životopisu. Následuje nejzajímavější část:), ve které prověřujeme odborné znalosti. Tu mám na starosti já, takže můžete být bez obav.:) Cílem není uchazeče potopit, ale diskutovat s ním o vývojářských tématech uvedených v odborném životopise. Na začátku je uchazeč dotázán, zda se vyzná v UML notaci. Když řekne, že ano, bavíme se s ním nad UML modelem. Když UML neznáte, tak si jeho pasivní čtení u nás rychle osvojíte, ale jeho neznalost neovlivňuje celkové hodnocení pohovoru. Preferujeme uchazeče, kteří rutinně ovládají ADO.NET, MSSQL, Web Forms a/nebo Windows Forms. Také předpokládáme perfektní znalost SQL, uchazeč má za úkol napsat složitější dotaz na základě předloženého schématu databáze. Zdůrazňuji, že se ptáme hlavně na témata, v nichž se cítíte sami silní. Smůlu mají uchazeči, kteří do životopisu uvedou, že znají .NET Remoting a pak si myslí, že MarshalByRefObject je jméno vysoce postaveného žoldáka z napoleonských válek:). Bez legrace, opravdu se mnoho uchazečů uváděním technologie, z níž znají jen název, vyřazuje samo.

Jestliže odbornou částí projdete bez vážných znalostních mezer, nabídneme vám ihned práci. Když se objeví více srovnatelných kandidátů nebo si nejsme jisti využitím znalostí konkrétního člověka v týmu, necháváme si nějakou dobu na rozmyšlenou. Nejpozději do jednoho týdne ale dostanete konečné vyjádření.

Proč byste měli jít právě k nám?

1)      Chcete pracovat se mnou.:)

2)      Nemáte rádi rutinní práci, ale milujete složité projekty z oblasti CRM, Document Managamentu, Integrace aplikací, intranetových aplikací...

3)      Chcete pracovat ve firmě, kde se dělá vždy analýza a systémový design aplikací, takže odpovědnost za kvalitní aplikaci neleží jen na bedrech programátora.

4)      Nejsme firma, která přijme lidi na jeden projekt s "žhavými" termíny, naslibuje jim všem nejméně modré z nebe a po dokončení projektu je bez skrupulí vyrazí. U nás chceme, aby se lidi neustále vzdělávali, aby odborně rostli – oboustranně výhodná symbioza zaměstnance a firmy, chcete-li.

5)      Nebaví vás neustále před dokončením projektu kompletně přepisovat aplikaci, protože si zadavatel usmyslel, že je všechno jinak? U nás jsou zákaznící srozuměni s tím, co se objeví v každé verzi aplikace a co již ne, takže nemáte pocit, že vaše několikatýdenní práce je rozmetána rozmary zákazníka. Dohadování se zákazníkem je záležitostí projektových vedoucích a obchodníků, nikdy ne programátorů.

6)      Jsme autorizované certifikační středisko, a proto přímo u nás můžete získat odborné certifikáty (MCP, MCAD, MCSD, IBM certifikáty atd.). Firma hradí veškeré náklady spojené se získáním certifikace, navíc dostanete po úspěšném složení zkoušky jednorázovou finanční odměnu a po dobu platnosti certifikátu máte speciální prémie k platu. Za složení a hrazení certifikace nechceme žádné „ďábelské“  úpisy jako jiné firmy, ve kterých byste se zavazovali, že budete pro nás určitou dobu pracovat nebo že při odchodu z firmy náklady na zkoušku zpětně doplatíte.

7)      Samozřejmě vám nabídneme i dobré finanční ohodnocení (13. plat), stravenky a další maličkosti.:)

Jestliže tedy právě teď měníte zaměstnavatele, určitě se mi ozvěte na email rstein at digi-trade.cz. Pokud máte dotazy, nebojte se napsat do diskuze pod článkem.

Aktualizace: Adresa společnosti
DIGI TRADE
Vlkova 36, Praha 3
tel: +420 2 22722356
fax: +420 2 22722302
web:
http://www.digi-trade.cz

 



Wednesday, June 02, 2004 4:34:00 PM (Central Europe Standard Time, UTC+01:00)       
Comments [29]  Ostatní


 Monday, May 31, 2004
"Některé věci mají k sobě nepopsatelně blízko" - příkaz switch v jazyce C# a metoda String.IsInterned

Jazyk C# povoluje konstrukci switch, v níž se podmíněná sekce kódu zvolí podle shody proměnné typu string s konstantním řetězcem v sekci case.

 

switch (myVariable1 + myVariable2)

{

            case “sekce1”:

            {

                        //Zpracuj

break;

 }

case “sekce 2”:

           {

                        //Zpracuj

break;

}

default:

{

            //Nedelej nic

            break;

}

 

}

 

I když napsání swich výrazu s řetězcem je pro vývojáře jednoduchou záležitostí, zpracování switch výrazu kompilátorem již tak triviální není. Představte si, že porovnání shody řetězců by bylo prováděno znak po znaku. S prodloužením řetězců by docházelo k lineárnímu nárůstu doby potřebné pro porovnání řetězců. Jak asi ze své zkušenosti víte, příkaz case je vždy stejně rychlý bez ohledu na délku řetězců a k žádnému neohrabanému porovnávání řetězců znak po znaku v žádném případě nedochází. Jak je tedy příkaz case kompilátorem zpracován a rozvinut?

 

Všechny literály (string someString = “Ja jsem literal“) jsou při JIT kompilaci aplikace přidány do speciální hashovací tabulky vytvářené  a spravované běhovým prostředím, v níž klíčem je řetězec a hodnotou odkaz (reference, adresa v paměti) na tento řetězec. Podstatné je, že řetězec se stejnou sekvencí znaků se v tabulce vyskytuje nanejvýš jednou. Takže pokud nadeklaruji  kromě výše uvedené proměnné someString proměnnou  someString2  a inicializuji ji stejným řetězcem jako proměnnou someString ( string someString2 = “Ja jsem literal“)),  tak běhové prostředí při JIT kompilaci zjistí, že v hashovací tabulce klíč Ja jsem literal již existuje a proto do proměnné someString2 přiřadí odkaz na objekt umístěný pod tímto klíčem. Proměnné someString a someString2 odkazují poté na stejné místo v paměti, což si lze snadno ověřit voláním metody ReferenceEquals.

Z umístění do hashovací tabulky jsou při JIT kompilaci vyloučeny řetězce, jež jsou  konstruovány dynamicky za běhu programu. Takže řetězec v proměnné string someString3 = “Ja jsem literal“ + someString2 přidán nebude. Třída String má ale statickou metodu Intern, jejím účelem je dodatečné vložení řetězce a odkazu na něj do hashovací tabulky. Příkazem String.Intern(someString3) je do hashovací tabulky přidán obsah proměnné someString3.

Když  nechceme řetězec do hashovací tabulky přidat, ale chceme se jen dotázat, zda je v hashovací tabulce již obsažen, použijeme další statickou metody String.IsInterned. Metoda IsInterned při nalezení řetězce v hashovací tabulce vrací odkaz na tento řetězec. Když řetězec v hashovací tabulce není, metoda IsInterned vrátí null.

Nyní si už můžete sami odvodit, jak kompilátor efektivně zpracuje příkaz switch s řetězci.  Po přechodu na příkaz switch je zjištěn proměnný rozhodovací řetězec, podle jehož hodnoty mají být zvoleny sekce case (switch(myVariable1 +myVariable2) ). Poté je volána metoda String. IsInterned, jíž je předán jako argument rozhodovací řetězec. Když metoda vrátí null, je jisté, že žádná sekce case nevyhovuje rozhodovacímu řetězci, protože všechny řetězce u case sekcí byly přidány do hashovací tabulky při JIT kompilaci. Jestliže metoda vrátí odkaz na řetězec, je testována shoda vráceného odkazu s odkazy řetězců u jednotlivých sekcí case. Když se reference řetězců shodují, je zvolena daná sekce case. Porovnávány jsou jen adresy řetězců v paměti (odkazy, reference), nikdy ne jednotlivé znaky, a proto rychlost provedení příkazu switch není nijak determinována délkou řetězců.

 



Monday, May 31, 2004 8:39:00 PM (Central Europe Standard Time, UTC+01:00)       
Comments [5]  .NET Framework


 Thursday, May 27, 2004
O MDA iniciativě, nerozhodných tazích Microsoftu a klukách na pískovišti

Dnes jsem se zúčastnil konference Vývoj celopodnikových aplikací v .NET pořádané Microsoftem a společností LBMS. Na konferenci jsem se přihlásil, protože v pozvánce byla zmínka o MDA (Model Driven Architecture) a já byl zvědavý, jestli na této přednášce bude upřesněn nebo vyjasněn z mého pohledu zdráhavý až macešský vztah Microsoftu k MDA iniciativě.

Protože konference nebyla zaměřena jen na vývojáře, Honza Šeda v úvodu shrnul hlavní výhody .Net platformy a vyzdvihl její přínosy pro segment „Enterprise aplikací". Termín „Enterprise aplikace“ je dnes chameleónskou nádobou, do které si každý s gustem naleje své myšlenky a sny o extra projektu. Já používám pracovní definici, že Enterprise aplikace jsou  velmi složitá a drahá řešení, která se významně podílejí na podpoře kritických business procesů firmy a netolerují se u nich chyby ani výpadky:). Jinak řečeno, vývoj a podpora Enterprise aplikace je méně riskantní než kšeftování se zbraněmi, ale zase ne o tolik. :.)  Na zbraních ale určitě vyděláte víc.:)

Dle zkušeností z jiných konferencí, kde přednášeli partneří Microsoftu, jsem měl obavu, že i tato konference bude jen zástěrkou pro propagaci produktů společnosti LBMS.  Naštěstí tomu tak nebylo. Přednášející z LBMS shrnuli základní rysy a cíle MDA architektury a soustředili se na dominantní koncept PDA – rozvržení různých modelů jednoho systému na hypotetickém grafu, jehož jednou osou je míra izomorfie modelu s přirozenými pojmy z problémové domény a druhou stupeň připravenosti modelu na automatizované generování programového kódu. (Computation Independent Model, Platform Independent Model, Platform Specific Model, o Language Specific Modelu nic nezaznělo). Mapování mezi modely je řízeno exaktními pravidly, i když v přednášce jejich význam nebyl podle mě dostatečně zdůrazněn. MDA tedy nenechává například mapování z analýzy do systémového designu na naší intuici, ale vyžaduje, aby byla pravidla této „hry“ explicitně zachycena, a tím se stala kontrolovatelnými.

Firma LBMS prezentovala svůj produkt Select Component Architect podporující MDA. Hodnotit celou aplikaci zatím nemíním, protože jsme demo Select Component Studia dostali na osahání a reálná zkušenost je vždy věrohodnější než pozorování dobře drezúrovaného přednášejícího, který má instrukce, co z programu předvést, aby dychtivé publikum ohromil, a jaké nedostatky musí naopak taktně zamlčet.

Takže vztah Microsoftu k MDA je dost rozpačitý. Občas pronese silácké prohlášení o svém zklamání z UML a MDA, přičemž u MDA své zklamání spíše anticipuje nebo věští, protože mi uniká, jak se mohu zklamat v něčem, co si svoje místo  ve světě softwaru teprve hledá, a jindy zase podpoří své partnery, kteří na MDA a UML vsázejí. Beru to tak, že Microsoft hraje přetahovanou se svým hlavním rivalem  IBM  a občas si holt umanutě dupne, aby IBM pochopila, že koupí Rational Rose nedeportuje Microsoft na periferii hlavních trendů ve vývoji softwaru. Přejme to oběma firmám, i malí vzteklí kluci na sebe silácky pořvávají, ti tvrdší  s gustem přerazí o sebe i pár klacků, ale potom všichni svorně stavějí  po celém pískovišti zvelebující bábovičky.



Thursday, May 27, 2004 7:43:00 PM (Central Europe Standard Time, UTC+01:00)       
Comments [5]  Analytické drobky


 Wednesday, May 26, 2004
Svůdná asynchronní volání v ASP.NET 2.0

ASP.NET 2.0 ulehčí vývojářům práci nativní podporou asynchronních volání. V aktuální verzi 1.1 je prováděno pouze synchronní odesílání formuláře („postback“)  Při větším množství „postbacků“, které musíme používat například proto, že plníme některé serverové ovládací prvky podle uživatelem zadaných hodnot v jiných ovládacích prvcích, rychle odhalíme méně příjemné aspekty „postbacků“. Uživatelé, zvláště ti s pomalejším připojením, takové aplikace nepoužívají rádi, protože jim obrazovka neustále nepříjemně problikává nebo musejí nezanedbatelnou dobu čekat na nové zobrazení stránky.

 

Řešení je mnoho. Ti troufalejší z nás na stránce uloží všechna data bez ohledu na to, že každý uživatel využije jen malý zlomek. Podmíněné plnění prvků je zajištěno  JavaScriptem.  Nevýhodou je, že uživatelé zbytečně stahují do svého prohlížeče i data, která nikdy nepoužijí. Při větším objemu dat je toto řešení nepřijatelné.

 

Lepším řešením je například asynchronní volání WWW služby z JavaScriptu nebo využití objektu XmlHttp. Uživatel pracuje a aplikace na pozadí stahuje potřebná data ze serveru.

 

Do ASP.NET 2.0 bylo přidáno nové API pro asynchronní volání, které vývojáře zbavuje nutnosti znát detailně principy a způsoby zajištění  asynchronního volání. Interně ale toto API (alespoň v IE) stále pracuje s komponentou XmlHttp.

 

Jak nové API vypadá?

 

Serverový ovládací prvek musí implementovat rozhraní ICallBackEventHandler.

 

interface ICallBackEventHandler

{

string RaiseCallbackEvent(string eventArgument);

}

 

Metoda RaiseCallBackEvent přijímá jeden argument typu string s názvem eventArgument, který je zaslán z klientské funkce na stránce v prohlížeči. Může se jednat například o identifikátor kategorie, jejíž výrobky mají být načteny. Metoda RaiseCallBackEvent načte data, ať už z databáze, XML souboru nebo jiného datového zdroje, a ve formě řetězce je vrátí. Návratová hodnota metody je zaslána do prohlížeče, který ji zobrazí nebo jinak zpracuje.

 

Serverový ovládací prvek si při svém renderování vyžádá od stránky kód v JavaScriptu, který z klienta  asynchronně zavolá aplikační logiku na serveru. Do třídy Page byla přidána přetížená metoda  GetCallbackEventReference. Zde je jedna z jejích verzí.

 

GetCallbackEventReference(Control control, string  content, string  callback, string context);

 

V argumentu control  metoda dostane odkaz na serverový ovládací prvek, pro nějž chceme vygenerovat skript, argument content je názvem metody v JavaScriptu, která poskytne parametr (eventArgument), se kterým pracuje výše popsaná metoda RaiseCallBackEvent. V argumentu callback je název další funkce v JavaScriptu, které má být předán výsledek vrácený metodou RaiseCallBackEvent. Tato fukce se většinou postará o aktualizaci uživatelského rozhraní. V argumentu context je název proměnné v JavaScriptu, kterou používáme pro odlišení různých asynchronních volání. Hodnota proměnné context není nikdy zasílána na server, používají ji jen funkce na klientovi.

 

Naše funkce v JavaScriptu, jíž je předán výsledek asynchronního volání, musí mít tuto signaturu.

 

function NazevFunkce (raiseCallbackEventMethodResult, context)

 

Jak mnou zvolené názvy argumentů napovidaji, v prvnim argumentu je výsledek asynchronního volání a ve druhém obsah proměnné context v okamžiku zahájení asynchronního volání.

 

V jiné verzi metody GetCallbackEventReference lze zadat také název funkce v JavaScriptu, jež bude zavolána, když v metodě RaiseCallbackEvent dojde k výjimce.

 

A to je celý trik. V rychlosti zrekapitulujme, jak celý scénář probíhá. Metodou GetCallbackEventReference vygenerovaný klientský kód zavolá na klientovi metodu __doCallBack. Ta získá data z funkce „content“ a odešle je na server, kde běhové prostředí nalezne serverový ovládací prvek, jemuž jsou data určena, zavolá jeho metodu RaiseCallbackEvent a výsledná data zašle zpět na klienta metodě „callback“.

Do třídy HttpBrowserCapabilities byly přidány dvě vlastnosti, abychom si mohli při renderování ovládacího prvku ověřit, zda cílový prohlížeč asynchronní volání podporuje. Vlastnost SupportsCallback nese informaci o přítomnosti nebo absenci podpory asynchronního volání v prohlížeči, ale nesděluje nic o tom, jak jsou případná asynchronní volání realizována. Vlastnost SupportsXmlHttp sděluje, jestli prohlížeč pro asynchronní volání může použít objekt XmlHttp.

 



Wednesday, May 26, 2004 8:11:00 PM (Central Europe Standard Time, UTC+01:00)       
Comments [0]  ASP.NET


 Monday, May 24, 2004
Katalog PDA zařízení na MobilManii

Na Mobilmanii přibližně před týdnem spustili testovací verzi katalogu PDA zařízení. K dnešnímu dni v něm najdete kolem 35 zařízení s operačním systémem Windows Mobile nebo Palm OS. Mimo běžného zobrazení všech důležitých parametrů jednoho zařízení si můžete pro detailní srovnání zobrazit vedle sebe až tři zařízení, takže ihned máte například informaci, jak se cenově srovnatelná PDA od sebe liší. Už nemusíme shánět informace o vysněném PDA prosíváním vylučujících se informací na netu nebo se se svými dotazy obracet na většinou ve svém oboru nekompetentní prodavače či infantilně žvatlající "kikiny" na různých infolinkách (bílým vránám v těchto povoláních se omlouvám), ani bastlit v Excelu vlastní srovnávací tabulky.:)

Jestliže si nejste jisti, jaké PDA byste si chtěli koupit, ale máte alespoň matnou představu, k čemu by vám mělo sloužit, a neděsí vás pojmy jako bluetooth nebo WI-FI, tak si po zadání svých nároků na funkce nechte PDA doporučit.

Katalogu se dá vytknout jen to, že v něm nejsou zahrnuty komunikátory, tedy zařízení, která umějí nejen plnit roli kapesního počítače, ale lze z nich i telefonovat. Pod komunikátory jsou řazena hlavně zařízení s operačním systémem Symbian (SE P900), Palm OS (Handspring Treo) a Windows Mobile Phone Edition (MDA II). Pro tyto přístroje je na MobilManii vyhrazen  samostatný katalog. Hranice mezi mobilním telefonem, smartphonem, komunikátorem a "čistým" PDA je stále méně patrná, takže schopnost katalogu porovnávat zařízení všech typů by se hodila. I tak jde ale o velmi užitečnou službu MobilManie svým čtenářům.



Monday, May 24, 2004 8:29:00 PM (Central Europe Standard Time, UTC+01:00)       
Comments [0]  Mobilitky