pondělí 29. prosince 2008

AJAX reloaded

Blíží se konec roku a to mi nedá zpětně se podívat, na některé názory, které jsem zde prezentoval. Dlouhou dobu jsem byl přesvědčen,že erá AJAXu splaskne jako bublina. Postupem času musím uznat, že AJAX rozhodně nesplasknul, ale došlo k tomu, že tvůrci aplikací si uvědomili jak jej šikovně skloubit s modelem webu.

Jsem již dalek detailně hodnotit technické možnosti dnešních prohlížečů, ale z povzdáli se mi zdá, že většinu těch zásadních problémů se podařilo vyřešit. Existují knihovny, které jak na straně serveru, tak především na straně klienta pomáhají s AJAXem pracovat celkem pohodlným způsobem z těch orientovaných na Javu vzpomenu DWR či GWT.

Kolem AJAX vznikly další prostředky, které se staly defacto webovými standardy jako je například formát přenášených dat JSON. V oblasti webových frameworků snad nenajdeme jeden jediný, který by nedeklaroval alespoň základní integraci s AJAXem. Oficiální JEE technologie pro web, tedy JSF (Java Server Faces), byla ve verzi 2.0 rozšířena přímo o podporu AJAXu resp. úpravu specifikace, která by měla umožnit lepší integraci.

AJAX se stal regulérní součástí pro tvorbu dnešních webových aplikací. Skoro se zdá, že pozice AJAXu bude neotřesitelná pro typ webových aplikací, tak jak je známe dnes. Tedy typ, který souvisí s vnímáním čehokoliv co běží uvnitř prohlížeče. Pak je AJAX, narozdíl třeba od jiných RIA technologií, přirozeným doplňkem webu a ne "umělým implantátem" (tím rozhodně neupírám těmto technologiím jejich případy užití).

pátek 26. prosince 2008

Mé alternativní zápisky

Po určité době používání služby Twitter ji považuji jako vhodný doplněk k tomuto blogu. Ostatně integrace je již nějaký ten pátek vidět v pravém sloupci viz obrázek. Síla Twitteru je v tom, že můžu velice jednoduše publikovat zajímavé postřehy a věci co právě řeším. Tedy sdělení, která svým obsahem nevydají na plnohodnotný spot, alespoň v první fázi, ale zase je škoda, aby někde zapadly. Rozměr sociální sítě (zdravím Budíka) dodává Twitteru to, že zároveň můžu podobné zápisky sledovat u dalších lidí. Takže vidím co zaujalo či co řeší Filemon, Borůvek, NkD, Satai a další zajímaví lidé.

Pokud chcete tyto moje alternativní zápisky sledovat a jste již a nebo se chystáte na Twitter, pak můj nickname je _dagi (to podtržítko tam skutečně je). Druhou možností je zmíněný scriplet vložený do pravého pruhu.

čtvrtek 25. prosince 2008

Cosi nevyřešeného nad Servlet specifikací

Asi nejsem sám, kdo považuje Servlet specifikaci jako nejzásadnější věc v JEE oblasti. Je to již celkem, co prosákly první informace o připravované verzi 3.0 standardizované pod JSR 315. Dnes jsem na InfoQ našel článek odkazující na debatu kolem vydaného Public Review (odkazuje stav specifikace) a nedobrý pocit se mě zmocnil.

Již mnohokrát se ukázalo, že není nic horšího než složitá specifikace postavená na předpokladech a tezích úzké skupiny lidí bez dostatečného reálného podkladu, EJB budiž mementem. Věřil jsem, že tohle období máme za sebou. V expertních skupinách (lidé zodpovědní za doručení specifikace) totiž začali zasedat lidé, kteří měli s Enterprise Javou reálné zkušenosti. Jedním z těchto garantů pro mě je Greg Wilkins, autor servlet kontejneru Jetty.

Proto mě nepříjemně zamrazilo, když tato mnou respektovaná osoba napíše v reakci Public review JSR 315 následující řádky:

JSR-315 has produced a Public Review (PR) of the servlet 3.0 specification, which unfortunately is a poor document and the product of a discordant expert group (EG) working within a flawed process.

Greg Wilkins dále velice správně a výstižně poukazuje na další fakt:

The API decided by JSR-315 will be with us for many years to come and will affect the evolution of java web applications and potentially the rest of our programming careers.

Je to přesně tak, a každý kdo kdy pracoval s JEE na tento fakt musí poukázat. Servlet API je tak zásadním API, že jakékoliv hazardování při jeho rozšiřování může mít dalekosáhlé následky. Wilkins dále poukazuje na další problémy jako vedlejší či pomalý deployment a nebo nejasné pořadí konfigurace v deployment descriptoru webové aplikace.

Jeho postřehy pro mě mají daleko větší váhu než kód kdesi ve vývojové větvi serveru GlassFish. Při vší úctě k odpovědím, které poskytnul spec lead Rajiv Mordani, to ve mě vyvolává obavy. Budeme mít nafouknutější specifikaci, která bude plná vágních formulací? Usnadní nám to opravdu život? Proč se snaží tuto specifikaci tak rychle dokončit, tlačí je snad rámec JEE 6?

Pokud specifikace obsahuje takové otazníky, tak je dle mého názoru lepší držet se hesla, že "méně je někdy více", už jenom například z důvodů zpětné kompatibility. Specifikace se dá rozšířit vždy, ale něco z ní vyškrtnout je problém. Ač si co do možností myslím o JPA specifikaci své, tak se jí musí nechat, že nebyla přehnaně ambiciózní, prakticky se inspirovala v Hibernate a nekonal se tak "pokus na vývojářích". Servlet 3.0 by se měla vydat stejnou cestou, jedná se totiž o tak zásadní věc, že jakýkoliv experiment může mít dalekosáhlé následky.

Na závěr přidávám jeden z komentářů na TheServerSide:

The Java community should realize that this is one of the few ways we can really "break" Java.

Many other blunders, such as EJB, have not been very important. The usage of many packages was specialized and restricted anyway. Servlets, though, are the common starting point for Web development in Java. At present they are easy to understand and implement. If you screw up servlets and make them hard to understand or implement, you'll lose the Java development community much faster than you might think is possible.

pondělí 8. prosince 2008

JBoss Microcontainer

V souvislosti s releasem aplikačního serveru JBoss verze 5 (po třech letech - neuvěřitelné!) jsem narazil na subprojekt JBoss Microcontainer. Jedná se o samostatný, na aplikačním serveru nezávislý, kontejner, který kromě IoC, které se samo nabízí, poskytuje například podporu AOP a deployment rozličných komponent OSGi bundly počínaje, přes staré MBean až pro JARy se Spring či Guice objekty konče. Pokdu se ptáte, jestli bude tyto modely kombinovat, pak odpověď je

Yes, and that's the beauty of it. Since all the components in JBoss irrespective of type (POJOs, MBean, Spring Beans, OSGi bundles, etc.) share the same back-plane they have the potential of being wired together by the MicroContainer with dependencies and aspects applied across the different component models. We are still at the early stages of understanding the capabilities and limits of the MicroContainer technology, designed by our mastermind Adrian Brock, but the possibilities look certainly very interesting.

Takhle na papíře to vypadá interesantně. Jenže ta představa, že to míchám všechno dohromady, OSGI bundly a POJO popsaná v Springu a Guice, ve mě vyvolává trochu obavu, aby to nedopadlo stejně jako když pejsek a kočička vařili dort. Navíc to co vypadá jednoduše pro jednoduché případy nemusí fungovat pro ty složitější, na které narazíme skoro vždy...

Na druhou stranu je dobře, že další aplikační server podporuje OSGi jako deployment model. Výčet těch dalších najdete v článku OSGi in the Enterprise.

Zdroje

středa 3. prosince 2008

Zase jsem se rozčílil

Opravdu jsem sám, komu přijdou EJB 3.1 pouze a jenom jako pokrok v intencích z bláta do louže? Nemyslím to nijak špatně, louže mi přijde lepší než bláto, ale jako radikální pokrok mi to nepřijde. Problém EJB je, že se nikdy nedokáže zbavit stigmatu "my víme co je pro vás nejlepší a pokud si to nemyslíte, tak děláte něco špatně". Zase jsem se rozčílil při čtení článku EJB 3.1 – EJB New and Improved!. Budu nesmírně rád když EJB bude jednou technologií inovující nikoliv technologií, která se snaží dohánět dávno ujetý technologický vlak. Bohužel.

Asi nejvíce mi vadí ta neschopnost pochopit, co jsou základní požadavky na DI či chcete-li IoC kontejner. Myslím si, že to je krásná ukázka toho, že lidé kolem EJB stále nechápou, co znamená nevtíravost (neinvazivnost) komponentového frameworku. A to přesto, že jim to Rod Johnson vysvětlil ve své knize J2EE Design and Development skoro před pěti lety. Ba co více, za tu dobu zhmotněním této myšlenky udělal fantastickou karieru.

Jedinou spásou EJB může být pokud dožene to co je jinde běžné a navíc přidá něco navíc. To něco navíc může být například OSGi a nebo nějaká forma hot deploymentu. Jinak bude trvale odsouzenu k standardního leč druhořadého příbuzného...

úterý 25. listopadu 2008

G1 nový grbage collector pro Javu 7

Pro Javu 7 je připraven z brusu nový typ garbage collectoru (dále GC) nazývaný G1 (Garbage First), který slibuje přiblížení chování GC k soft real-time. Kromě předpovídatelnějších přerušení běhu aplikace by mělo být dalším cílem omezení častého úplného uklizení heapu (po tuto dobu aplikace nemůže reagovat) a třetím je snížení vlivu GC na výkon aplikace. G1 se od stávajících GC odlišuje organizací a způsobem správy paměti.

Zatímco klasické Hot Spot GC jsou typu Concurrent Mark-Sweep se striktně rozděleným heapem na oblast generací - young, tenured (vychází se z předpokladu, že mladé objekty umírají dřívěji. Pokud objekt přežije několik úklidů, posune se do oblasti zasloužilých objektů, kde nedochází k úklidu tak často). G1 toto rozdělení nemá striktní. Paměť je místo toho rozdělena na relativně malé regiony. G1 tyto regiony prochází a ty s nejvíce mrtvými objekty uklízí, přeživší objekty jsou kopírovány do dalších regionů.

Dříve než vás odkážu na místa, kde dostanete další informace ke G1, doporučuji prolétnout prezentaci Garbage Collection-Friendly Programming, která je plná užitečných tipů a uvádí na pravou míru mýty např. o užitečnosti rušení referencí na objekty a nebo o poollingu objketů.

Další informace ke G1

úterý 18. listopadu 2008

Glosa: Týmová chemie

Vojín Kefálín čo si tak predstavujete pod pojmom týmová chemie? Každý kdo hrál někdy nějaký kolektivní sport určitě ví o čem mluvím. Rád hledám paralely mezi světem sportu a světem softwarového vývoje a jedna z oblastí, kde je vidět krásný překryv je tým, jeho vztahy a fungování. Jinak též ve sportu věc běžně nazývaná jako týmová chemie.

S týmem fotbalovým je to stejné jako s partou vývojářů. Můžeme vyskládat tým s blyštivých jmen, jako se to svého času snažil Real Madrid, ale to nám nezaručuje úspěch, pravděpodobně dopadneme jako sedláci u Chlumce. Stejně tak v týmu softwárových vývojářů musíme nutně dbát na to, aby zde byli zástupci všech typů.

Musíme mít dělníky pole na černou práci, kteří to lidově řečeno odjezdí po zadku. Ty jsou, stejně jako ve fotbale, daleko méně doceňováni než by si zasloužili. Zároveň potřebujeme dribléry a špílmachry, kteří dají hře myšlenku, řád a přitáhnou oko diváka. V přeneseném slova smyslu to znamená, že potřebujeme lidi, kteří přinesou něco navíc. Každý tým potřebuje svoje vůdce alias leadry, na jejichž bedrech spočívá ta tíha okamžiku v klíčových fázích zápasů. V případě softwarového vývoje, to je ulehčené v tom, že rozhodnutí se nemusí činit ve zlomcích vteřin. Stejně tak každý tým potřebuje svého manažera alias trenéra, který určuje jaká je každého úloha kdo bude co během releasu alias zápasu dělat.

Lidé v týmu si musí sednout lidsky, proto občas v novinách čteme, že někoho "kabina" nepřijala. Občas zaslechneme nepsané pravidlo, že "kabinu" si dělají starší hráči. Stejně tak v softwarovém týmu ti starší a zkušenější dávají nováčkům nutné rady do života a starají se o integraci nových členů týmu. Někdy je to rada jak zrovna nastavit IDE, jindy ukázka zajímavé technologie nebo debata nad zajímavým problémem, kterým je člověk vtáhnut do dění v týmu.

Nejenom čutáním nebo klapáním na klávesnici živ je člověk. Proto po sezóně nebo po důležitém zápase dochází takzvaně k vypuštění páry což je pouhý eufemismus pro nezřízenou pijatiku ve stylu - kurvy, chlast a chlebíčky. To se hráči či vývojáři sejdou nad žejdlíkem piva, společně zanadávají a nebo zajuchají v závislosti na předchozím výsledku. Výsledkem je pročistění atmosféry no a další den je čeká trénink či rachota. Týmová chemie je prostě všude stejná...

sobota 15. listopadu 2008

Sun zeštíhluje

Necítím se být úplně povolaným komentvat jakékoliv dopady současné finační krize, ale vypadá to, že by se tato krize mohla dotknout i samotné Javy. Ne není to myšlenka tolik utopická, jak by se mohlo na první pohled zdát, obzvláště pokud zvážíme, oznáméní Sunu o celkovém zeštíhlení společnosti o 5000-6000 zaměstnanců, restrukturalizaci softwárové divize a odchod R. Greena (CTO pro software). Co to všechno může pro Javu znamenat.

Byl to právě Green, který byl hlavním hybatelem mohutného otevření (open source) Javy. Jeho odchod zřejmě nebude přímo znamenat ukončení pokračování tohoto procesu, ale může dojít k jeho zpomalení a to by Jave určitě nepomohlo. Vlastní propouštění zaměstnanců může být dvousečné. Může znamenat, že část ušetřených peněz bude použita pro posílení R&D kolem Javy a nebo naopak, že softwarové divizi Sun pustí žilou a na Jave jako takové bude pracovat méně lidí.

Dalším nepříjemným faktem může být jistá frustrace či rozčarování ze současného stavu firmy Sun u samotných zaměstnanců, kteří stojí za Javou. Pak by mohl pokračovat exodus těch schopných a talentových do firem jako Google či Microsoft. Právě ztráta těcto klíčových mozků se může ukázat jako nejvážnější problém.

Nezastávám názor, že budoucnost Javy je nezávislá na budoucnosti Sunu. Díky open source procesu kolem a JCP (proces rozšiřování Javy) se stala Java méně závislá na Sunu jako takovém, ale pořád je s ním spojená doslova pupeční šňůrou. Pokud by musel Sunu tuto šnůru lidově řečeno přiškrtit, musel by se najít jiný garant, který by převzal roli Sunu. Často se mluví o IBM jako o koruním princi, ale ja zatím vidím ve všech klíčových věcech (runtime, vývojové nástroje, podpora komunity, vedení zásadních JCP - EE, SE) jasnou pozici Sunu.

Pokud by se tak stalo a IBM by tuto roli převzalo resp. by jí bylo nuceno převzít, nebyla by to rozhodně skoková změna. IBM by muselo více investovat do Javy a to především personálně. Rozhodně nejsem v tomto směru optimista a myslím si, že ačkovliv tu jsou další silné firmy, oslabení pozice Sunu by mělo bohužel zásadní vliv na Javu.

pátek 14. listopadu 2008

CZ Podcast 28 - QA

Další podcast je tu, tentokrát na zajímave téma QA. Důvodů poslechnout si tenhle podcast je celá řada: zkratka QA vám nic neříká, tohle oddělení z duše nesnášíte a nebo chcete začít dělat "kvalitu", ale nevíte vlastně jak. My jsme pro Vás vyzpovídali Lukáše Hasíka (QA NetBeans) a výsledkem je, a to říkám bez nejmenší známky chvástalství, jeden z nejzajímavějších podcastů, které naše partička dala dohromady.

úterý 11. listopadu 2008

Spring nabyl Groovy a Grails

Rod Johnson právě oznámil akvicizi společnosti G2One stojící za dynamickým jazykem Groovy a Grails.

Groovy has unique benefits as a dynamic language on the Java platform. It’s the only dynamic language that can compile directly to Java .class files; it’s the only language that can be used mixed seamlessly with Java; it’s currently the only language that can process Java annotations, which are becoming central to modern use of Java; and it has a natural migration path from Java, rather than calling for a big, risky leap of faith. It’s also a promising language for implementing DSLs—an increasingly important issue.

Like Spring, Grails is a technology that simplifies the lives of developers and makes them more productive. As our new tagline, Weapons for the war on Java complexity, reflects, simplification has always been core to what we’ve done as a company and as technologists. The values behind Grails are the values behind Spring and SpringSource.

Skvělá zpráva pro všechny uživatele těchto technologií. Jak dále Johnson podotknul, SpringSource může například poskytnout svoje odborníky na podporu v nástrojích jako Eclipse. Díky tomu, že Spring framework měl integraci s jazykem Groovy a Grails zpětně se Springem, tak můžeme očekávat její další prohloubení.

Související linky

středa 5. listopadu 2008

JSF nemá mou důvěru

K tomuto zamyšlení mě vyburcovalo přečtení článku JSF vs. Tapestry - jak jednoduché je dělání komponent a letmé nahlídnutí do JSF specky 2.0 (zdroj JavaServer Faces 2.0 Composite Components). Nevím jestli se tomu dá říkat předpojatost, možná ano, možná ne, ale technologie JSF ve mě prostě nebudí důvěru. A mám k tomu několik pádných důvodů.

JSF byly od počátku přesně tím typem specifikace v Jave, který jasně ukazuje, jak se to nemá dělat. Není možné si říci, my teď potřebujeme komponentovou technologii pro vývoj web aplikací, tak si něco vymyslíme. To už ukázaly jiné specifikace v JEE, že tohle prostě nefunguje, protože lidé ve skutečnosti chtějí trochu něco jiného. Příklad JSF jasně ukazuje, že ve verzi 1.0 jsou uživatelé dané technologie spíše v roli pokusných králíků.

Mluvím o tom v každé své prezentaci otírající se o JEE, základním nepochopením lidí, kteří JEE tvořili (doufám už v minulém čase), bylo to, že je potřeba, aby technologie byla jednoduchá a použitelná. Většina všech webových aplikací, neřkuli všechny, řeší ty samé problémy. Proto musí být základní charakteristikou každého web frameworku to, že umožní tyto problémy řešit jednoduše.

K čemu je webový framework řešící problémy třetího světa (nadneseně řečeno), když v něm nejde jednoduše udělat vlastní komponenta. Přijde mi jako utopie spoléhat na nástroje, které by nás měly od této komplexnosti odstínit. Vývojáři neradi spoléhají na magické skříňky, které jim pod rukami generují tuny kódu. Je to vcelku pochopitelné a vychází to z dobře známých důvodů.

Další věcí k zamyšlení je, jestli opravdu odstínění od principu webové aplikace požadavek/odpověď je to co při vývoji webových aplikací potřebujeme. Opravdu nám vyšší abstrakce přinese tolik výhod oproti tomu, o co přijdeme? Má smysl zakrývat základní paradigma webu a tvářit se, že webovou aplikaci lze stavět podle podobných principů jako tu desktopovou? Osobně tuhle víru ztrácím. Položme si otázku, mají něco podobného technologie jako PHP či Ruby on Rails. Pokud ne, proč asi...

Poslední, ale rozhodně ne nejméně důležitý fakt představuje faktor inovace či agilnosti. JSF 2.0 po jejich finálním vydání zůstanou zakonzervované nějaký ten pátek. Oproti tomu jakýkoliv proprietární (nestandardizovaný) framework může relativně pružně reagovat na aktuální potřeby. Přidávání nových vlastností do čehokoliv standardizovaného je prakticky nemožné a pokud je to vůbec možné, tak ve většině případů ztrácíme přenositelnost. U proprietárních frameworků tohle prostě a jednoduše nehrozí.

úterý 4. listopadu 2008

Spring a jeho další směřování v enterprise oblasti

V rozhovoru SpringSource Elected Newest Executive Member of the Java Community Process poodkrývá Rod Johnson další budoucnost Springu a jeho další směřování v JEE oblasti. To co se dalo číst mezi řádky vyplouvá v tomto rozhovoru na hladinu. To nejdůležitější co jsem si odnesl odpovídá v podstatě tomu, co si již dávno myslím.

  • PHP, Ruby on Rails, .NET je potřeba brát jako seriózní hrozbu. JEE platforma a nejenom ona se musí neustále rozvíjet jinak zanikne. Není možné se neustále spoléhat na silné stránky jako škálovatelnost či spolehlivost, protože ty mohou být v relativně blízkém čase i v konkurenčních technologiích. Inovace je potřeba, stejně jako kopírování osvědčených postupů. Základním cílem je výrazné zjednodušení používání JEE.
  • Spring nebo mnohem přesněji SpringSource dm Server je alternativou se vším všudy k tradičním JEE serverům jak je známe. Velkou sázkou je OSGi, které zatím představuje dle mého soudu největší riziko, protože ovlivňuje návrh aplikace, její rozčlenění (packaging), vývoj i deployment.
  • SpringSource dm Server je jasným důkazem toho, že SpringSource (společnost stojící za Springem) snaží zaměřit na runtime a stát se plnohodnotným middleware dodavatelem. Ostatně je to logické, to je oblast, ze které tečou peníze. Proto nepřekvapí prohlášení o tom, že SpringSource dm Server bude JEE 6 implementace minimálně na úrovni web profilu.
  • Tím, že se SpringSource stal členem JCP (Java Community Process) může ovlivňovat rozhodnutí, která se mu hodí do krámu. To může být například adopce právě OSGi jako dalšího deployment modelu.

úterý 28. října 2008

Eclipse tipy a triky: statické importy

Kolikrát jen už jsem napsal při psaní testů import static org.junit.Assert.*, abych pak mohl někde v testovací metodě napsat assertThat a nadávat si, že ještě musím naimportovat další statické metody. Samozřejmě to jde mnohem jednodušeji. Eclipse umožňuje přidat si metody předdefinovaných typů do content assist a ty potom nabízet aniž by byl typ v dané třídě naimportován. Při jejich použití se pak import automaticky nadeklaruje v dané třídě.

Postup je následující: Window >> Preferences >> Java >> Editor >> Content assist >> Favorites. Favorites menu nabízí přidání celého typu, resp. všech jeho statických metod viz tlačítko New Type, a nebo pouze vybraných metod viz tlačítko New Member.

pondělí 27. října 2008

Problém "Božského objektu"

Setkal jsem s ním snad v každé aplikaci, ale teprve teď jsem proto našel ten správný výraz - God object.

a God object is an object that knows too much or does too much

Mluvím o objektu, který plní stěžejní úlohu v celé aplikaci, něco jako centrální mozek lidstva ze seriálu Návštěvníci. Problém tohoto objektu je v tom, že neustále bobtná, výsledkem je, že máme interface s dvaceti a více metodami, což jednoduše nepřidá na přehlednosti našeho API a to už ani nemluvím o jeho implementaci.

To, že v aplikaci existuje nějaká business fasáda, která zastřešuje vícero operací je myslím v pořádku. To co většinou nebývá v pořádku je jakým způsobem je tato fasáda vytvořena a především naimplementována. Pomůžeme si praktickým příkladem.

public interface ObjednavkovaSluzba {
    public void vytvorObjednavku(Objednavka objednavka);
    public void smazObjednavku(Objednavka objednavka);
    public void aktualizujObjednavku(Objednavka objednavka);
    public Objednavka nactiObjednavku(Serializable identifikator);
    
    public void zpracujObjednavku(Serializable identifikator);
    public void zrusObjednavku(Serializable identifikator);   
}    

Jak je vidět z rozhraní, míchají se nám tam dvě odpovědnosti (většinou to bývá i více odpovědností nežli dvě). Jednak samotné CRUD (Create, Read, Update, Delete) operace pro vytvoření objednávky a jednak operace pro zpracování objednávky. Logika věci nám velí rozhraní roztrhnout, ale jak to udělat, aby zde byla stále možnost jednoho centralizovaného rozhraní pro práci s objednávkami.

Je to velice prosté. Opravdu to roztrhneme na dvě rozhraní podle odpovědností, ale rozhraní ObjednavkovaSluzba zachováme. A zachováme ho tak, že bude složením právě těchto dvou rozhraní.

public interface CRUDOperace {
    public void vytvorObjednavku(Objednavka objednavka);
    public void smazObjednavku(Objednavka objednavka);
    public void aktualizujObjednavku(Objednavka objednavka);
    public Objednavka nactiObjednavku(Serializable identifikator);          
}   

public interface ProcesniOperace {    
    public void zpracujObjednavku(Serializable identifikator);
    public void zrusObjednavku(Serializable identifikator);   
}  
 
public interface ObjednavkovaSluzba extends CRUDOperace, ProcesniOperace {
       
}        

Díky tomuto roztržení umožníme klientům využít nejen různé pohledy na jednu fasádu (CRUD, procesní operace a nebo celek), ale umožníme mít implementaci náležející plně dané odpovědnosti. Výslednou funkcionalitu můžeme dosáhnout například složením a delegací těchto implementací.

public class CRUDOperaceImpl implements CRUDOperace {
  //...implementace vynechána
}    

public class ProcesniOperaceImpl implements ProcesniOperace {
  //...implementace vynechána
}

public class ObjednavkovaSluzbaImpl implements ObjednavkovaSluzba  {
  private CRUDOperace crudDelegate;
  private ProcesniOperace procesniDelegate;
  
  public void vytvorObjednavku(Objednavka objednavka) {
      crudDelegate.vytvorObjednavku(objednavka);       
  }  
  
  public Objednavka nactiObjednavku(Serializable identifikator) {
      procesniDelegate.nactiObjednavku(identifikator);
  
  
  //...zbytek vynechán

Tímto velice jednoduchým cvičením jsme náš Božský objekt dekomponovali na menší části, které můžeme lépe spravovat, ale zároveň jsme zachovali jednotné rozhraní, které zaštiťuje práci s centrální funkcionalitou. Takto zrefaktorované rozhraní je navíc pro klienty API zpětně kompatibilní, takže se nemusíme obávat, že bychom něco rozbili.

neděle 26. října 2008

Java SE 6 Update 10 venku

Po roce čekání a více než miliónu stažení (viz Java SE 6 Update 10 is out but what does it deliver?) beta verze je venku dlouho očekávaný update číslo deset.

Podle označení by se zdálo, že se jedná pouze o fix pack, nicméně seznam úprav odpovídá spíše pořádnému třesku. Nejzásadnější změnou je nový plug-in systém, který umožňuje lepší běh a deployment appletů a to navíc v hybridním módu, kdy je možné běžící applet přetáhnout na desktop a provozovat jako klasickou desktopovou aplikaci.

  • Improved reliability. The JVM running the applet is isolated from the web browser at the operating system level. If something should go wrong while running the applet, or if an uncooperative applet refuses to shut down, the new Java Plug-In detects and handles the error condition gracefully; the web browser is unaffected.
  • Built-in JNLP support. The new plug-in offers the capability to launch applets directly from JNLP files, unifying deployment of Java content both in the browser and out of the browser (via Java Web Start). Developers can now reuse JNLP extensions for advanced functionality including the JavaFX run-time libraries, 3D graphics via OpenGL, and planetary-scale terrain visualization within applets. Applets can now access JNLP APIs for persistent data storage, local file system access, and other useful functionality from sandboxed code.
  • Per-applet command-line arguments. JVM command-line arguments may be specified on a per-applet basis, providing fine-grained control over options such as the heap size and Java 2D hardware acceleration features. JNLP-launched applets simply incorporate the command-line arguments and/or system properties into the JNLP file. Old-style applets can embed these arguments in the HTML of the web page.
  • Multiple JRE version support. Each individual applet instance may request a different JRE version on which to run. This feature is designed for enterprise customers which prefer to qualify their applets against either a particular JRE version or a particular JRE family. Both selection of a specific JRE version, or any in a particular family, are supported in the new plug-in.
  • Improved Java/JavaScript communication. The bridge between the JavaScript engine in the web browser and the Java programming language has been completely reimplemented. The new implementation is backward-compatible and features improved reliability, performance and cross-browser portability, for both Java calling JavaScript as well as JavaScript calling Java. Formerly Mozilla-specific "LiveConnect" functionality, such as the ability to call static Java methods, instantiate new Java objects and reference third-party packages from JavaScript, is now available in all browsers.
  • Improved user experience. The new Java Plug-In starts applets in the background, so the web browser always remains responsive. Applets appear on the web page as they become ready to run.
  • Improved applet lifecycle management. Calls to the applet lifecycle methods init, start, stop, and destroy are more deterministic and cross-browser behavior has been improved. The applet class loader cache and the legacy applet lifecycle, required for backward compatibility, are fully supported and the behavior of both has been improved.
  • Better large heap support. Historically, the maximum heap size that could be specified for applets via the Java Control Panel has been limited. This limitation is fixed in the new Java Plug-In; applets can now utilize as much heap space as command-line applications.
  • Better Windows Vista support. Signed applets running in Protected Mode Internet Explorer on Microsoft's Windows Vista now have the same privileges as normal user applications, eliminating a portability barrier to this platform.

Nuže předmostí pro JavaFX je položeno, otázka zní není to pozdě? Technologie appletů totiž žehrá na to, že na ní Sun dlouhou dobu kašlal a ta se tak trochu zkompromitovala sama. Uvidíme jestli tato resuscitacek něčemu povede.

pátek 24. října 2008

Nové API pro práci (nejen) se soubory

Tak už jsem si myslel, že nám tu zůstane java.io.File na věky věků jako jediná abstrakce pro práci se souborovým systémem v Jave. Dlužno dodat trochu nepovedená abstrakce. Naštěstí za hlavu se nechytali, jenom všichni jenž byli nuceni toto API používat a tak nám vzniklo JSR 203 More New I/O APIs for the Java Platform ("NIO.2"), které bude součástí JDK 7. Toto nové API řeší celkem tři oblasti, a to kromě lepšího rozhraní pro práci s souborovým systémem i asynchronní IO a doplnění socket-channel funkcionality.

Centrálními třídami nového package java.nio.file a java.nio.file.attribute budou FileSystem jako základní abstrakce pro práci se souborovým systémem a Path vyjadřující systémově závislou cestu k adresáři/souboru a BasicFileAttributes představující metadata (velikost, ACL, čas poslední změny atd.) k danému resourcu. Na další třídy se můžete podívat v javadocu.

Kromě toho, že celé API je rozšiřitelné, takže si budeme moci napsat například vlastní FileSystem implementaci nad naším obskurním souborovým systémem reprezentovaným REST interfacem, nás bude zajímat práce se samotnými soubory a to konkrétně jejich kopírování/přesouvání či zápis/čtení do souboru.

import static java.nio.file.StandardCopyOption.*;

Path source = Path.get("C:\\My Documents\\Stuff.odp");
Path target = Path.get("D:\\Backup\\MyStuff.odp");
source.copyTo(target);
source.copyTo(target, REPLACE_EXISTING, COPY_ATTRIBUTES);

Všechny operace, které nové IO API definuje a mohou končit IOException, tak opravdu touto výjimkou končí. Díky tomu nejsou výjimečné stavy řešeny boolean návratovou hodnotou jako tomu je ve starém IO API viz například metoda renameTo. Nové API by mělo být v tomto směru konzistentní. Díky tomu, že nové API počítá i s metadaty k souborům/adresářům je možné celkem rozumě zacházet například se symbolickými linky.

Funkčnost, která mi přišla zajímavá představuje podpora notifikací a asynchronního IO. Vznikla třída WatchService, která umožňuje sledovat danou entitu na typy události - čtení, smazání a nebo změnu. díku tomu bude jednoduché reagovat například na změnu souboru.

WatchService watcher = FileSystems.getDefault().newWatchService();
Set<StandardWatchEventType> events =
EnumSet.of(ENTRY_CREATE, ENTRY_DELETE, ENTRY_MODIFY);
WatchKey key = dir.register(watcher, events);
for (;;) {
    // wait for key to be signalled
    key = watcher.take();
    // process events
    for (WatchEvent<?> ev: key.pollEvents()) {
        if (event.getType() == ENTRY_MODIFY) {
            //do something
        }
    }
    // reset key
    key.reset();
}

Asynchronní podpora nám umožňuje provádět určité operace, např. kopírování souboru, asynchronním způsobem za použít abstrakcí jako java.util.concurrent.Future a nebo za použití callbacku. Ale co bych vám povídal, materiálu k dispozici je přehršel.

neděle 19. října 2008

CZ Podcast #27 - organizace času

Podcast číslo 27. jsme věnovali né tak úplně technikcému tématu, ale zato tématu, které by mohlo zajímat širší publikum a tím je organizace času (timemanagement, zkráceně tm). K tomuto povídání jsme si pozvali Ondru Nekolu, který se ukázal jako velký příznivec hledání cest k zefektivnění organizace času.

úterý 14. října 2008

Záludnost jménem clone

Dneska jsem s hrůzou v očích zjistil, že jsem měl základní nedostatek v tom, jak by se měla správně překrývat metoda clone(). Psát zde, že i mistr tesař se někdy utne, není na místě, protože se rozhodně za mistra nepovažuji. Pojdmě se tedy podívat na to kde leží zakopaný pes.


public class A implements Cloneable{
 @Override
 protected Object clone() throws CloneNotSupportedException {  
  return new A();
 } 
}


public class B extends A implements Cloneable {
 @Override
 protected Object clone() throws CloneNotSupportedException {  
  return (B) super.clone();
 } 
}

Problém leží v překryté metodě clone třídy A, protože ta nepoužívá metodu clone předka (java.lang.Object#clone). Tato metoda na java.lang.Object totiž zaručí, že vnikně právě kopie objektu, na kterém byla volána.

Správně tedy:


        @Override
 protected Object clone() throws CloneNotSupportedException {  
  Object clone = super.clone();
                assert clone instanceof A;
                return clone;
 } 

Když toto chování nedodržíme ve všech třídách, pak nám dojde k ClassCastException. Dobré to vědět! Skoro se stydím označit tento spot štítkem pro-zacatecniky.

pátek 10. října 2008

Prezentace Spring Framework - Enterprise Java s lidskou tváří

V rámci konference WebExpo 2008, která proběhne, 18-19. října budu mít prezentaci na téma Spring framework s podtitulem Enterprise Java s lidskou tváří. Budu mluvit například o tom, kde Java v oblasti webových aplikací selhala a jaký vliv to mělo na vznik Spring frameworku. Představím základní technologické myšlenky jako IoC a nebo AOP, které považuji za koncepčně klíčové. No a samozřejmě se dotknu vlivu dynamických jazyků. Celé povídaní bude koncipováno i pro lidi, kteří mají mizivou a nebo žádnou představu o tom co Spring framework je. Dovolte mi tedy, abych vás touto cestou pozval.

středa 1. října 2008

Proč používat anotaci @Override

Jednou z nejužitečnějších anotací, kterou představila Jave 1.5, je bezesporu anotace @Override. Tuto anotaci je důležité použít pokaždé, když překrýváte metodu, kterou deklaruje předek vaší třídy. Díky tomu budete kompilátorem upozorněni, a to ne varováním jak si mnozí mylně domývají, ale rovnou kompilační chybou, ve chvíli kdy kompilátor nenajde metodu stejné signatury v předkovi. Díky použití této anotace chráníte vlastní kód před těžko detekovatelnými chybami.

public class Predek {
  public void doSomething() {
  }
}

public class Potomek extends Predek {

  @Override
  public void doSomething() {    
  }

}

Ve chvili kdy se změní například signatura metody (bez rozdílu jestli v předkovi nebo potomkovi) - přidáme argument, kompilátor zahlási následující hlášku (toto hlásí kompilitáro v Eclipse): The method doSomething() of type Potomek must override or implement a supertype method.

úterý 30. září 2008

Nemám rád mrtvý kód

Za posledních čtrnáct dní jsem přečetl tolik kódu, že mi to vystačí minimálně na další dva příspěvky ;-). Jestli mě v kódu něco dráždí jako červený hadr býka, pak je to mrtvý kód. Nejdříve malá definice, co je podle mého mrtvý kód. Mrtvý kód - představuje nevyužité proměnné, importy, metody a zakomentované části kódu a nebo větve kam se program prostě nedostane.

Někdo by si řekl, že mrtvý kód přece ničemu překážet, ale opak je pravdou. Mrtvý kód má následující stinné dopady:

  • Zhoršuje čitelnost a v konečném důsledku udržovatelnost kódu. Metoda s poměrem 2:1 mrtvého vůči živému kódu se opravdu nečte dobře a úplně dobře se v takovém textu ani nevyhledává. To už ani nemluvím o kódu, do kterého se program nemůže dostat, protože podmínky pro jeho splnění již dávno neplatí např. zastaralý přepínač nebo změna rozsahu vstupní hodnoty.
  • Působí zmatečně. Kolikrát se mi stalo, že jsem chtěl opravit nějaký defekt a najednou koukám, že část zakomentovaného kódu dělá něco podobného. Je to tám schválně? Co mi tím chtěl autor říci, nemám si dát pozor na něco? Dalším příkladem jsou nepoužité proměnné, argumenty metod a konstruktorů. Smetí, které zhoršuje čitelnost se dá najít celá řada.

Moje zkušenost je taková, že čím větší poměr mrtvého kódu na metodu/třídy připadá, tím větší žumpa to bude. Taková třída/metoda se minimálně pětkrát přepsala, vyřádila se na ní minimálně půlka firmy a kód podle toho vypadá. Někdy je zakomentovaný kód signálem toho, že došlo k rychlému fixu, autor prostě nevěděl co s tím nebo neměl čas to udělat pořádně, tak danou část kódu přeimplementovatl a tu zakomentovanou nechal pro strýčka příhodu.

K mrtvému kódu resp. zakomentovanému se dokonce váže jedna veselá historka. Jeden programátor údajně argumentoval tak, že zakomentovaný kód tam nechává proto, aby bylo vidět, jak bylo před tím. To mělo jistě svojí logiku, ale pouze za předpokladu, že bychom si zdrojáky stále předávali na disketě a version control systémy jako CVS a SVN by byly v plenkách.

Moje rada, nenechávejte po sobě mrtvý kód. Refaktorujte, refaktorujte a refaktorujte. Vše co není potřeba nechť zmízí. Případnou historii lze stejně najít ve verzovacím systému a ruku na srdce, kolikrát jste z mrtvého kódu udělali zase ten živý.

pondělí 22. září 2008

Do pranice - využívat možnosti syntaxe až do morku kostí

Nebudu začínat obvyklým "nedávno jsem", ale třeba, tak jsem vám viděl zajímavé a opravdu vypečené konstrukce v kódu. První z nich představuje využití instančních inicializátorů ve spojitosti s anonymní vnitřní třídou, což umožňuje zajímavý způsob konstrukce a naplněni objektu. Druhou konstrukcí je vícenásobná definice lokální proměnné (jiný název mě proto nenapadá).

instančních inicializátor (zkopírováno odjinud - díky Martine)

Set s = new HashSet() {
  {
    add("x");
    add("y");
    add("z");
  }
};

vícenásobná definice lokální proměnné (díky NkD)

public class Foo {    
  public void my(){
    {
      String var = "foo";
      System.out.println(var);      
    }
    
    {
      String var = "hoo";
      System.out.println(var);
    }
    
    String var = "bar";
    System.out.println(var);
  }
}  

Osobně si myslím, že by se syntaxe jazyka neměla využívat úplně do morku kostí, protože to přece jenom přináší těžko čitelný kód a především pro méně zkušené programátory to může být docela oříšek k rozlousknutí. Vlastně ani nemusíte hledat někoho méně zkušeného, stačí se zeptat vedle sedícího kolegy, jestli se mu výše uvedený kód zdá kompilovatelný a co přesně dělá.

Mě osobně přijde příklad s instančním inidializátorem a anonymní vnitřní třídou jako akceptovatelný a dokonce se mi líbí. Druhý příklad naopak považuji za takovou obezličku k tomu, abych mohl uvnitř metody programovat podle vzoru zkopíruj a vlož. Je samozřejmě věcí osobního vkusu vývojáře kde leží ona hranice mezi řekněme kompaktním zápisem a nesrozumitelnou sekvenci písmen a dalších znaků. A tak se samozřeumě ptám na váš názor, měla by se syntaxe využívat až do morku kostí?

pátek 19. září 2008

IoC anti patterns nejen pro Spring

Při procházení kódu aplikací, které jsem sám dělal a nebo které jsem procházel jsem narazil na několik často se opakujících anti vzorů (anti patterns) při použítí Inversion of Control (dále v textu pouze IoC) frameworku. Rád bych se s vámi o tyto vzory podělil, aby jste neopakovali stejné chyby, které udělal někdo před vámi. Většina uvedeného kódu více či méně souvisí se Spring frameworkem a je zapsána v programovacím jazyku Java, nicméně vzory jako takové se budou vyskytovat při použití jakéhokoliv IoC frameworku. Pokračovat na dokument...

čtvrtek 11. září 2008

Tak už ani balená voda v gůglu...

Kam ten svět spěje, pomyslel jsem si dnes po přečtení článku proklamující údajně znechucení jednoho z majitelů gůglu nad tím, že je unavený půtkami zaměstnanců kolem balené vody a bonbonů M&M. Už ani můj oblíbený gůgl prý není to co býval, prý tam chtěli více zpeněžit školku pro děti. Našincům z HR (čti ejčár) by asi vstávaly vlasy hrůzou, teda pokud by jim rovnou nevypadly, kdyby si přečetli jaké výhody má, pardon mělo, pracovat v gůglu.

Jak je vidět i v Google dělají jenom lidé, takže místo toho, aby si tetelili blahem, že mohou strávit část pracovní doby nad open source projektech dle libovůle, tak řeší balenou vodu a bonbóny U nás máme také pár zajímavých benefitů, nicméně lidé stejně většinou řeší "proč nemůžu mít svůj oblíbený druh čaje", "proč v kuchyňce není med do čaje" a "jak je ksakru možné, že zase dochází balená voda".

Je to úsměvné, co vlastně těm lidem chybí, takové základní věci řekl by si jeden. Žádné auto, mobil a nebo akcie, ale nicotná sklenka medu za dvě pětky . Jsme moc rozmazlení až zhýčkaní jak občas slýchávám a nebo stačí uspokojit především základní potřeby? Řekl bych, že tak trochu od obojího, ale...

Tak či onak je to vlastně jedno, protože o tom rozhoduje ejčár manévrující v prostoru vymezeném magickým trojúhelníkem: stravenky, angličtina a mobil. Na druhou stranu uznávám, nemají to v tom oddělení jednoduché, lapit nějakou novou dušičku na profil firmy v němž stojí v kolonce benefity: čaj dle vlastního výběru, následovaný medem a balenou vodu hraničí skoro s ekvilibristickým kouskem.

úterý 9. září 2008

Generické DAO pro Hibernate/JPA

Nečekejte žádnou raketovou vědu, ale jenom takový malý tip ;-). Na pár projektech jsem se setkal s tim, že pro každou entitu bylo ručně vytvořeno a nebo vygenerováno DAO. Většina těchto DAO objektů však obsahovala pouze metody pro CRUD operace (Create, Update, Delete) pro danou entitu. To vedlo k často se opakujícímu kódu, který rozhodně nebyl potřeba. Díky generickým typům zavedeným v Jave 5 můžeme vytvořit generické a typově bezpečné DAO, které bohatě poslouží jako náhrada za původní generované objekty.

public class GenericDAO<E extends Object>{
  private Class<E> entityClass;
  
  protected GenericDAO(Class<E> entityClass) {
    this.entityClass = entityClass;
  }

  public E get(Serializable id) {
    return (EgetSesion().get(entityClass, id);
  }
  
  public void save(E entity) {
    getSesion().save(entity);
  }
  
  public void update(E entity) {
    getSesion().save(entity);
  }
  
  public void delete(E entity) {
    getSesion().delete(entity);
  }
      
  protected Session getSesion() {
    return null//get Hibernate session from somewhere
  }
  
  protected Class<E> getEntityClass() {
    return entityClass;
  }
  
  public static <T extends Object> GenericDAO<T> createGenericDAO(Class<T> clazz) {
    GenericDAO<T> dao = new GenericDAO<T>(clazz);    
    return dao;
  }
}

Takto připravené DAO je možné jednoduše používát v kódu.

GenericDAO<Dog> dao = GenericDAO.createGenericDAO(Dog.class);
Dog dog = dao.get(1);

CZ podcast volume #26 - JavaFX

Tenhle podcast o JavaFX vzniknul již před čtrnácti dny, nicméně jeho vydání se opozdilo díky mojí dovolené, čímž bych se chtěl omluvit především našemnu vrchnímu stříhačovi Kolískovi, kterého vždycky popoháním :-). Takže do tohoto podcastu se nám podařílo ulovit Honzu Štěrbu, který nám poskytl poměrně komplexní představení tehnologie JavaFX.

úterý 19. srpna 2008

Kdy je Enum roven

Když jsem včera prolétnul článek Neater Java, ve kterém je ukázána zajimává prace s Enum konstruktem/typem, tak mě překvapilo, že se pro porovnání dvou instancí enum používá equals metoda a přemýšlel jsem jestli není možné použít přímo test identity ==, když se vlastně jedná o konstantu.

Moje pátrání začalo v metodě Enum#equals(java.lang.Object), která je finální a její obsah je poměrně všeříkající.

public final boolean equals(Object other) { 
    return this==other;
}
        

Sice jsem byl spokojen, že na tato implementaci Enumu můžu použít test identity, nicméně se mi to zdálo vachrlaté přeci jenom jsem se nechtěl spolehát na implementační detail a hledal jsem nějaký exaktní důkaz a nakonec jsem našel na místě nejpovolanějším a to přímo v Java Language Specification, kde v sekci 8.9 Enums.

Because there is only one instance of each enum constant, it is permissible to use the == operator in place of the equals method when comparing two object references if it is known that at least one of them refers to an enum constant. (The equals method in Enum is a final method that merely invokes super.equals on its argument and returns the result, thus performing an identity comparison.)

Každopádně pokud používáte RMI a to i nepřímo například skrze vzdálené volání EJB, tak máte s enum typy problém, protože serializace RMI-IIOP (klasická Java serialziace funguje korektně) s nimi jaksi nepočítá viz defekt Serialization of Enums over IIOP is broke.

sobota 16. srpna 2008

Trochu o designu API

Včera večer jsem ještě se sirkami v očích dopisoval nějaké postřehy ke code review prezentaci, kterou budu mít v pondělí a zároveň jsem konečně dorazil rozhovor s Jardou Tulachem k vydání jeho knihy Practical API Design s podtitulem Confessions of a Java Framework Architect. Musím předeslat, že ten rozhovor na mě udělal dojem, že tato kniha nesmí chybět v mojí knihovničce. Taky je na čase přehodnotit můj trochu skeptičtější pohled na code review, ale pěkně po pořádku, protože to všechno začalo trochu jinde.

Udělali jsme jehož účel není pro popis této příhody vůbec důležitý. Proto abyste mohli s tímto API začít pracovat, tak potřebujete Spring. Náš původní předpoklad byl, že kdokoliv (klient), kdo s tím API bude pracovat, bude nejlépe sám managovaný Springem. Díky IoC pak všechno do sebe zapadne jako dílky puzzle skládačka Jednou ze základních tříd toho API byla továrna na vyrábění domain objektů typu jablka, hrušky, švestky a broskve. Zároveň tato továrna měla metodu k vyrábění unikátních identifikátory pro tyto domain objekty. Všechny naše objekty byly navenek reprezentované rozhraním a to včetně onoho zmíněného identifikátoru.

    
public interface OvocnaTovarna {
    public <T extends Ovoce> T newOvoce(Class typOvoce);    
}    

public interface IdTovarna {
    public Id newId();
    public Id fromString(String idAsString);
}

    
  

Rozdíl mezi implementací Ovoce a Id byl v tom, že ovoce skutečně představovalo netriviální strukturu, jejíchž instance šlo vytvářet pouze se znalostí určitého kontextu. Identifikátor byl oproti tomu v uvozovkách jednoduchý objekt, pro jehož zkonstruování nebylo potřeba kontext znát. Nicméně v rámci jednotnosti API jsme se rozhodli, že i Id bude vytvářeno továrnou a že bude taktéž reprezentované rozhraním jako zbytek domain objektů. Dalším faktorem pro volbu Id jako rozhraní byla možnost změnit jeho implementaci, kdyby například vespodu ležící java.util.UUID nevyhovoval.

Když jsem si včera procházel kód komponent, které naše API používají, tak se najednou ukázalo, že tento způsob návrhu API u klientů narazil a vedlo to k docela zajímavým často se opakujícím paradoxním praktikám. Ačkoliv klient, sám managovaný Springem, použil továrnu na ovoce, ale místo továrny na identifikátory prostě sveřepě konstruktorem vytvářel jedinou dostupnou implementaci rozhraní Id.

Kód vypdadal následovně

   
public class FooComponent { 
   @Autowired //zajisti dependency injection implementace 
   private OvocnaTovarna ovocnaTovarna;
   
   public void doSomethingFishy(String idAsString){
      IdImplementace id = new IdImplementace(idAsString);
      Hruska hruska  = ovocnaTovarna.newOvoce(Hruska.class);
      ...    
   }
}   
   
   

...přitom námi zamýšlené použití se přímo nabízelo.

   
public class FooComponent { 
   @Autowired 
   private OvocnaTovarna ovocnaTovarna;
   @Autowired
   private IdTovarna idTovarna;
      
   public void doSomethingFishy(String idAsString){
      Id id =  idTovarna.fromString(idAsString);
      Hruska hruska  = ovocnaTovarna.newOvoce(Hruska.class);
      ...    
   }
}   
   
   

V zmiňovaném rozhovoru Jarda Tulach uvádí dva základní axiomy.

  • "The first version of an API is never perfect."
  • "You cannot know all the users of your library."

První axiom se potvrdil celkem beze zbytku. Díky code review víme, že uživatelé některé části API používají jinak než jsme zamýšleli. Otázkou je proč. Nejpravděpodobnější variantou je, že jsme dostatečně nezdokumentovali, že se má používat továrna na vytváření identifikátorů. Méně pravděpodobné, ačkoliv reálné, je nechuť používat továrny pro "jednoduché" objekty ačkoliv to bych spíše chápal na místech, kde se Sring používá programově tj. programový bean lookup a po pravdě nikdo nemá rád vzor továrna na továrny.

Druhý axiom je pro nás daleko nebezpečnější v tom, že API může používat člověk u něhož těžko uděláme code review, protože ani nevíme kdo všechno a kde API použil. Poučení pro nás je v tom, že jednak musíme udělat příště tři věci:

  • dobře zdokumentovat API včetně příkladu použití
  • být defensivní - implementační třída nemusí být vůbec veřejná
  • být pragmatičtější - místo rozhraní jsme mohli pro identifikátor zvolit třídu

čtvrtek 14. srpna 2008

Synchronizace kolem objektů v HTTP session

Rozečetl jsem knihu Java Concurrency in practice a jen tak letmo mezi stránkami mě napadlo, že většina webových aplikací, na kterých jsem dělal, vlastně byla thread safe jen tak na oko. Slabé místo představovaly objekty, které ležely v session a mohlo dojít k jejich současnému použití různými vlákny.

Servlet specifikace přímo říká:

Multiple servlets executing request threads may have active access to the same session object at the same time. The container must ensure that manipulation of internal data structures representing the session attributes is performed in a thread safe manner. The Developer has the responsibility for thread safe access to the attribute objects themselves.

Toto riziko se úměrně zvýšilo tím, jak se začaly používat aplikace postavené kolem AJAX konceptů. Tím totiž došlo k několika paralelním asynchronním voláním, které se typický zbíhaly v datech uložených v session. Je potřeba si uvědomit, že ačkoliv se to na první pohled nezdá, tak nesprávně řízený konkurenční přístup k datům v session může vést u aplikace k docela neočekávaným stavům, které v lepším případě končí například na zdánlivě nesmyslné NullPointerException výjimce. Na druhou stranu neřízené synchronizování všeho a na všem může vést k špatné škálovatelnosti aplikace.

Pro případ, kdy chceme opravdu vzájemné vyloučení, tedy serializovaný přístup k datům uvnitř session, tak bychom měli zvážit velikost zámku. Pokud se nepletu tak webový framework JBoss Seam umožňuje synchronizaci každého požadavku právě přes asociovanou session. To je v mnoha případech zbytečně velký zámek, proto se můžeme sami zasynchronizovat přímo na objektu, který se bude potenciálně mezi vlákny sdílet.

Pokud chceme zaručit pouze správnou viditelnost dat mezi vlákny a konkurenční přístup k nim nám nevadí pak můžeme použít volatile a nebo vhodné abstrakce na programové úrovni např. pro mapu zvolit jako implementaci ConcurrentHashMap.

Myslím si, že na správnou synchronizaci objektů sdílených přes session se v mnoha případech nemyslí, protože si to člověk neuvědomí a nebo se tiše ignoruje protože všechny důsledky nejsou patrné. Docela by mě zajímalo jestli to ve svých aplikacích řešíte a nebo to necháváte takzvaně koňovi s poukazem na "ono to už nějak dopadne".

úterý 5. srpna 2008

CZ Podcast #25 - jOpenSpace 2008 speciál

Tento podcast vznikal v poměrně dost živelné atmosféře konference jOpenSpace 2008. Menší kvalita zvuku je proto vykoupena autentičností všech zůčastněných.

pondělí 4. srpna 2008

O metodologiích a lidech

Kolikrát jsem slyšel otázku, jestli jsou lepší agilní metodiky a nebo RUP based metodologie. Diskuse na toto téma vždy zabere minimálně půl dne a takřka vždy se zvrtne v pěkně velký flamewar. Je mlácením prázdné slámy se na to téma bavit, protože lidé jsou skoro vždy zakopání ve svých pozicích. Zkusili jste se někdy zamyslet, proč vlastně metodologie zavádíme?

Myslím si, že primárním důvodem bude potřeba řídit něco tak netriviálního jako je softwarový vývoj. Ve většině případů, se kterými jsem se setkal, byl vstup následující: datum finální uzávěrky, seznam požadované funkcionality a počet vývojářů. Je jenom otázkou každé metodologie, jak s těmito atributy vstupu nakládá. Hodně manažerů a i vývojářů podlehne snadno klamu, že "hbitá" nebo "líná" a nebo "fialová" metodologie může sama o sobě něčemu pomoci.

Je to stejné, jako když budete mít tým hráčů fotbalu. Máte-li partu lidí hrajících pro žízeň, tak s nimi těžko vyhrajete Ligu mistrů a to jim můžete naordinovat sebegeniálnější taktiku. Ovšem i naopak platí, že pokud sesbíráte nejlepším hráče na světě, pak to nemusí garantovat vůbec nic. V FC Chelsea napumpované penězi oligarchy Romana Abramoviče o tom vědí své. Vždycky totiž potřebujete kvalitní mix, který je tvořen nejen špičkovými hráči, ale i vhodně zvolenou taktiku, mnohdy ušitou na míru vašeho dalšího soupeře a samozřejmě ono často vzývané štěstíčko.

Přeceňování a nebo naopak podceňování jednak lidi a jednak metodologií vede často k tomu, že si fotbalovou terminologií dáme vlastňáka. Pouze pokud máme vhodný mix lidí, kteří se sednou lidsky i profesně a k nim zvolíme vhodnou metodologii, tak můžeme projekt dostat k úspěšnému konci. Občas jsme tak zaslepeni jedním nebo druhým, že na to zapomínáme. Nedělejme to prosím...

pátek 1. srpna 2008

Když bootuje bankomat

Tak se dějí zajímavé věci... (prosím omluvte špatnou kvalitu fotek)

Co je na tom zajímavého? Že bankomat resp. jeho software běží na MS Windows. A že se tam pro něco používá Java viz první fotka a celkem dobře čitelný výpis org.quartz.core.QuartzScheduler. No a autoři se s tím moc nemazali viz další hláška nastavuji succesfull timestamp na primar: true.

čtvrtek 31. července 2008

Chci věřit

Nepředvídatelný tok událostí mi vnuknul myšlenku, o kterou bych se s vámi rád podělil. Nedávno jsem vedl během obědu debatu o přínosu frameworků, které používáme, anebo které chceme použít. Na jedné straně jsem byl zakopán já se svými argumenty a na druhé straně někdo, kdo v kostce tvrdil, že tím že používáme kód, do kterého zcela nevidíme, tak přesně nevíme co se tam děje. Přiznejme si, že tento argument má hlavu, ale má i patu?

Kde v takovém případě končí ta hranice toho, kam až potřebujeme vidět? Protože přesně nevím, co se děje v transakčním manažeru, budu si psát vlastní, asi ne. Protože přesně nevím co se děje v databázi, budu si psát vlastní, asi ne. Protože přesně nevím co se děje v souborovém systému, budu si psát vlastní, asi ne. A kde to skončí, u operačního systému? Je to málo anebo hodně? Pokud používám nějakou abstrakci, a je lhostejné na jaké úrovni to bude, pak se jaksi dobrovolně vzdávám toho, že vidím co a jak se tam děje.

Používání softwarových komponent, anebo abstrakcí chcete-li, je v prvé řadě založeno na tom, že chci věřit, že daná abstrakce funguje a že to co se tam děje, se děje správně. Pokud by to neplatilo, pak by se celý softwarový průmysl zhroutil pod tíhou neefektivity, protože všichni by si dělali všechno. Pokud vám tedy někdo argumentuje tím, že používat cizí kód je nebezpečné, protože nevidíme co se tam děje, tak se toho člověka rovnou zeptejte, jestli je ze stejného důvodu rozumné vůbec používat operační systém či databáze…

úterý 22. července 2008

Protocol Buffers - binární protokol nejen pro RPC

Ta zpráva působí tak nevině a přitom vyvolává tolik kontroverze. Jedná se přesně o oznámení vypuštění projektu Protocol Buffers, což je ve své podstatě binární formát vyvinutý a používaný Googlem pro efektivní výměnu dat. Stop, pokud vás napadá nějaká z následujících otázek.

  • Jak binární formát?
  • Jak výměna dat?
  • K čemu tu sakra máme XML?
  • Je to zabiják XML?

Dobrá, to všechno jsou přesně diskusní témata, která ono oznámení vyvolalo. Jak se říká, nic není tak horké, jak se upeče. Takže pěkně po pořádku. Protocol Buffers (dále PB) vycházejí z požadavků na co nejefektivnější formát pro výměnu dat. Google potřebuje takový formát dat, který by se dal rychle serializovat/deserializovat a zároveň byl co nejšetrnější co do objemu řídících dat. Na základě tohoto požadavku se ihned vyřadilo XML.

Protocol buffers have many advantages over XML for serializing structured data. Protocol buffers:

  • are simpler
  • are 3 to 10 times smaller
  • are 20 to 100 times faster
  • are less ambiguous
generate data access classes that are easier to use programmatically

Samozřejmě přímo s binárním protocolem nepracují ani inženýři v Google. Proto je součástí PB i generátor objektové reprezentace. Práce s PB je následující:

  • Pomocí speciálního jazyku (protocol buffer language) popíšete strukturu vašich dat - vytvoříte schéma zprávy
  • Pustíte kompilátor pro váš oblíbený jazyk (Java, C++, Python, Perl, Haskell), který vám vygeneruje objektovou reprezentaci pro data (z pohledu Javy je to klasická Java beana - settry/gettry, která má navíc metodu pro serializaci a deserializaci do/z pole bajtů)
  • V kódu pak pracujete s již vygenerovanou reprezentací.

Jednoduchá ukázka, kterou jsem vytáhnul z Java tutoriálu PB.

Popis struktury dat

   
package tutorial;

option java_package = "com.example.tutorial";
option java_outer_classname = "AddressBookProtos";

message Person {
  required string name = 1;
  required int32 id = 2;
  optional string email = 3;

  enum PhoneType {
    MOBILE = 0;
    HOME = 1;
    WORK = 2;
  }

  message PhoneNumber {
    required string number = 1;
    optional PhoneType type = 2 [default = HOME];
  }

  repeated PhoneNumber phone = 4;
}
   
  

Práce v Jave

   
Person john =
    Person.newBuilder()
    .setId(1234)
    .setName("John Doe")
    .setEmail("jdoe@example.com")
    .addPhone(
      Person.PhoneNumber.newBuilder()
        .setNumber("555-4321")
        .setType(Person.PhoneType.HOME))
    .build();

//serializace    
FileOutputStream output = new FileOutputStream("john.dat");
john.writeTo(output);

//deserilizace
john = Person.parseFrom(new FileInputStream("john.dat"));
   
  

Jednoduché že? Google prozradil, že PB používá v RPC systems and for persistent storage of data in a variety of storage systems a že Protocol buffers are now Google's lingua franca for data – at time of writing, there are 48,162 different message types defined in the Google code tree across 12,183 .proto files (.proto soubory slouží pro popis struktury).

Právě zmíňka o RPC se stala velkým prubířským kamenem pro všechny XML věrozvěsty. Kde kdo to nechal Googlu pěkně sežrat. Každopádně jak to tak bývá, pointa je trochu někde jinde. To že PB využívá Google pro RPC neznamená, že vy to musíte dělat také. Pěkně to napsal Ted Newrd v článku So You Say You Want to Kill XML....

In the end, if you want an endpoint that is loosely coupled and offers the maximum flexibility, stick with XML, either wrapped in a SOAP envelope or in a RESTful envelope as dictated by the underlying transport (which means HTTP, since REST over anything else has never really been defined clearly by the Restafarians). If you need a binary format, then Protocol Buffers are certainly one answer... but so is ICE, or even CORBA (though this is fast losing its appeal thanks to the slow decline of the players in this space). Don't lose sight of the technical advantages or disadvantages of each of those solutions just because something has the Google name on it.

Mimochodem PB nejsou svého druhu jediným řešením, protože je tu ještě Thrift (již v Apache inkubátoru). Pro zajímavost dávám k dobru srovnání jejich vlastností.

Zdroje: v článku bylo hojně čerpáno z informací přímo či nepřímo získaných z Google Introduces Binary Encoding Format: Protocol Buffers.

sobota 12. července 2008

CZ Podcast #24 - tooly, tooly, tooliky

V tomto podcastu najdete tipy a komentáře k nástrojům, které používáme (nejen pro vývoj), ale i námi používáné postupy například pro třídění a sběr informací. Příjemný poslech a omluvte občasné posunutí Roumena, on ten jeho oeprační systém ještě trochu zlobí ;-).

úterý 8. července 2008

Hledáme inspiraci v dynamických jazycích

Dlouhou dobu jsem, a teď použiju možná silné slovo, opovrhoval dynamickými jazyky jako je Groovy či Ruby. Postupem času mi v nich ovšem, některé věci přijdou kouzelné. Část jejich oblíbenosti určitě vychází z toho jak je výsledný kód čitelný. Můžete namítnout, že to je dané jejich syntaxí, kterou budeme v Javě těžko měnit, ale ono to není jenom tou syntaxí. V těchto jazycích se totiž vytváří častěji API, které nese označení FluentInterface.

Martin Fowler rozdíl mezi klasickým a fluent (plynulým, tekoucím) API ukazuje na následujícím příkladu.

    private void makeNormal(Customer customer) {
        Order o1 = new Order();
        customer.addOrder(o1);
        OrderLine line1 = new OrderLine(6, Product.find("TAL"));
        o1.addLine(line1);
        OrderLine line2 = new OrderLine(5, Product.find("HPK"));
        o1.addLine(line2);
        OrderLine line3 = new OrderLine(3, Product.find("LGV"));
        o1.addLine(line3);
        line2.setSkippable(true);
        o1.setRush(true);
    }
    private void makeFluent(Customer customer) {
        customer.newOrder()
                .with(6"TAL")
                .with(5"HPK").skippable()
                .with(3"LGV")
                .priorityRush();
    }

Líbí se mi na tom, že se nikde neopakuje kontext, ten je daný uspořádáním - tokem kódu. Kód je tak pěkně odizolován od zbytečného smetí. Pak platí myslím význam fráze "samokomentující se kód". Na druhou stranu, jak píše Fowler, boří se některé zažité idiomy např. setter bez návratové hodnoty.

K tomu, abychom vytvářeli API tímto způsobem, nepotřebujeme dynamické jazyky. Při troše šikovnosti a vhodného návrhového vzoru (Method Chaining) to dokážeme i v Jave.

FluentInterface je pro mě způsob jak přemýšlet o návrhu API, tak aby dávalo smysl a bylo čitelné, když jej člověk používá anebo čte jeho použití. Asi určitě se nehodí úplně všude, ale minimálně pro doménový model aplikace se o něm sluší přemýšlet.