<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	>

<channel>
	<title>Java crumbs</title>
	<atom:link href="http://blog.krecan.net/feed/" rel="self" type="application/rss+xml" />
	<link>http://blog.krecan.net</link>
	<description>Short remarks from Java world</description>
	<lastBuildDate>Sun, 21 Feb 2010 10:20:02 +0000</lastBuildDate>
	<generator>http://wordpress.org/?v=2.8.6</generator>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
			<item>
		<title>Generovaný kód je zlo. A to i ve webových službách.</title>
		<link>http://blog.krecan.net/2010/02/21/generovany-kod-je-zlo-a-to-i-ve-webovych-sluzbach/</link>
		<comments>http://blog.krecan.net/2010/02/21/generovany-kod-je-zlo-a-to-i-ve-webovych-sluzbach/#comments</comments>
		<pubDate>Sun, 21 Feb 2010 10:15:40 +0000</pubDate>
		<dc:creator>Lukáš Křečan</dc:creator>
				<category><![CDATA[WS]]></category>

		<guid isPermaLink="false">http://blog.krecan.net/?p=511</guid>
		<description><![CDATA[Minulý týden jsem zase trochu programoval, psal jsem jednu webovou službu. Ta měla WSDL definované třetí stranou, takže to byla poměrně jednoduchá a rutinní záležitost. Vzal jsem XML schema, z něj vygeneroval XmlBeans a začal jsem implementovat. Narazil jsem ale na jeden problém, který se mi nedařilo vyřešit.
Měl jsem vyrobit čtyři webové služby, jejichž odpovědi [...]]]></description>
			<content:encoded><![CDATA[<p>Minulý týden jsem zase trochu programoval, psal jsem jednu webovou službu. Ta měla WSDL definované třetí stranou, takže to byla poměrně jednoduchá a rutinní záležitost. Vzal jsem XML schema, z něj vygeneroval <a href="http://xmlbeans.apache.org/">XmlBeans</a> a začal jsem implementovat. Narazil jsem ale na jeden problém, který se mi nedařilo vyřešit.</p>
<p>Měl jsem vyrobit čtyři webové služby, jejichž odpovědi se lišily jen v pár detailech. V zásadě vypadaly takto:</p>
<pre name="code" class="xml">
&lt;XXXResponse&gt;
        &lt;Version&gt;1&lt;/m:Version&gt;
        &lt;RequestId&gt;XYZ123&lt;/RequestId&gt;
        &lt;Result&gt;SUCESS&lt;/Result&gt;
        &lt;XXXTransactionId&gt;ABC456&lt;/XXXTransactionId&gt;
&lt;/XXXResponse&gt;
</pre>
<p>Místo XXX si představte různé fáze transakce. Můj problém spočíval v tom, že jsem nechtěl mít v programu čtyřikrát ten samý kus kódu pro generování odpovědi, chtěl jsem ho tam mít jen jednou. Jenže se to nedařilo, zkoušel jsem všelijaké finty s dědičností, vymýšlel jsem sofistikované wrappery, ale pořád jsem měl čtyři docela ošklivé bloky, které si byly ohromě podobné. Jediný rozdíl byl v jménu odpovědi a jménu transactionId. Ale tyto drobné rozdíly mi bránily v tom, udělat znovupoužitelný kód pro všechny webové služby.</p>
<p>Až mě napadla jednoduchá věc. Vždy jsem tvrdil, že generování kódu je zlo, kterému je potřeba se za každou cenu vyhnout. Ale u webových služeb jsem to tak nějak bral za dané. Znáte to, <a href="http://static.springsource.org/spring-ws/sites/1.5/reference/html/why-contract-first.html">contract first</a> přeci spočívá v tom, že začnu s návrhem XSD a podle něj píši kód. Je jen přirozené si ten kód pak nechat vygenerovat. A to je právě ta chyba. XML a Java jsou různé světy. Ano jsou si docela podobné, ale každý má jiný účel, jiné zvyklosti a jiné potřeby. Problém je, že, generovaný kód vždy odráží svůj původ.</p>
<p>Když generuji kód na základě XML, dostanu <a href="http://pichlik.sweb.cz/archive/2009_10_04_archive.html#3099964125087268552">anemický model</a> se kterým se mi pak špatně pracuje. Často pak skončím u toho, že mapuji vygenerované třídy na nějaké svoje vymazlené třídy a pak zase zpátky.  </p>
<p>Když na druhou stranu generuji XSD na základě Javy, riskuji, že se s výsledným XML bude mým klientům špatně pracovat, že bude špatně rozšířitelné a podobně.</p>
<p>Je to podobný problém jako u objektově relačního mapování. Objekty a tabulky jsou si hrozně podobné, ale přesto je mezi nimi obrovská propast. Pamatuji si doby, kdy jsem generoval Javovské třídy na základě tabulek. Výsledek byl vždy žalostný. V poslední době jednoduše namapuji ručně psanou Javu na ručně optimalizovanou databázi a obě strany jsou spokojené.</p>
<p>Proč něco podobného nejde u XML? Pokud jste byli na mém <a href="http://www.java.cz/article/czjug-leden-lightning-talks">lightning talku</a>, možná si vzpomenete jak jsem si stěžoval, že v roce 2010 musím ručně mapovat XML třídy na normální třídy a zpátky. Mýlil jsem se, nemusím. Mohu udělat to samé jako s databází. Díky <a href="https://jaxb.dev.java.net/tutorial/section_6_2_1-A-Survey-Of-JAXB-Annotations.html">JAXB 2</a> mohu jednoduše namapovat svoje třídy na XML. Samozřejmě, v první iteraci si mohu pro jednoduchost ty třídy vygenerovat, ale pak už je ručně upravím a nikdy je negeneruji znovu.  </p>
<p>A přesně tak jsem vyřešil svůj problém s duplicitou kódu. Ručně jsem si upravil JAXB třídy. Nejdřív jsem si vyrobil abstraktního předka všech odpovědí. To by ještě šlo zařídit úpravou XML schematu. Ale pak jsem do toho abstraktního předka přidal abstraktní metodu setTransactionId a dokonce jsem ho nechal implementovat nějaké rozhraní. To jsou koncepty, které v XML vůbec nemají smysl! Tím pádem ani nemá smysl pomýšlet na jejich generování. </p>
<p>Tím, že jsem udělal JAXB třídy nezávislé na XSD, jsem si zajistil, že je nemusím kopírovat do jiných interních tříd. Mohu svůj business kód udělat závislý jen na rozhraních, které XML třídy implementují. Konkrétně u mě to ušetřilo desítky řádků ošklivého kódu.</p>
<p>Kdybych měl dost odvahy, mohly bych dokonce i k těmto třídám přidat JPA anotace a ukládat je bez obav do databáze. Ale tak silný žaludek zatím ještě nemám.</p>
<p>Samozřejmě i tento přístup má své nevýhody. Asi největší je, že se mi může Java odchýlit od XML schematu. Může se mi stát, že udělám chybu, a začnu generovat nevalidní XML. Od toho ale máme testování, můžete použít třeba moji <a href="http://javacrumbs.net/spring-ws-test/">úžasnou knihovnu</a>, která vám to pohlídá.</p>
<p>Zkuste se nad tím zamyslet. Generovaný kód nefungoval nikdy, vždy s ním byly jen problémy. Ale u webových služeb jsem ho alespoň já bral jako hotovou věc. Když se ho ale zbavíme, ušetříme si spoustu starostí. Náš kód může vypadat o něco víc objektově a my si užijeme mnohem víc legrace s programováním užitečných věcí.</p>
]]></content:encoded>
			<wfw:commentRss>http://blog.krecan.net/2010/02/21/generovany-kod-je-zlo-a-to-i-ve-webovych-sluzbach/feed/</wfw:commentRss>
		<slash:comments>10</slash:comments>
		</item>
		<item>
		<title>Sláva abstrakci</title>
		<link>http://blog.krecan.net/2010/02/02/slava-abstrakci/</link>
		<comments>http://blog.krecan.net/2010/02/02/slava-abstrakci/#comments</comments>
		<pubDate>Tue, 02 Feb 2010 17:31:32 +0000</pubDate>
		<dc:creator>Lukáš Křečan</dc:creator>
				<category><![CDATA[Uncategorized]]></category>

		<guid isPermaLink="false">http://blog.krecan.net/?p=500</guid>
		<description><![CDATA[	Dnes mám nějakou náladu na filozofování, tak napíši něco, čeho už jsem se několikrát dotkl. Takže žádná novinka. Začnu svým oblíbeným prohlášením. Já píšu programy pro uživatele, snažím se řešit nějaký jejich problém. Říkejme tomu business problém. Rozhodně nepíši operační systémy, programovací jazyky, vývojová prostředí ani knihovny. Obvykle píši něco, co mému zákazníkovi přináší nějaké [...]]]></description>
			<content:encoded><![CDATA[<p>	Dnes mám nějakou náladu na filozofování, tak napíši něco, čeho už jsem se několikrát <a href="http://blog.krecan.net/2009/05/24/dva-druhy-kodu/">dotkl</a>. Takže žádná novinka. Začnu svým oblíbeným prohlášením. Já píšu programy pro uživatele, snažím se řešit nějaký jejich problém. Říkejme tomu business problém. Rozhodně nepíši operační systémy, programovací jazyky, vývojová prostředí ani knihovny. Obvykle píši něco, co mému zákazníkovi přináší nějaké peníze.</p>
<p>	Počítače ale pořád ještě pracují s nulami a jedničkami, od kterých je k penězům setsakra daleko. A od toho tu právě jsou abstrakce. Operační systém mě odstíní od těch nul a jedniček, virtuální stroj mě odstíní od operačního systému a správně zvolené knihovny mě odstíní od virtuálního stroje.</p>
<p>	V ideálním případě bych měl psát kód, který co nejblíže popisuje řešení daného business problému. Pokud to tak není, je něco špatně. Pokud musím v kódu kopírovat pole bytů, starat se o vlákna, řešit systémové výjimky, starat se o paralelizaci, tak vím, že je někde chyba. Já chci prostě a jednoduše psát jenom business kód. </p>
<p>	A nejsem to jenom já, podívejme se tímto pohledem na úspěšné technologie. Můžeme začít třeba samotnou Javou. Ta uspěla také díky tomu, že programátora odstínila od spousty do té doby běžných infrastrukturních starost. V Javě už jste se nemuseli starat o dealokování paměti, nemuseli jste řešit, jestli je String ukončený nulou nebo čím, nemuseli jste řešit jaký typ procesoru používáte nebo jaký je rozdíl mezi endianem a indiánem. V Javě jste se mohli jste se soustředit na psaní kódu. (Ano vím, že Smalltalk to uměl už o sto let dříve). </p>
<p>	Podobně úspěšné je servlet API. To nám zas umožňuje chovat se k vícevláknovému systému tak, jako by v něm bylo jen jedno vlákno. Ano, jako každá abstrakce i tato <a href="http://blog.krecan.net/2008/10/27/tomu-rikam-prosakujici-abstrakce/">prosakuje</a>, ale v zásadě to tak je. Vsadil bych se, že tato podařená abstrakce stojí za úspěchem servlet API a tím pádem i enterprise Javy. Naopak špatnou abstrakci poznáte podle toho, že vás nutí dělat něco, co byste jinak nedělali. Třeba EJB 2 a jeho šílená rozhraní.</p>
<p>	Nejen že mi dobrá abstrakce umožňuje se soustředit na můj business problém, ona mi i umožňuje držet krok s vývojem. Změní se operační systém? Nic se neděje. Změní se architektura procesoru? Nezájem, já jsem svůj program napsal v obecnější rovině, takže mě to (pravděpodobně) neovlivní. Naopak, já mohu využít novinek aniž bych  na svůj kód třeba jen šáhnul.  Procesor má tisíc jader? Nevadí, jenom změním konfiguraci serveru a mám vystaráno. Práce s více vlákny je pomalá? Nevadí, udělám update JVM a hned je vše jinak. Moje problémy za mě řeší někdo jiný.</p>
<p>	A to je vlastně důvod, proč to všechno píši. Pokud mě někdo nutí zahrnout do programu něco, co nevyjadřuje business problém, vím že je to špatně. Pokud mě někdo například nutí používat asynchronní API a z mých požadavků to přímo nevyplývá, vím, že se snaží řešit problém na nesprávném místě. Často není vyhnutí, často není technologie dost pokročilá. Ale většinou je to prostě jen špatná volba.</p>
<p>	Představme si, že například nechci, aby uživatel čekal, až se mi data zapíší do databáze, tak jak to <a href="http://pichlik.sweb.cz/archive/2010_01_24_archive.html#8023233373717081647">píše Dagi</a>. Samozřejmě, že to mohu řešit v kódu. Ale tam já to řešit nechci, tam já chci řešit jenom business. Musím se proto zamyslet jak to dělat jinak. Použít rychlejší databázi? Použít lepší JDBC ovladač? Použít databázi, která bere transakce velmi benevolentně? Všechno je možné, změna kódu je až poslední varianta. </p>
<p>	Je tu ještě jeden z argumentů, který jsem zatím nezmínil.  Lidé, kteří píší knihovny, databáze nebo virtuální stroje tomu rozumí mnohem lépe než já. Já vím jak převádět peníze, oni rozumí transakcím. Já vím co zajímá zákazníka, oni vědí jak synchronizovat data mezi vlákny. Kdykoliv to musím řešit za ně, vím, že buď odvedli špatnou práci nebo že já jsem si zvolil špatnou technologii. </p>
<p>	Vemte si například <a href="http://gee.cs.oswego.edu/dl/jsr166/dist/extra166ydocs/extra166y/ParallelArray.html">ParallelArray</a>. To mi umožňuje provádět operaci nad poli paralelně. Úžasná a i převratná knihovna. Ale z mého pohledu je špatná v tom, že mě nutí řešit thread pooly. To já nechci, to zákazníka vůbec nezajímá. Zamysleme se, proč to za mě nemůže řešit někdo jiný. Řekněme, že zavolám klasické Arrays.sort(). Proč nemůže běžet paralelně? Že JVM neví kolik vláken se má použít? Jak to že ne? To to ví dokonce lépe než já. Virtuální stroj dokonce i ví, kolik přesně má v daném okamžiku volných procesorů. To já nikdy v okamžiku psaní programu nevím a vědět nikdy nebudu. Že neví jestli je to operace k paralelizaci vhodná? Jak to? HotSpot to ví zase mnohem přesněji než já. To je stejné, jako kdybyste tvrdili, že je lepší, když programátor ručně uvolňuje paměť nebo optimalizuje kód.</p>
<p>	Tak se nad tím prosím zkuste zamyslet. Třeba nad tím jak do toho všeho zapadají dynamické jazyky, DSL a podobně. Připadá mi, že to všechno dává docela smysl.</p>
]]></content:encoded>
			<wfw:commentRss>http://blog.krecan.net/2010/02/02/slava-abstrakci/feed/</wfw:commentRss>
		<slash:comments>11</slash:comments>
		</item>
		<item>
		<title>Proč nepotřebuji asynchronní JDBC</title>
		<link>http://blog.krecan.net/2010/01/28/proc-nepotrebuji-asynchronni-jdbc/</link>
		<comments>http://blog.krecan.net/2010/01/28/proc-nepotrebuji-asynchronni-jdbc/#comments</comments>
		<pubDate>Thu, 28 Jan 2010 19:28:00 +0000</pubDate>
		<dc:creator>Lukáš Křečan</dc:creator>
				<category><![CDATA[Uncategorized]]></category>

		<guid isPermaLink="false">http://blog.krecan.net/?p=486</guid>
		<description><![CDATA[Můj blog nějak usíná, tak jsem si řekl, že nalákám čtenáře na nějakou kontroverzní diskuzi. Jako záminku si beru pondělní CZJUG, při kterém jsem narazil, že moc nerozumím  asynchronnímu volání. Nebo jinak, myslím si, že tomu rozumím a připadá mi, že to moc nepotřebuji. Budu rád, když mě někdo vyvede z omylu. Proto budu [...]]]></description>
			<content:encoded><![CDATA[<p>Můj blog nějak usíná, tak jsem si řekl, že nalákám čtenáře na nějakou kontroverzní diskuzi. Jako záminku si beru <a href="http://java.cz/article/czjug-leden-lightning-talks">pondělní CZJUG</a>, při kterém jsem narazil, že moc nerozumím  asynchronnímu volání. Nebo jinak, myslím si, že tomu rozumím a připadá mi, že to moc nepotřebuji. Budu rád, když mě někdo vyvede z omylu. Proto budu psát víc kousavěji než obvykle. Snad tím někoho vyprovokuji. </p>
<p>Ještě musím podotknout, že budu psát o klasickém serveru, který má problém s tím, že má moc uživatelů. Rozhodně se to netýká třeba dávkového zpracování velkého množství dat, to je úplně jiná kapitola.</p>
<p>Takže o co jde? V pondělí jsem viděl bleskořeč o <a href="http://nodejs.org/">node.js</a>. Zaujal mě příklad, na kterém bylo předvedeno asynchronní čtení z databáze. Motivace je jednoduchá. Čtení z databáze je obvykle pomalé a je škoda zdržovat drahé a cenné vlákno čekáním. Je lepší ho poslat obsluhovat další požadavky. Výsledek databázového dotazu může být zpracovaný později, buď tím samým, nebo jiným vláknem. Tím pádem bude náš systém skoro neomezeně škálovatelný. To dává smysl, že? Ani náhodou!</p>
<p>Původně jsem chtěl napsat, že to je špatně zvolený příklad, že asynchronní JDBC je nesmysl. Ale pak se mi to rozleželo a jsem ochoten připustit, že by v tom něco být mohlo. Ale jen malinko. </p>
<p>Nejdřív si musíme uvědomit, že databázový dotaz trvá dlouho proto, že databáze nestíhá. Chudinka totiž bývá tím jedním bodem, na který se všichni připojují. Tím že aplikačnímu serveru umožním zpracovat víc připojení celou situaci jen zhorším. Je to stejné, jako když na pomalém internetu  čekáte na načtení stránky a z nudy si otevřete druhou. Ta samozřejmě také dlouho trvá a proto si otevřete třetí. A ono pořád nic. Dokonce to vypadá, jako by ten internet byl ještě pomalejší. Stejná věc by se vám mohla stát i u databáze. Takže si prosím zapamatujte, že pokud máte pomalou databázi, tak ji více souběžnými dotazy moc nepomůžete.</p>
<p>Naštěstí máme obvykle omezený pool připojení do databáze takže to akutně nehrozí (Jirka Mareš má bod za postřeh). Za domácí úkol se zkuste zamyslet co by se v takovém případě stalo? Čekaly by požadavky ve frontě (jaké, jak dlouho) na uvolnění připojení nebo by to vyhazovalo chybu?</p>
<p>Obdobný problém máme, i pokud čekáme na pomalý disk nebo zatížený procesor. Tím že budeme přijímat víc práce, situaci jen zhoršíme. V takovém případě asynchronní volání smysl moc nedává. Naopak, potřebujeme požadavky co nejdříve přibrzdit, aby měl server čas na zotavení. </p>
<p>Představme si ale situaci, kdy nečekáme na nedostatkový zdroj, ale na něco, co prostě jen dlouho trvá. Jsou lepší vlákna nebo asynchronní volání? Já hlasuji pro vlákna. Asynchronní volání až moc smrdí předčasnou optimalizací. Nutí programátora myslet úplně jinak, jenom kvůli strachu z něčeho, co možná nenastane. Bojíme se, že náš systém nezvládne dost vláken a proto znepřehledňujeme zdrojový kód. Klasická předčasná optimalizace. </p>
<p>Schválně, zkuste odhadnout kolik vláken zvládne JVM na běžném serveru? 10, 100, 1K, 10K nebo 100K? Víte to? Já jsem také nevěděl, tak jsem se vydal hledat. Moc zdrojů k tomu není, ale narazil jsem na užasnou <a href="http://www.mailinator.com/tymaPaulMultithreaded.pdf">prezentaci</a>. Tu si určitě přečtěte. Kromě jiného se v ní dočtete, že 10 000 vláken by neměl být problém (s menším laděním velikosti zásobníku)! Navíc je to prý i dost rychlé. Najdou se i tací, kteří <a href="http://capriccio.cs.berkeley.edu/pubs/threads-hotos-2003.pdf">tvrdí</a>, že použití vláken je dokonce rychlejší než událostní řízení! Takže je možné, že si chceme znepřehledňovat kód jen proto, abychom ho zpomalili. Nevím jestli už jsem to psal, ale to by byla klasická předčasná optimalizace. Zapamatujte si proto prosím, že spící vlákno (skoro) nic nestojí.</p>
<p>Ale i kdyby vlákna byla pomalejší, radši bych počkal až to za mě Oracle vyřeší při dalším updatu Javy, než abych kvůli tomu učil spoustu programátorů myslet jinak! Schválně, jak dlouho vám bude trvat pochopit <a href="http://java.sun.com/javaee/6/docs/api/javax/servlet/AsyncContext.html#dispatch%28%29">asynchronní servlety</a>.  Mě se to pořád ještě pořádně nepodařilo. A to jsem se docela snažil. (Pěkný úvod najdete <a href="http://www.restfusion.com/blog/2010/01/why-asynchronous-servlets-matter-part-i/">zde</a>.)</p>
<p>Ale abych přeci nebyl jen tak jednostranný, je spousta míst, kde se asynchronní zpracování hodí. Jedním z nich může být šílený AJAX dotaz, který drží otevřené připojení a tím i vlákno desítky sekund. Třeba proto, že čeká až vám přijde mail. Pak má možná smysl uvažovat nad tím, uvolnit vlákno pro někoho jiného. Ale i to by mělo jít řešit transparentně. Něco ve smyslu: JVM si všimlo, že toto vlákno dlouho spí, tak jeho zásobník někam schová a uvolní prostředky. Já se pak se nebudu musit učit úplně jinému způsobu myšlení a moje programy budou zároveň škálovatelné i čitelné.</p>
<p>Rozloučím se pár citáty:</p>
<blockquote><p>What's harder, synchronizing 2 threads or synchronizing 1000 threads?</p></blockquote>
<blockquote><p>
We examined the code structure of the Flash web server and of several applications in Ninja, SEDA, and TinyOS. In all cases, the control flow patterns used by these applications fell into three simple categories: call/return, parallel calls, and pipelines. All of these patterns can be expressed more naturally with threads.</p>
<p>[Rob von Behren, Jeremy Condit and Eric Brewer,  <a href="http://capriccio.cs.berkeley.edu/pubs/threads-hotos-2003.pdf">Why Events Are A Bad Idea (for high-concurrency servers)</a>]
</p></blockquote>
]]></content:encoded>
			<wfw:commentRss>http://blog.krecan.net/2010/01/28/proc-nepotrebuji-asynchronni-jdbc/feed/</wfw:commentRss>
		<slash:comments>3</slash:comments>
		</item>
		<item>
		<title>RESTované webové služby</title>
		<link>http://blog.krecan.net/2009/12/06/restovane-webove-sluzby/</link>
		<comments>http://blog.krecan.net/2009/12/06/restovane-webove-sluzby/#comments</comments>
		<pubDate>Sun, 06 Dec 2009 15:07:42 +0000</pubDate>
		<dc:creator>Lukáš Křečan</dc:creator>
				<category><![CDATA[Knihovnička SE]]></category>
		<category><![CDATA[REST]]></category>
		<category><![CDATA[WS]]></category>

		<guid isPermaLink="false">http://blog.krecan.net/?p=476</guid>
		<description><![CDATA[	Jak je o mě jistě známo, jsem svého druhu dinosaurus. Stále ještě programuji v Javě a dokonce používám takové předpotopní technologie, jakými jsou SOAP webové služby. Ale abych věděl, o čem všichni mluví, občas si přečtu i nějakou tu knihu o novinkách.  Onehdá jsem studoval Scalu (vřele doporučuji) a teď jsem zrovna dočetl knihu [...]]]></description>
			<content:encoded><![CDATA[<p>	Jak je o mě jistě známo, jsem svého druhu dinosaurus. Stále ještě programuji v Javě a dokonce používám takové předpotopní technologie, jakými jsou SOAP webové služby. Ale abych věděl, o čem všichni mluví, občas si přečtu i nějakou tu knihu o novinkách.  Onehdá jsem studoval <a href="http://www.amazon.co.uk/Programming-Scala-Comprehensive-Step-Step/dp/0981531601/ref=sr_1_1?ie=UTF8&#038;s=books&#038;qid=1260111299&#038;sr=1-1">Scalu</a> (vřele doporučuji) a teď jsem zrovna dočetl knihu <a href="http://www.amazon.co.uk/RESTful-Web-Services-Leonard-Richardson/dp/0596529260/ref=sr_1_1?ie=UTF8&#038;s=books&#038;qid=1260111272&#038;sr=8-1">RESTful Web Services</a> od pánů Richardsona a Rubyho. </p>
<p>	Pokud se chcete dozvědět co to vlastně ten REST je, tak je to ta pravá kniha pro vás. Dozvíte se tam hodně o filozofii RESTu, o jeho výhodách, o tom jak takové služby navrhovat a jaké technologie k tomu používat. Většina příkladů je sice napsána v jakémsi obskurním jazyce jménem Ruby, ale pochopí je i Javista.</p>
<p>	Kniha je napsána i docela čtivě, musíte jenom překousnout demagogii typu „REST je nejlepší, RPC je k ničemu“. Co se mi hodně líbilo je to, že jsem snad konečně pochopil principy RESTu. Je to totiž jedna z těch technologií, o kterých všichni mluví, ale málokdo ji plně rozumí. Pokusím se tu shrnout to nejdůležitější.</p>
<p><strong>Dělej to jako Web</strong></p>
<p>	To je asi hlavní krédo RESTovaných aplikací. Web funguje, je snadno použitelný, dobře škáluje, tak proč bychom nemohli dělat webové služby úplně stejně. Je tu veliký rozdíl v tom, že normální web je určen pro lidi a webové služby pro stroje. Ale proč nepoužít stejných osvědčených principů?</p>
<p><strong>Zdrojově orientované</strong> </p>
<p>	Zdrojově orientované je můj geniální překlad pro Resource-Oriented. Znamená to, že se místo na služby, orientujeme na zdroje. Místo na slovesa typu udělej, založ, smaž se soustředíme na podstatná jména typu účet, zákazník a podobně. Je to podobné jako objektové programování, v něm bychom se měli soustředit hlavně na objekty samotné, jejich operace by z nich měli vyplývat.  Stejné princip by měl platit u RESTu. Tady musím dát příznivcům RESTu za pravdu, normální WS jsou silně funkcionální, o objektech tam není ani památky. Na druhou stranu je spousta služeb, které se jako RESTové jenom tváří, ale v podstatě jsou také jen RPC. </p>
<p><strong>Adresovatelnost</strong></p>
<p>	Další důležitý princip je adresovatelnost. Každá věc která je v daném systému důležitá, by měla mít vlastní adresu. To znamená, že každá instance objektu, by měla mít vlastní URI. Hodně to souvisí s  orientací na zdroje. Každý zdroj, má svoji adresu, například takovouto <em>http://www.exaple.com/v1/bank/client/12345</em>. Pokud použijeme přirovnání k objektům, tak URI je podobná referenci. </p>
<p><strong>Propojenost (Connectedness)</strong></p>
<p>	Propojenost hodně souvisí s předchozími body. Znamená to, že jako výsledek operací dostávám odkazy na další zdroje. Pokud se například zeptám na seznam klientů banky, měl bych dostat seznam jejich URI a ne jen jejich ID. Pokud bereme URI jako referenci na instanci, tak to dává smysl.</p>
<p><strong>Idempotentnost</strong></p>
<p>	Krásné české slovo označující, to, že by mělo být možné zavolat jednu službu vícekrát, aniž by hrozilo něco ošklivého. To znamená, že operace by pokud možno neměly mít žádné vedlejší účinky. Pokud mění stav systému, měly by to dělat tak, aby se nic nestalo, pokud ho změní vícekrát. Je překvapivé, že takových operací je valná většina. Nic se nestane, pokud například vícekrát nastavím stejnou hodnotu nebo něco smažu. Jsou tu samozřejmě výjimky, ale i u těch se dá idempotentnost zařídit. </p>
<p><strong>Bezstavovost</strong></p>
<p>	Bezstavovost je často nepochopené téma. A není se čemu divit, je to hodně matoucí. Pokusím se to ale vysvětlit. Bezstavovostí se v tomto případě myslí, že webová služba neukládá stav klienta. Rozhodně tam není žádná session. Klient může navíc volat operace v libovolném pořadí, takže by se nemělo objevovat žádné flow jak ho známe z normálního webu. Ale aplikace samotná samozřejmě stav má. Takže si samosebou pamatuje, kolik kdo má na účtu, kam chce letět na dovolenou nebo kam rád chodí do restaurace. Ale nejedná se o stav klientské aplikace, jedná se o stav zdrojů. V tom je veliký rozdíl. </p>
<p>	Bezstavovost je docela rozumný princip, díky ní se například dobře škáluje. Bohužel často k jejímu dodržení musíme švindlovat. Občas prostě potřebujeme držet stav klientské aplikace. V RESTu proto dělají krok stranou a prohlásí stav klienta za stav systému. Takže když potřebují uložit obsah nákupního košíku, řeknou, že to není stav klienta, ale stav aplikace. Nákupní košík je vlastně takový zdroj, jehož stav aplikace naprosto přirozeně drží. Takový košík má pak svoji URI, své operace a je to prostě normální zdroj. Problém vyřešen. Tedy kromě té škálovatelnosti, s ní jsem na tom úplně stejně jako kdybych používal session. (Kvízová otázka. Jak zajistit, aby přidání položky do nákupního košíku bylo idempotentní?) </p>
<p>	No zbytek z těch asi 400 stránek tu opisovat nebudu. Radši napíšu proč se budu držet dál normálních (tlustých) webových služeb. </p>
<p>	V první řadě se mi nelíbí úzká vazba na HTTP. To je jedna z věcí, která mi ještě nedošla, takže budu rád když mi ji někdo vysvětlí. Na jedné straně čtu, že REST je na HTTP úplně nezávislý. Na druhé straně, je ale REST s HTTP neuvěřitelně úzce spjat. Chcete-li změnit stav zdroje, máte použít HTTP PUT, chcete-li ho smazat, použije HTTP DELETE, chcete zjistit jeho stav, použijte GET. Nastane chyba? Dostanete ten a ten HTTP chybový kód. Tak je to závislé nebo ne? Mě spíš připadá že jo. </p>
<p>	Dalším důvodem, proč zatím zůstanu u klasického ošklivého SOAPu je to, že mi vyhovuje. Já prostě nepíši aplikace, které jsou podobné webovým stránkám. Píši věci, které jsou svoji podstatou spíše procedurální než objektové. Navíc mi vyhovuje to, že existuje něco jako WSDL, které je sice ošklivé jak noc, ale které i přes své mouchy funguje. Ano pro REST máme WADL, ale že by byl široce rozšířen se říci nedá.</p>
<p>	Také mi vyhovuje, že v SOAPu jsou metadata součástí zprávy a ne protokolu, kterým se zpráva posílá. Prostě mi to připadá bezpečnější. Když volám webovou službu tak volání bohužel často přejde přes několik JMS front a pár HTTP připojení. Takže se na to radši dívám tak, že posílám XML dokument, který přes nějaké složitosti snad doputuje k svému adresátu. </p>
<p>	Tím rozhodně nechci říci, že je REST špatný. Pokud bych vystavoval webové služby pro něco, co má svůj ekvivalent ve webové aplikaci, asi bych nad RESTem vážně uvažoval. Protože se ale pohybuji v jiném světě, tak je moje volba jiná. To mi ale nebrání se poučit a pár fint od RESTu okoukat.</p>
]]></content:encoded>
			<wfw:commentRss>http://blog.krecan.net/2009/12/06/restovane-webove-sluzby/feed/</wfw:commentRss>
		<slash:comments>5</slash:comments>
		</item>
		<item>
		<title>Testujeme WS klienty</title>
		<link>http://blog.krecan.net/2009/11/05/testujeme-ws-klienty/</link>
		<comments>http://blog.krecan.net/2009/11/05/testujeme-ws-klienty/#comments</comments>
		<pubDate>Thu, 05 Nov 2009 21:04:36 +0000</pubDate>
		<dc:creator>Lukáš Křečan</dc:creator>
				<category><![CDATA[Testy]]></category>

		<guid isPermaLink="false">http://blog.krecan.net/?p=458</guid>
		<description><![CDATA[Chystám se přihřát si vlastní polívčičku a budu psát o tom, na čem právě ve svém volném čase dělám. Jde o knihovnu, která mi pomáhá s testováním Spring WS klientských aplikací. Jako obvykle jsem si chtěl ušetřit sám sobě práci. Jsem totiž docela nakažen testováním, takže se snažím psát unit testy skoro na všechno co [...]]]></description>
			<content:encoded><![CDATA[<p>Chystám se přihřát si vlastní polívčičku a budu psát o tom, na <a href="http://javacrumbs.net/spring-ws-test/">čem právě ve svém volném čase dělám</a>. Jde o knihovnu, která mi pomáhá s testováním Spring WS klientských aplikací. Jako obvykle jsem si chtěl ušetřit sám sobě práci. Jsem totiž docela nakažen testováním, takže se snažím psát unit testy skoro na všechno co dělám. </p>
<p>	Některé části aplikace se ale testují dost špatně. Většinou jde o „okraje“ aplikace jako například JSP, komunikaci s databází, volání webových služeb nebo proprietárního kódu. Jinými slovy, pokud je testovaný kód používaný pouze mým kódem, testuje se docela dobře. Pokud je ale na rozhraní mezi mnou a uživatelem, databází nebo něčím jiným, testování se komplikuje.</p>
<p>	Proto je důležité psát takové části co nejtenčí. Co to znamená? Vaše JSP stránky by měly být co nejjednodušší, DAO vrstva by neměla obsahovat žádnou logiku a knihovny které používáte by měly být co nejméně invazivní.</p>
<p>	Pokud ale tyto věci na periferii chci otestovat, musím se často uchýlit k funkčním testům. K testům, které jsou sice automatizované, ale které vyžadují běžící aplikační server, Spring kontext nebo třeba databázi v paměti jako HSQL.  Takové testy jsou obvykle komplikovanější a také jejich spouštění trvá výrazně děle.</p>
<p>	Podobný problém mívám i s testy volání webové služby. Samosebou mám toto volání zapouzdřeno ve speciální vrstvě, ale i tu bych rád otestoval. Kód často vypadá podobně jako tento.</p>
<pre name="code" class="java">
public List&lt;Flight&gt; getFlights(String origin, String destination) {
	//prepare request
	GetFlightsRequest request = new GetFlightsRequest();
	request.setFrom(origin);
	request.setTo(destination);
	request.setServiceClass(ServiceClass.ECONOMY);
	request.setDepartureDate(Calendar.getInstance());
	//call the service
	GetFlightsResponse response = (GetFlightsResponse)webServiceTemplate.marshalSendAndReceive(request);
	//convert response
	return response.getFlight();
}
</pre>
<p>	Na začátku musím vyrobit dotaz. Obvykle musím naplnit nějaký objekt vygenerovaný XML mapovacím nástrojem. Pak zavolám službu a její odpověď musím zase převést na něco čemu rozumí moje aplikace. </p>
<p>	Jak něco takového otestovat? Samozřejmě to jde, jenom mě to vůbec nebaví. Nejdřív potřebuji otestovat, že jsem správně vytvořil dotaz. Pokud to testuji klasicky, tak ten test vypadá podezřele stejně jako kód samotný. Hrozně mě nebaví testovat, jestli když nastavím datum odletu, tak je opravdu dobře nastaveno. Navíc je to hrozně odtrženo od požadavků. Nikdo po mě přeci nechce, abych plnil nějaký hloupý vygenerovaný objekt. Chtějí po mě, abych vygeneroval XML. Věřím sice, že XML mapovací knihova funguje správně, ale pořád mám pocit, že by bylo pěkné to otestovat nějak lépe.</p>
<p>	Pak by bylo dobré otestovat, jestli opravdu volám tu webovou službu. Další trapný a nudný test. Nastavím mock a ověřím, jestli se opravdu zavolá. Nůůůda.</p>
<p>	No a pak mě čeká otestovaní, jestli se dobře konvertují data z odpovědi do objektu, který má často podobnou strukturu. Další nuda. </p>
<p>	Dá se to dělat lépe? Samozřejmě. Za pomocí našeho skvělého patentovaného přípravku, který vyčistí všechny vaše testovací skvrny bez narušení podstaty látky. Můžeme si totiž připravit požadovaný dotaz i odpověď jako XML, použít naši <a href="http://javacrumbs.net/spring-ws-test/">speciální knihovnu</a> a napsat test například takto</p>
<pre name="code" class="java">
@Test
public void testGetFligts()
{

	//create control
	WsMockControl mockControl = new WsMockControl();
	//teach mock what to do and create it
	WebServiceMessageSender mockMessageSender = mockControl.expectRequest("PRG-DUB-request.xml").returnResponse("PRG-DUB-response.xml").createMock();
	webServiceTemplate.setMessageSender(mockMessageSender);

	//do the test
	List&lt;Flight&gt; flights = client.getFlights("PRG","DUB");
	assertNotNull(flights);
	assertEquals(1, flights.size());
	assertEquals("PRG",flights.get(0).getFrom().getCode());
	assertEquals("DUB",flights.get(0).getTo().getCode());

	//verify that everything was called at least once
	mockControl.verify();
}
</pre>
<p>	Krásné, jednoduché a elegantní. Popis XML dat je realizován v k tomu nejvhodnějším jazyce - v XML.  Test mi i automaticky ohlídá, že jsem opravdu službu zavolal. A to nezmiňuji spoustu dalších vymožeností, které zde pro jistotu nezmiňuji, abyste ohromením neomdleli.</p>
<p>	Pokud jste tedy zůstali při vědomí vězte, že to všechno je k mání zdarma, na adrese <a href="http://javacrumbs.net/spring-ws-test/">http://javacrumbs.net/spring-ws-test/</a>. Jenom račte prominouti, že dokumentaci ještě nestačila býti plně dohotovena. Naše dokumentační oddělení na ní pilně pracuje tudíž se lze domnívati, že bude dohotovena v nedaleké budoucnosti. Prozatím račte vzíti v potaz <a href="https://java-crumbs.svn.sourceforge.net/svnroot/java-crumbs/ws-client-tdd/trunk/ws-client-tdd">příklad použití</a>, který Vám návod jistojistě poskytne.</p>
]]></content:encoded>
			<wfw:commentRss>http://blog.krecan.net/2009/11/05/testujeme-ws-klienty/feed/</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
		<item>
		<title>Černá magie testů výkonnosti</title>
		<link>http://blog.krecan.net/2009/10/18/cerna-magie-testu-vykonnosti/</link>
		<comments>http://blog.krecan.net/2009/10/18/cerna-magie-testu-vykonnosti/#comments</comments>
		<pubDate>Sun, 18 Oct 2009 08:01:16 +0000</pubDate>
		<dc:creator>Lukáš Křečan</dc:creator>
				<category><![CDATA[Uncategorized]]></category>

		<guid isPermaLink="false">http://blog.krecan.net/?p=449</guid>
		<description><![CDATA[Většina vývojářů věří, že je dobrá v ladění výkonu, ale obecně se ukazuje, že většina vývojářů  v tom dobrá není.
Kirk Pepperdine

Tento citát z rozhovoru s Kirkem Pepperdinem jsem tu použil záměrně. Chci tu psát o svých nedávných zkušenostech s měřením a laděním výkonu, ale vzhledem k tomu, že jsem docela dobrý vývojář, je velká [...]]]></description>
			<content:encoded><![CDATA[<blockquote><p>Většina vývojářů věří, že je dobrá v ladění výkonu, ale obecně se ukazuje, že většina vývojářů  v tom dobrá není.<br />
Kirk Pepperdine
</p></blockquote>
<p>Tento citát z <a href="http://java.sun.com/developer/technicalArticles/Interviews/community/pepperdine_qa_2009.html">rozhovoru</a> s Kirkem Pepperdinem jsem tu použil záměrně. Chci tu psát o svých nedávných zkušenostech s měřením a laděním výkonu, ale vzhledem k tomu, že jsem docela dobrý vývojář, je velká pravděpodobnost, že jsem na to šel špatně.</p>
<p>Takže jste byli varováni a já se může pustit do popisu problému. Pracuji na jednom velkém a zbytečně složitém systému. Nedávno se po jedné podařené marketingové akci velká skupina zákazníku rozhodla, že ho začne volat v jeden okamžik najednou. Navíc ještě k tomu v pátek večer. No a protože to je docela velká skupina, náš systém s tím měl drobné potíže. Kolegové s řešením strávili pěkných pár dnů, nakonec našli místa potencionálních problémů a před systém postavili pár obraných mechanizmů, které ho chrání před přetížením. Nicméně problém stále trvá a bylo by pěkné ho vyřešit. Jinak by se mohlo stát, že se z velké skupiny stane malá, což by mohlo potěšit naše administrátory, ale rozhodně ne náš marketing.</p>
<p>Teď přicházím do hry já. Kolegové mi ukázali na jednu věc, kterou aplikace dělá evidentně zbytečně a ať prý vymyslím, jak se jí zbavit, aniž by se něco rozbilo. Jenže já jsem známý potížista a navíc jsem si vzpomněl na jednu přednášku Kirka Pepperdineho, v které říkal něco v tomto smyslu (nedaří se mi najít zdroj, takže cituji z paměti):</p>
<ol>
<li>Nejdřív si zjistěte jaký je požadovaný výkon (SLA)</li>
<li>Naměřte současné hodnoty</li>
<li>Zjistěte možné problémy</li>
<li>Jeden z nich opravte</li>
<li>Naměřte nové hodnoty</li>
<li>Opakujte dokud nesplníte 1. nebo dokud má zákazník ještě nějaké peníze</li>
</ol>
<p>Takže jsem si zjistil SLA a začal měřit. A už tady jsem možná udělal chybu. Začal jsem měřit na svém notebooku a ne na prostředí, které se podobá produkci. Mojí výmluvou je to, že jsem si myslel, že už víme v čem je problém. A opravdu, při testech se projevovala potíž v té jedné nadbytečné operaci. Zbytečně se tam zapisovala data do jedné tabulky. Z té se obratem zase četlo a občas tu jeden select zabíral desítky sekund. Cože? Desítky sekund u dotazu nad tabulkou v které je jen pár set tisíc záznamů? Něco je špatně. Po chvíli pátrání jsem objevil, že někteří klienti mají v dané tabulce stovky záznamů místo očekávaného tuctu a pro ně trvá dotaz neúnosně dlouho. Jeden dobře mířený index nad tabulkou, která na daný dotaz zdánlivě neměla vliv to vyřešil. </p>
<p>Tento problém moji pozornost obrátil na test samotný. Jak je možné, že data vypadají jinak, než je očekáváno? Ukázalo se, že chyby mohou být i v testu samotném. Místo simulace tisíců různých klientů, simuloval tisíce přístupů od pár desítek klientů. Takže den testování v čudu, ale jsme alespoň o krok blíž. Máme opravený test.</p>
<p>Spustím opravené testy a aplikace je stále podezřele pomalá. Navíc i když spouštím JMeter, aplikaci i databázi na jednom stroji, zátěž procesoru dosahuje ubohých 75%. Brzdou je něco jiného. Vypadá to, že disk. A opravdu MySql proces zapisuje a čte jak divoký. Že by to přece jen byly ty zbytečné inzerty. To se zjistí velice snadno, prostě je vyhodím.</p>
<p>Po pár minutách hledání nejlepšího místa pro sabotáž, vyřazení inzertů z boje a desítkách minut buildu a startu serveru nedočkavě spouštím test a ... chvilka napětí ... jste tak napjatí jako já ? ... vážně  ? ... výsledky jsou srovnatelné s předchozími. Obě jádra se pořád flákají, disk maká jak afroameričan. </p>
<p>Takže dalších pár hodinek pátrání a nacházím tabulku, která na první pohled s testem moc nesouvisí. Ale předchozí testy do ní nasypaly hromadu dat, která teď zdržují. Vymažu obsah tabulky, znovu spustím test a graf výkonu málem proletěl vrškem monitoru. Požadovaný výkon bych možná splnil i na notebooku!</p>
<p>Problém vyřešen. Nebo ne? Co se stane, když inzerty vrátím? Další desítky minut strávené novým buildem a spouštím test. Sakra, je to srovnatelně rychlé, jako když tam ty inzerty nejsou. </p>
<p>Ukazuje se, že obsah databáze a způsob testování má na výkon větší vliv, než struktura kódu! To je trochu nečekaný výsledek. Jediné co jsem udělal bylo, že jsem opravil test, přidal jeden index a promazal tabulky. A už to mělo za následek dvojnásobné zvýšení výkonu. Alespoň toho naměřeného. Takže jsem tam kde jsem začal.  O tom kde nás tlačí bota nevím skoro nic. Že by měl Kirk pravdu? Že by programátoři byli opravdu špatnými testery?  Tomu se mi nechce věřit. Nevzdávám to a zítra se vrhnu na testy v reálném prostředí. To by v tom byl čert, abych na něco nepřišel.</p>
]]></content:encoded>
			<wfw:commentRss>http://blog.krecan.net/2009/10/18/cerna-magie-testu-vykonnosti/feed/</wfw:commentRss>
		<slash:comments>4</slash:comments>
		</item>
		<item>
		<title>Test coverage &#8211; interesting only when low</title>
		<link>http://blog.krecan.net/2009/09/28/test-coverage-interesting-only-when-low/</link>
		<comments>http://blog.krecan.net/2009/09/28/test-coverage-interesting-only-when-low/#comments</comments>
		<pubDate>Mon, 28 Sep 2009 19:10:59 +0000</pubDate>
		<dc:creator>Lukáš Křečan</dc:creator>
				<category><![CDATA[Testy]]></category>
		<category><![CDATA[test coverage]]></category>

		<guid isPermaLink="false">http://blog.krecan.net/?p=435</guid>
		<description><![CDATA[What a nice and controversial title. But I really mean it. Level of test coverage is really interesting only when it's low. Of course, we should aim for highest coverage possible, but the higher the coverage is, the less useful information it brings. Let take the following example and let's assume there are no tests [...]]]></description>
			<content:encoded><![CDATA[<p>What a nice and controversial title. But I really mean it. Level of test coverage is really interesting only when it's low. Of course, we should aim for highest coverage possible, but the higher the coverage is, the less useful information it brings. Let take the following example and let's assume there are no tests for this method.</p>
<pre name="code" class="java">
	/**
	 Adds positive numbers. If one of the parameters is negative,
	 IllegalArgumentException is thrown.
	 * @param a
	 * @param b
	 * @return
	 */
	public int addPositive(int a, int b)
	{
		if ((a<0) || (b<0))
		{
			throw new IllegalArgumentException("Argument is negative");
		}
		return a+a;
	}
</pre>
<p><strong>No coverage - wow, that's interesting</strong></p>
<p>The fact that some piece of code is not covered at all is really interesting. It either means, that we have to start writing tests at once or that the piece of code has to be deleted. Either way we know that we should do something. Moreover, we know exactly what to do. For example, we can start with the following test.</p>
<pre name="code" class="java">
	@Test
	public void testAddition()
	{
		assertEquals(2, math.addPositive(1, 1));
	}
</pre>
<p>It will get us partial coverage like this<br />
<img src="/files/coverage.png" alt="Partial coverage" width="641" height="114"/></p>
<p><strong>Partial coverage - cool, I know what to test next</strong></p>
<p>If I have partial coverage, I can see what other tests I am supposed to write. In our example I see that I have to test what happens if I pass in a negative numbers.</p>
<pre name="code" class="java">
	@Test(expected=IllegalArgumentException.class)
	public void testNegative1()
	{
		math.addPositive(-1, 1);
	}
	@Test(expected=IllegalArgumentException.class)
	public void testNegative2()
	{
		math.addPositive(1, -1);
	}
</pre>
<p><strong>Total coverage - I have no clue</strong></p>
<p>Now we have 100% coverage. Well done! Unfortunately, I have no clue what to do next. I have no idea if I need to write more tests, I do not know if I have complete functional coverage. I have to stop looking at the coverage and I have to start thinking. You see, when the coverage was low it gave me lot of useful information, when it's high I am left on my own. For example I can think hard and come up with following complex test scenario.</p>
<pre name="code" class="java">
	@Test
	public void testComplicatedAddition()
	{
		assertEquals(3, math.addPositive(1, 2));
	}
</pre>
<p>Please note, that the coverage was already 100% before I have written the test. So one more test could not make it higher. Nevertheless the test actually detected a bug that was there from the beginning. It means that 100% code coverage is not enough, we have to aim higher. We should care about functional coverage and not about code coverage!</p>
<p>That's also one of many reasons why we should do test driven development. Or at least test first development. If we write the tests before the code, we are forced to think from the beginning. In TDD we do not care about the coverage. We just think about the functionality, write corresponding tests and then add the code. Total coverage is automatically achieved. </p>
<p>In the opposite situation, when we write the code first and then add the tests as an afterthought, we are not forced to think. We can just write some tests, achieve the target coverage and be happy. Test coverage can be really deceitful. It can give us false sense of security. So please remember, test coverage is a good servant but a bad master. </p>
]]></content:encoded>
			<wfw:commentRss>http://blog.krecan.net/2009/09/28/test-coverage-interesting-only-when-low/feed/</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
		<item>
		<title>Spring WS Test</title>
		<link>http://blog.krecan.net/2009/09/02/spring-ws-test/</link>
		<comments>http://blog.krecan.net/2009/09/02/spring-ws-test/#comments</comments>
		<pubDate>Wed, 02 Sep 2009 19:15:51 +0000</pubDate>
		<dc:creator>Lukáš Křečan</dc:creator>
				<category><![CDATA[Spring]]></category>
		<category><![CDATA[Testy]]></category>
		<category><![CDATA[spring-ws]]></category>
		<category><![CDATA[test]]></category>

		<guid isPermaLink="false">http://blog.krecan.net/?p=422</guid>
		<description><![CDATA[Last few weeks I have been working on one of my pet projects. Its name is Spring WS Test. As the name implies, its main purpose is to simplify Spring WS tests. 
Again, I am scratching my own itch. I am quite test infected and I have needed something that allows me to write functional [...]]]></description>
			<content:encoded><![CDATA[<p>Last few weeks I have been working on one of my pet projects. Its name is <a href="http://javacrumbs.net/spring-ws-test/">Spring WS Test</a>. As the name implies, its main purpose is to simplify Spring WS tests. </p>
<p>Again, I am scratching my own itch. I am quite test infected and I have needed something that allows me to write functional tests of my application without having to depend on an external server.  Until now, you basically had two options. This first one is to test WS client application using plain old JUnit together with a library like EasyMock. But usually this test are quite ugly and hard to read. Moreover this type of tests does not test your configuration. The second option is to create a functional test that calls an external mock service. But this solution requires you to have two JVM, its configuration is complicated and error prone.</p>
<p><img src="/files/spring-ws-test/seq1.png" alt="Classical WS test" /></p>
<p>I have been looking for something in between, for something that would allow me to write functional tests using JUnit and would be able to run in the same JVM as the test. Unfortunately I have not been able to find anything similar.</p>
<p><img src="/files/spring-ws-test/seq2.png" alt="Spring WS Test test" /></p>
<p>That's the reason why I have created Spring WS Test project. It's quite simple and easy even though I had to spent lot of my evenings getting it into a publishable state.</p>
<p>Basic configuration looks like this</p>
<pre name="code" class="xml">
&lt;beans ...&gt;
  &lt;!-- Creates mock message sender --&gt;
  &lt;bean id=&quot;messageSender&quot; class=&quot;net.javacrumbs.springws.test.MockWebServiceMessageSender&quot;/&gt;

  &lt;!-- Injects mock message sender into WebServiceTemplate --&gt;
  &lt;bean class=&quot;net.javacrumbs.springws.test.util.MockMessageSenderInjector&quot;/&gt;

  &lt;!-- Looks for responses on the disc based on the provided XPath --&gt;
  &lt;bean class=&quot;net.javacrumbs.springws.test.generator.DefaultResponseGeneratorFactoryBean&quot;&gt;
     &lt;property name=&quot;namespaceMap&quot;&gt;
         &lt;map&gt;
            &lt;entry key=&quot;soapenv&quot;
                value=&quot;http://schemas.xmlsoap.org/soap/envelope/&quot;/&gt;
            &lt;entry key=&quot;ns&quot;
                value=&quot;http://www.springframework.org/spring-ws/samples/airline/schemas/messages&quot;/&gt;
         &lt;/map&gt;
     &lt;/property&gt;
     &lt;property name=&quot;XPathExpressions&quot;&gt;
         &lt;list&gt;
             &lt;value&gt;
                 concat(local-name(//soapenv:Body/*[1]),'/default-response.xml')
             &lt;/value&gt;
         &lt;/list&gt;
     &lt;/property&gt;
 &lt;/bean&gt;
&lt;/beans&gt;
</pre>
<p>Here we have MockWebServiceMessageSender that replaces standard Spring <a href="http://static.springsource.org/spring-ws/sites/1.5/apidocs/org/springframework/ws/transport/WebServiceMessageSender.html">WebServiceMessageSender</a>. The replacement is done by MockMessageSenderInjector. The only other thing you have to do is to define ResponseGenerator. It's main purpose is to look for files in you test classpath and return them as mock responses. </p>
<p>Of course it has to decide, which file to use. By default a XPath expression is used to determine the resource name. In our example it is <code>concat(local-name(//soapenv:Body/*[1]),'/default-response.xml')</code>. It takes name of the payload (first soap:Body child) and uses it as a directory name. File “default-response.xml” from this directory is used as the mock response. Simple isn't it? </p>
<p>Of course you can define more complicated XPaths, you can use XSLT templates to generate your responses, you can validate your requests etc. More details can be found in the <a href="http://javacrumbs.net/spring-ws-test/">documentation</a>.  </p>
<p>Now I am looking for some end-user feedback. So please, if you are using Spring WS on the client side do not hesitate and test it. It should be stable enough to be used although there might be a bug here and there.</p>
]]></content:encoded>
			<wfw:commentRss>http://blog.krecan.net/2009/09/02/spring-ws-test/feed/</wfw:commentRss>
		<slash:comments>3</slash:comments>
		</item>
		<item>
		<title>Stoprocentní mantra</title>
		<link>http://blog.krecan.net/2009/08/25/stoprocentni-mantra/</link>
		<comments>http://blog.krecan.net/2009/08/25/stoprocentni-mantra/#comments</comments>
		<pubDate>Tue, 25 Aug 2009 18:26:24 +0000</pubDate>
		<dc:creator>Lukáš Křečan</dc:creator>
				<category><![CDATA[Testy]]></category>

		<guid isPermaLink="false">http://blog.krecan.net/?p=412</guid>
		<description><![CDATA[Programátoři a jejich manažeři občas řeší, jaká míra pokrytí unit testy je dostatečná. Můžeme zaslechnout, že cokoliv pod 60% nestojí za zmínku, občas zahlédneme, že to magické číslo je 95%  a někteří fundamentalisté dokonce tvrdí, že cesta k nirváně vede jen a pouze přes stoprocentní pokrytí. 
Dnes jsem si řekl, že je ideální počasí [...]]]></description>
			<content:encoded><![CDATA[<p>Programátoři a jejich manažeři občas řeší, jaká míra pokrytí unit testy je dostatečná. Můžeme zaslechnout, že cokoliv pod 60% nestojí za zmínku, občas zahlédneme, že to magické číslo je 95%  a někteří fundamentalisté dokonce <a href="http://homepage.mac.com/hey.you/lessons.html">tvrdí</a>, že cesta k nirváně vede jen a pouze přes stoprocentní pokrytí. </p>
<p>Dnes jsem si řekl, že je ideální počasí na to, vyzkoušet jestli se dá sta procent dosáhnout. Povedlo se mi to během dopoledne a nyní bych se chtěl podělit o své zkušenosti.</p>
<p>Pracuji na jednom menším projektu, který v podstatě jen zpracovává REST volání a přeposílá je pomocí SOAP na další systémy. Není to nic složitého, ale není to ani žádná trivialita. Prostě ideální kandidát na pokusy. I před tím, než jsem se rozhodl dosáhnout vytoužené mety, jsem se snažil unit testy dělat poctivě. Jen občas jsem něco neotestoval s tím, že to je příliš triviální na to, abych se patlal s testem. Většinou jsem ale svoji lenost ovládl. Proto mě překvapilo, že moje pokrytí testy bylo něco kolem 60%. </p>
<p>Začal jsem pátrat po příčinách a zjistil jsem, že nejsem tak svědomitý, jak jsem si myslel. Narazil jsem například na neotestovanout třídu, kterou jsem jen odněkud zkopíroval Fůůůůůj. Ale občas je to potřeba. Znáte to, potřebujete něco podobného co umí nějaká metoda ve Springu, jenom je to potřeba trochu ohnout, má to implementovat jiné rozhraní a navíc je to v tom Springu private. Tak to vezmete, zkopírujete a trochu přiohnete. Pokud se pokoušíte o stoprocentní pokrytí, musíte to i otestovat. Pokud se spokojíte s pokrytím nižším, je velice lákavé si říci, že to už je vlastně otestovaný kód, tudíž není potřeba testovat. Ještě jednou fůůůj. Ještě že se stydím jenom před děvčaty. Nakonec jsem byl rád, že jsem tu zkopírovanou metodu musel otestovat. Díky tomu jsem se nad ní pořádně zamyslel a zkrátil ji na polovinu. </p>
<p>Pak jsem ještě napsal pár testů na metody, které jsem nepovažoval za hodné testu. Potěšilo mě, že jsem narazil jenom na jednu metodu, kterou jsem evidentně netestoval, protože by to bylo moc práce. Díky své nové stoprocentní mantře jsem se donutil otestovat i ji. Nakonec to ani moc nebolelo, jenom jsem se musel ponořit do vnitřností Spring-WS abych zjistil jak nejlépe vytvořit instanci jednoho rozhraní (SoapMessage).  Alespoň jsem se něco naučil. Pak už zbývaly jen zapeklitější věci.</p>
<p><strong>Get a Set metody</strong><br />
Jedním ze zádrhelů byly get metody. Poté co jsem otestoval všechen kód, který něco dělá, zbyla mi jedna skupina metod, které prostě v žádném testu nebyly potřeba. Byly to get metody u Spring bean. Když totiž potřebuji pomocí Springu něco injektnout, automaticky vygeneruji set a get metody. A to i když používám autowiring přímo do polí. Set metody využívám právě v unit testech. Ukázalo se, že pokud není v testu set metoda použita, je v tom testu něco špatně. A to bez výjimky. Buď to, co nastavuji, není vůbec potřeba nebo netestuji funkcionalitu, která danou hodnotu využívá. Takže si prosím zapamatujte:</p>
<blockquote><p>Pokud není otestována set metoda, je něco špatně.</p></blockquote>
<p>Ale zpátky ke get metodám u Spring bean. Ty pro test potřeba nejsou. Ony totiž nejsou potřeba vůbec. Jenom jsem měl hrozný psychický problém s tím je smazat. Pořád jsem si říkal, že je tam nechám, co kdyby byly potřeba. Co kdyby někdo potřeboval vědět, jak je daná třída nakonfigurována atp. Ale pak mě stoprocentní mantra donutila je smazat a myslím, že si na ně nikdo nevzpomene. Jenom je to divné mít set bez getu. Kdybych ty get metody opravdu někdy potřeboval, třeba kvůli JMX, tak je prostě přidám a otestuji.</p>
<p><strong>Equals</strong><br />
Dalším špekem je equals metoda. Pokud byste náhodou nevěděli jak vypadá, tak vám ukáži, to co mi normálně generuje Eclipse</p>
<pre name="code" class="java">
	public boolean equals(Object obj) {
		if (this == obj)
			return true;
		if (obj == null)
			return false;
		if (!(obj instanceof Person))
			return false;
		Person other = (Person) obj;
		if (firstname == null) {
			if (other.firstname != null)
				return false;
		} else if (!firstname.equals(other.firstname))
			return false;
		if (secondname == null) {
			if (other.secondname != null)
				return false;
		} else if (!secondname.equals(other.secondname))
			return false;
		return true;
	}
</pre>
<p>A teď si představte jak otestovat všechny možnosti takového krasavce. Abyste dosáhli plného pokrytí, museli byste napsat cca devět testů. To vše kvůli vygenerovanému kódu. K tomu mě nikdo nedonutí. Zkusil jsem použít <a href="http://commons.apache.org/lang/api/org/apache/commons/lang/builder/EqualsBuilder.html">EqualsBuilder</a>, ale moc jsem si nepomohl. I s jeho pomocí jsou tam asi čtyři kombinace, které je potřeba otestovat. Mumlaje si pod vousy „sto procent, sto procent“ jsem se zeptal pana Googla a ten mě navedl na <a href="http://gsbase.sourceforge.net/apidocs/com/gargoylesoftware/base/testing/EqualsTester.html">EqualsTester</a>. Problém vyřešen, jsem zas o krok blíže k vytouženému cíli.</p>
<p><strong>Nemožná výjimk</strong>a<br />
Zbývala mi jen jedna úplně poslední past nastražená na mě pány ze Sunu:</p>
<pre name="code" class="java">
	private byte[] toByteArray(String data)
	{
		try {
			return data.getBytes("UTF-8");
		} catch (UnsupportedEncodingException e) {
			LOG.error("Can not happen",e);
			throw new RuntimeException(e);
		}
	}
</pre>
<p>Abych dosáhl kompletního pokrytí, musím otestovat i catch blok. Ten je bohužel dosažitelný jen pokud vaše JVM nepodporuje UTF-8. Vzhledem k tomu, že by pak JVM nesplňovalo specifikaci není tato situace moc pravděpodobná.  Bohužel, tím pádem ani otestování není moc snadné. Nakonec jsem musel kód změnit takto:</p>
<pre name="code" class="java">
	private static final Charset UTF8 = (Charset)Charset.availableCharsets().get("UTF-8");

	private byte[] toByteArray(String data)
	{
		return data.getBytes(UTF8);
	}
</pre>
<p>Není to moc elegantní, ale alespoň se mohu utěšovat tím, že je to výkonově efektivnější. Pokud znáte lepší cestu, podělte se o ni, rád se něco přiučím.</p>
<p>A to je vše, dosáhl jsem stoprocentního pokrytí. Zde mi samozřejmě hrálo do karet, že jsem nemusel řešit připojení k databázi. To bych se musel uchýlit k mockování JDBC template nebo k mé oblíbené in-memory databázi ve spojení s JPA. To už by sice nebyl unit test, ale třeba by to nikdo nepoznal. </p>
<p>Takže mám stoprocentní pokrytí, co mi to dalo? Donutilo mě to otestovat věci, na které bych se pravděpodobně jinak vykašlal. U některých z nich jsem byl rád, že jsem je nakonec otestoval. Přivedlo mě to k lepšímu kódu. Potěšilo mě, že jsem nemusel psát žádné nesmyslně testy, jenom kvůli pokrytí. Toho jsem se ze začátku trochu bál. Samozřejmě nesmím usnout na vavřínech. To že mám kód zcela pokryt neznamená, že v něm není chyba. Těch tam naprosto jistě ještě hodně zůstalo.  Nicméně mám z toho docela dobrý pocit, myslím si, že 100% je docela dobrá laťka. Na jednu stranu vám nedovolí vymýšlet si výmluvy, proč něco netestujete, na stranu druhou se ukázala jako dosažitelná. Proto se příště jako správný úderník pokusím  pokrýt na 105%.</p>
]]></content:encoded>
			<wfw:commentRss>http://blog.krecan.net/2009/08/25/stoprocentni-mantra/feed/</wfw:commentRss>
		<slash:comments>15</slash:comments>
		</item>
		<item>
		<title>Není důležitá cesta, ale cíl</title>
		<link>http://blog.krecan.net/2009/07/04/neni-dulezita-cesta-ale-cil/</link>
		<comments>http://blog.krecan.net/2009/07/04/neni-dulezita-cesta-ale-cil/#comments</comments>
		<pubDate>Sat, 04 Jul 2009 09:27:52 +0000</pubDate>
		<dc:creator>Lukáš Křečan</dc:creator>
				<category><![CDATA[Uncategorized]]></category>

		<guid isPermaLink="false">http://blog.krecan.net/?p=405</guid>
		<description><![CDATA[Není důležitý cíl, ale cesta k němu
Budha
Jsem členem týmu, který se zrovna formuje. To s sebou nese trochu tápání, diskuzí ohledně toho co a jak chceme dokumentovat, jak se mezi sebou domlouvat, jak testovat, jak dělat revize kódu  a podobně. V poslední době se mi stává, že uprostřed živé diskuze vyslovím svoji zabijáckou otázku. [...]]]></description>
			<content:encoded><![CDATA[<blockquote><p>Není důležitý cíl, ale cesta k němu<br />
Budha</p></blockquote>
<p>Jsem členem týmu, který se zrovna formuje. To s sebou nese trochu tápání, diskuzí ohledně toho co a jak chceme dokumentovat, jak se mezi sebou domlouvat, jak testovat, jak dělat revize kódu  a podobně. V poslední době se mi stává, že uprostřed živé diskuze vyslovím svoji zabijáckou otázku. Vždy je to něco ve smyslu „Proč to chceme dělat?“, „Jaký je cíl?“, „Pro koho to chceme psát?“ nebo „What's the objective?“. Většinou si za podobnou otázku vysloužím pár pohledů, některé z nich říkají „Vždyť je to přece jasné“, jiné „Ty seš zas úplně mimo“. Málokdy zahlédnu pohled říkající „Děkuji, že jsi nás přivedl na pravou a jedinou cestu, ó velký.“. </p>
<p>Tak jsem si řekl, že napíši tento zápisek, aby kolegové věděli, jak ke mně mají vzhlížet. Myslím si totiž, že ať už člověk dělá v práci cokoliv, měl by se nejdřív zamyslet nad cílem. Napadají mě tyto příklady</p>
<ul>
<li>Připravuji prezentaci. Musím se zamyslet nad tím co je ta nejdůležitější věc, kterou chci sdělit. Pak už bývá snadné vymyslet, jak má prezentace vypadat.</li>
<li>Píši dokument. Musím se zamyslet pro koho ho píši a při jaké příležitosti ho bude číst. Jinak vypadá dokument pro manažery, který ho (možná) bude číst jednou při schvalování a jinak pro programátora, který v něm bude občas něco hledat. </li>
<li>Organizuji schůzku. Musím se zamyslet co je ten nejdůležitější výstup. Má někdo něco zařídit? Chci se něco dozvědět? Jakmile v tom mám jasno, mám z půlky vyhráno.</li>
<li>Dělám revizi kódu. Musím se ujistit, že vím proč ji chci dělat. Chci se ujistit, že nováčci píší kód který je konzistentní se stávajícím? Vím že revizi musí dělat zkušenější kolega. Chci zachytit největší chyby co nejdřív? Musím dělat revize průběžně. Chci šířit znalosti? Stačí mi jedna revize na konci za účasti všech.</li>
<li>Píši aplikaci. Měl bych vědět, co je ten hlavní důvod její existence.</li>
<li>Jdu se pohádat s kolegou. Nejdřív bych se měl nadechnout a zamyslet se nad ideálním výstupem z hádky. Čeho jí chci dosáhnout?</li>
<li>Píšu zápisek do blogu. Co je ta hlavní myšlenka, kterou chci sdělit?</li>
</ul>
<p>Zní vám to povědomě nebo dokonce samozřejmě? Není divu. Se stejnou myšlenkou se setkáváme na různých školeních, v agilních metodikách, v chytrých knihách, zkrátka všude. Zamyslete se ale, jak často tento postup dodržujete. Mě se to povede jen občas a to se docela snažím. Ono to totiž není vůbec jednoduché. </p>
<blockquote><p>Na každou otázku existuje jednoduchá, snadno pochopitelná, nesprávná odpověď. </p></blockquote>
<p>Ještě víc se to zesložití, když vám řeknu, že ten cíl by měl být ideálně jen jeden. Já vím, že chcete zabít víc much jednou ranou. Je ale neuvěřitelně užitečné zformulovat jediný snadno popsatelný cíl. Pak si můžete nadefinovat i pár vedlejších cílů, ale pořád musíte vědět, který je ten primární. Je to podobné  jako měli posádky bombardérů za druhé světové. Ty také dostali jeden primární cíl. Pak samozřejmě měli i pár druhotných cílů, kterým se měli věnovat, kdyby jim náhodou nějaká bomba zbyla nebo kdyby byl prvotní cíl nedosažitelný. Ale ten hlavní byl jen jeden. Proč to tak bylo? Přece proto aby věděli kam letět. Kdyby dostali cílů dvacet, tak by jim to k ničemu nebylo.</p>
<p>My jsme v úplně stejné situaci. Jakmile si řekneme, že dokument je určen pro manažery, ale vlastně i pro programátory a přihodíme tam i pár kapitolek pro testery, tak nakonec skončíme s dokumentem, který nebude vhodný pro nikoho. </p>
<p>Dejme tomu, že jsme investovali velké úsilí a dost času a máme cíl, s který je jasně sdělitelný a pochopitelný. Čeká nás další krok. Musíme cíl roztroubit. Musíme zajistit, aby všichni zúčastnění věděli co ten cíl je. Napíšeme to do pozvánky, na začátek dokumentu, řekneme to v úvodu, prostě se ujistíme, že to všichni vědí. U opakovaných akcí to čas od času zopakujeme. Ještě lepší je, když se na cíli zúčastnění dohodnou sami, ale to už bych toho chtěl moc.</p>
<blockquote><p>Promiňte mi tento dlouhý dopis, ale neměl jsem čas napsat krátký.<br />
Pascal</p></blockquote>
<p>Jakmile mám super cíl a všichni o něm vědí, můžeme si začít užívat jeho pozitivních účinků. Nejlépe je to vidět na schůzkách. Když lidé vědí proč tam sedí, vědí o čem mají mluvit. Organizátor  dokonce může schůzku nasměrovat, když se stáčí někam kam nemá. Lidé dokonce dopředu vědí, jestli jsou na té schůzce potřeba. Někdy se dokonce při vymýšlení cíle schůzky zjistí, že není vůbec potřeba, že se ten cíl dá naplnit úplně jinak, jednodušeji. </p>
<p>To je hrozně důležité. Při vymýšlení cíle, často přijdeme na to, že k jeho naplnění by se nám hodily úplně jiné prostředky.</p>
<p>Cíle také umožňují prioritizaci. Pokud vím co je cílem iterace, mohu si při nedostatku času vybírat, které úkoly jsou důležitější. Všechno co s cílem nesouvisí musí pryč. Stejně tak u dokumentů, co neslouží k cíli tam nemá co dělat. O prezentacích nemluvě, dobrá prezentace se pozná podle toho, že je jasné co se vám přednášející snaží říci. </p>
<p>Zbývá nám tedy otázka, proč se to tak málo vidí? Proč chodíme na schůzky, u kterých nevíme proč jsou svolávány, proč čteme dokumenty, u kterých není jasné komu jsou určeny, proč píšeme programy, u kterých si nejsme jisti k čemu mají sloužit? Důvodů je asi víc. </p>
<p>Hlavně si všichni myslí, že cíl je přeci jasný. Všichni přeci víme, proč se každý týden scházíme a říkáme si co kdo dělal a bude dělat, všichni vědí, proč píšeme ten který typ testů, všichni přece víme proč děláme revizi kódu, všichni víme proč píšeme design. Opravdu? Tak mi to řekněte jednou větou.</p>
<p>Mám podezření, že dalším problémem s cílem je, že nutí lidi myslet. Já například myslím hrozně nerad. Je jednodušší svolat schůzku a o něčem si povídat, než si lámat hlavu s cílem. Jasné cíle také lidi neuvěřitelně omezují. Když třeba dělám prezentaci, tak chci předvést co všechno o tématu vím, nechci se nějak omezovat. Když píšu dokument pro manažery, chci se vytáhnout, tak tam švihnu jak bude vypadat databáze. Když píšu blog, tak chci předvést jak jsem skvělý, ne se soustředit na na nějaký trapný cíl. Na druhou stranu, kdybych to udělal, byl by i tento zápisek dvakrát kratší a mnohem lepší.</p>
]]></content:encoded>
			<wfw:commentRss>http://blog.krecan.net/2009/07/04/neni-dulezita-cesta-ale-cil/feed/</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
	</channel>
</rss>
