Category Archives: Uncategorized

Paralelní běh pod kontrolou

Nedávno jsem si hrál se zátěžovými testy komunikace přes síť. Protože se nedal použít žádný standardní nástroj, byl jsem nucen naimplementovat paralelní běh několika vláken ručně. Naštěstí je součástí Javy od verze 5 balík java.util.concurrent, který nám práci výrazně usnadní.

Představme si situaci, kdy máme úkol, který je dobře paralelizovatelný. Například hodně malých nezávislých výpočtů nebo stažení hodně souborů po síti. Tyto malé úlohy chceme spustit paralelně proto, abychom naplno využili zdroje (všechny procesory, šířku přenosového pásma atp.) Zároveň ale chceme omezit počet vláken, které běží najednou, aby režie na správu vláken nebyla zbytečně velká. Nemá smysl spouště zároveň sto výpočetně náročných vláken, když máme jenom dva procesory. V Jave 5 máme k dispozici třídu Executors. Ta nám umožní vytvořit implementace rozhraní ExecutorService, určené ke spouštění vláken. Výše popsaný úkol vyřešíme jednoduše takto:



01 ExecutorService executor = Executors.newFixedThreadPool(8);//8 threads
02     for (int i=0;i<100; i++)
03     {
04       executor.execute(new Runnable(){
05         public void run() {
06           paralelTask();//neco co chceme spustit paralelne  
07         }
08       });
09     }
10     executor.shutdown();//prestane prijimat nove ukoly
11     executor.awaitTermination(60, TimeUnit.SECONDS);

Na prvním řádku si necháme vytvořit thread pool s osmi vlákny. Poté mu zadáme 100 úkolů ke zpracování. Implementace ExecutorService se už postará o jejich spuštění. Hlavní vlákno pokračuje v běhu dál. Pokud chceme počkat až na konec výpočtu, řekneme executorovi aby se začal vypínat (řádek 10). Executor tím pádem přestane přijímat nové úkoly, ale pokračuje ve vykonávání již zadaných. Počkat na jejich dokončení můžeme počkat pomocí metody awaitTermination. Té musíme říci, jak dlouho má na dokončení čekat. Pokud se vykonání do specifikovaného času nestihne, metoda awaitTermination vrátí false.

Už tam budem?

Právě jsem dokoukal záznam z přednášky Roda Johnsona s názvem „Už tam budem?“ (Are we there yet?) Vřele ji doporučuji, člověk se v ní doslechne mnoho zajímavých myšlenek.

Jak už název napovídá, celá přednáška měla být o tom, jestli už se Java vyvinula natolik, aby v ní bylo bezproblémové vyvíjet enterprise aplikace. Začíná zajímavým ohlédnutím do roku 2003, kdy jedinými masově rozšířenými open source projekty v Javě byly Struts a Log4j. Upozorňuje také na zajímavý posun v myšlení vývojářů. V roce 2003 panovalo přesvědčení, že na to, aby mohla být technologie úspěšná, musí být i komplexní. Dnes už tomuto věří málokdo.

Dle svého zvyku se přednášející obouvá do EJB. Hlavně do jejich snahy skrýt některé věci před vývojáři (pooling, starání se o vlákna atp.) Zaujaly mě následující hlášky

Když se k vývojářům budeme chovat jako k opicím, jediné co dostaneme bude tlupa naštvaných opic.

Je zásadní chybou definovat infrastrukturu a architekturu s tím, že architekti a vývojáři jsou hloupí.

Tento problém nemají jen EJB, setkáme se s tím i u všelijakých vlastnoručně psaných frameworků. Podle Roda Johnsona se omezením kreativity vývojařů o hodně připravíme. Toto téma vede k zamyšlení nad standardy a specifikacemi. Dovolím se opět ocitovat

Specifikace dobře pochopených problémů jsou úspěšné.

Je snadné standardizovat něco, co se za dvacet let nezměnilo.

Evidentními příklady jsou JMS, JTA a JNDI. Jsou to věci, které v době jejich specifikace byly dobře prozkoumány a jejich standardy jsou tím pádem úspěšné. Naproti tomu standardizování věcí, které ještě nejsou dobře prozkoumány vede k problémům (např. entity beany)

Zásadní myšlenka zazněla přibližně uprostřed prezentace.

Většina Java aplikací není objektově orientována.

Nejprve mě to překvapilo, ale pak jsem si uvědomil, že má pravdu. Uvědomme si, že objekt je cosi co seskupuje data a chování do jedné entity. Podíváme-li se na klasickou třívrstvou Java aplikaci, zjistíme, že tříd, které by měly obojí je tam minimum. Máme servisní vrstvu, která je obvykle bezstavová a kromě konfigurace v sobě moc dat nemá. V podstatě obsahuje jenom chování. Na druhé straně pak máme doménový model, který obvykle jenom drží data a neobsahuje žádné chování. To je zajímavé. Všichni tvrdíme, že OOP je dobrý nápad, ale přesto programujeme více méně procedurálně. Připravujeme se tím o spoustu výhod, které nám OOP nabízí.

Obchodní logika v servisní vrstvě není znovupoužitelná.

Co s tím? Řešením je přesunout logiku do doménových objektů. Tzn. místo toho abychom měli službu, která zaregistruje mazlíčka u veterináře, mít příslušnou metodu přímo u třídy reprezentující veterináře. Narazíme zde ale na jeden problém. Jak nainjektovat podpůrné služby do doménového objektu? Přes Spring to nejde, doménové objekty jsou obvykle instanciovány OR nástroji. Řešením je AspektJ. Napíšeme si malou anotaci (nebo XML konfiguraci) a můžeme injektovat přímo do doménového modelu. Pan Johnson tvrdí, že se tím výrazně zvýší znovupoužitelnost kódu.

V poslední části prezentace uvidíme zajímavou studii interceptorů v EJB 3. Zde se autoři specifikace nepoučili ze zkušeností AOP aliance a rozhodli se, že si problém AOP vyřeší po svém.

Ve skutečnosti nezáleží na tom jak je člověk chytrý, když mu chybí zkušenost.

U EJB 3 máme AOP bez pointcutů. Tzn. jediný způsob jak určit, kdy se interceptor zavolá, je přidat ke třídě nebo metodě příslušnou anotaci (nebo se vrhnou do ekvivalentní XML konfigurace). Není možné říci například, že chci mít interceptor kolem všech metod v tomto balíku. To je přinejmenším nepohodlné. Není možné říci, že chci volat interceptor jen u metod, které mají parametr daného typu. To už je i náchylné na chybu.

EJB interceptory jsou experimentální.

Ano, ještě nikdo nikdy nezkoušel dělat AOP bez pointcutů. Dá se očekávat, že se přitom narazí na problémy.

A jak zní odpověď na otázku v názvu prezentace? Dovolím si zde použít citát z Murphyho zákonů

Končí-li novinový titulek otazníkem, zní odpověď “ne”.

Zbývá ještě dost problémů, které je třeba v Javě vyřešit, než budeme moci říci, že vývoj enterprise aplikací je v ní bezproblémový.

Upozornění: V tomto příspěvku se mísí citáty Roda Johnsona s mojí interpretací. Netvrdím, že všechno co zde píši řekl, je to spíš o tom co jsem si z toho vzal já. Pokud chcete informace nezkreslené, vřele doporučuji originál.

Tabulka v Javě

Ahoj, jmenuji se Lukáš a napsal jsem si tabulku. Opravdu, v dnešní době frameworků, knihoven a jiných hotových řešení jsem se neudržel a podlehl jsem pokušení napsat si tříditelnou, filtrovatelnou a stránkovatelnou tabulku. Jenom tak, jen s pomocí JSP a Springu. I když je to neodpustitelná hloupost, pokusím se o chabou obhajobu.

Asi bych začal tím jak to všechno začalo. Píší docela zajímavou aplikaci a v analýze jsem narazil na to, že si zákazník přeje prohlížet audit log uložený v databázi. Takže v celé aplikaci je jenom jedna tabulka. Navíc mám za vzor aplikaci pro stejného zákazníka, kde už je hotový layout, styly a i vzor JSP. Nabízejí se následující řešení

Pozměnění existujícího řešení

Touto cestou jsem se vydal. Nicméně stávajícímu řešení jsem příliš nerozuměl, nenaplňovalo moje požadavky a neodolal jsem nutkání si ho vylepšit. Takže nakonec zůstala zachována jenom kostra JSP stránky. Tudíž se to rovná napsání si od píky něčeho, co by už dávno mělo být nějak standardizováno. Trvalo mi to sice jenom asi půl dne, ale nepochybuji, že v .NETu by to nebylo na víc než na půl hodiny.

Použití knihovny

Řešení, nad kterým jsem uvažoval, ale nepovažoval jsem ho za nutné kvůli jedné hloupé tabulce. Podívejme se na to co se nám pro Javu nabízí.

Displaytag

Displaytag je osvědčená knihovna určená pro zobrazování tabulek. Má ale problém s rozsáhlými daty. Standardně provádí stránkování a třídění v paměti. To v mém případě nepřichází v úvahu, protože log bude mít záznamů opravdu hodně.

Valuelist

Valuelist byla moje oblíbená knihovna. Implementuje design pattern valuelist a je přímo dělaná na rozsáhlá data. Pěkné na ní je to, že umožňuje pomocí konfigurace nastavit čtení dat přímo z databáze a to v případě potřeby i za použití Hibernate. Sice tím porušujeme rozdělení na vrstvy, ale na malé aplikace nebo prototypy k nezaplacení. Její nevýhodou bylo to, že nebyla příliš rozvíjena. Nicméně vypadá to, že se situace zlepšila a nějaký vývoj přece jenom probíhá. Tuto knihovnu jsem nepoužil jenom proto, že ji nazná nikdo z kolegů, což je z pohledu dalšího vývoje problém. Ale pokud hledáte pro komponentu na vykreslení tabulky, doporučuji vzít Valuelist v úvahu.

Extremecomponents

Extremecomponents je knihovna, kterou používáme u nás ve firmě. Má jednu velkou nevýhodu, neznám ji já. Odhadl jsem tedy, že si to sám napíši rychleji, než se ji naučím.

JSF

Kromě toho že to je řešení stylu kanónem na vrabce, nejsem si jistý, jestli existuje rozumná, lehce dostupná komponenta, který by splňovala všechny požadavky. Navíc křivka učení JSF je opravdu hodně strmá. Kvůli jedné tabulce se mi po ní šplhat nechtělo.

Co z toho všeho plyne? Prostě mi v Javě chybí všeobecně uznávané a známé řešení tohoto jednoduchého a standardního problému. Zatímco existuje spousta knihoven, které umějí snadno a rychle tabulku vykreslit, pro nižší vrstvy je řešení necháno na tvořivosti programátora. Neznám žádný standard na to jak předávat hodnoty filtru, stránkování a třídění. Proto si každý více či méně úspěšně píše třídy na to, aby uměl business logice říci, že chce záznamy 10-19, takové které jsou z letošního roku a mají typ 8. To je podle mě škoda, je to problém, který programátoři řeší denně.