<?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>Webtrh Blog</title>
	<atom:link href="http://blog.webtrh.cz/feed" rel="self" type="application/rss+xml" />
	<link>http://blog.webtrh.cz</link>
	<description></description>
	<lastBuildDate>Mon, 25 Jul 2011 12:41:55 +0000</lastBuildDate>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>http://wordpress.org/?v=3.0.5</generator>
		<item>
		<title>Jak zrychlit Web(trh)</title>
		<link>http://blog.webtrh.cz/rychlost</link>
		<comments>http://blog.webtrh.cz/rychlost#comments</comments>
		<pubDate>Fri, 22 Jul 2011 06:00:30 +0000</pubDate>
		<dc:creator>Martin</dc:creator>
				<category><![CDATA[Nezařazené]]></category>

		<guid isPermaLink="false">http://blog.webtrh.cz/?p=142</guid>
		<description><![CDATA[Posledních několik dní jsem, povzbuzený přestěhováním na nový server, zrychloval načítání Webtrhu. Reakční doba Náš dojem z aplikace se mění podle reakční doby: Pod 0,1 s vnímáme reakci jako okamžitou. Aplikace reaguje na naše požadavky, přímo ji ovládáme. Pod 1 &#8230; <a href="http://blog.webtrh.cz/rychlost">Celý příspěvek <span class="meta-nav">&#8594;</span></a>]]></description>
			<content:encoded><![CDATA[<p>Posledních několik dní jsem, povzbuzený <a href="http://webtrh.cz/145951-novy-server-rychlejsi-webtrh">přestěhováním na nový server</a>, zrychloval načítání <a href="http://webtrh.cz/">Webtrhu</a>.</p>
<p><strong>Reakční doba</strong><br />
Náš dojem z aplikace <a href="http://www.useit.com/papers/responsetime.html">se mění podle reakční doby</a>:</p>
<p>Pod 0,1 s vnímáme reakci jako okamžitou. Aplikace reaguje na naše požadavky, přímo ji ovládáme.<br />
Pod 1 s ztrácíme pocit okamžitosti, ale prodleva nepřerušuje naši práci.<br />
Prodleva pod 10 s přerušuje uživatelovu práci, ale ten ještě dokáže udržet pozornost na úkol.<br />
Reakce trvající déle než 10 s ztrácí lidskou pozornost.</p>
<p>Cíl je jasný: Reagovat pod desetinu sekundy.</p>
<p><strong>Jaká kritéria optimalizovat</strong><br />
<em>1. Co nejméně požadavků</em><br />
<a href="http://code.google.com/speed/page-speed/docs/rtt.html">Každý požadavek je drahý</a>. Může obsahovat řadu zdržujících činností od překladu DNS, zahájení a ukončení TCP [neřkuli SSL] spojení po zbytečné chybové (4xx) a přesměrovávací (30x) stavy.<br />
Je vhodné požadavky spojit, šetřit spojení &#8211; udržovat je otevřené pomocí Keep-Alive &#8211; a opakované požadavky úplně odstranit správným cachováním.</p>
<p><em>2. Rychlé odpovědi</em><br />
Požadavky musí být vyřízené co nejdřív. Server je musí zpracovat rychle, výstup odeslat co nejdřív a odpověď musí cestovat co nejrychleji.</p>
<p><em>3. Malé odpovědi</em><br />
Všechny odpovědi je důležité gzipovat a kód &#8211; HTML, JS, CSS &#8211; předtím minifikovat, pokud je to možné.<br />
U kódu se objem přenášených dat po minifikaci a gzipování zmenší většinou <a href="http://compressorrater.thruhere.net/">na méně než 20%</a>.</p>
<p><em>4. Feedback co nejdřív</em><br />
Často můžeme dát uživateli feedback ještě před odesláním požadavku. Reakční doba je pak rozložená na okamžitý feedback a opožděné zobrazení odpovědi. Neurychlí se tím samotné provádění úkolu, ale zlepší se dojem z používání aplikace.</p>
<p><strong>MySQL</strong><br />
Vlastně jsem na začátku neříkal úplně pravdu. Optimalizovat jsem začal už v zimě, kdy jsem se zakousl do užitečné knihy <a href="http://www.amazon.com/High-Performance-MySQL-Optimization-Replication/dp/0596101716/">High Performance MySQL</a>.</p>
<p>Autoři měli naprostou pravdu, když tvrdili, že správně navržené indexy a napsané dotazy dokáží urychlit zpracování dat o řády. <a href="http://webtrh.cz/">Hlavní stránku Webtrhu</a> jsem přepsáním několika dotazů a úpravou indexů zrychlil z několika sekund na desetiny.</p>
<p>Optimalizace nastavení SQL serveru a cachování výkon vylepšila přesně podle jejich předpovědi už &#8222;jen&#8220; v desítkách procent.</p>
<p>Pokud má aplikace problémy v DB, je dobré začít právě tam. Optimalizace DB poskytne nejvíc muziky, protože nejvíc ovlivňuje <a href="http://blog.browsermob.com/2009/04/understanding-time-to-first-byte/">Time To First Byte</a>.</p>
<p><strong>Server</strong><br />
Všechny odpovědi by se měly gzipovat a měly by mít správné hlavičky pro cachování. V Apache jednoduše pomocí <a href="http://httpd.apache.org/docs/2.0/mod/mod_expires.html">mod_expires</a> a <a href="http://httpd.apache.org/docs/2.0/mod/mod_deflate.html">mod_deflate</a>:</p>
<p><code>
<pre>&lt;IfModule mod_deflate.c>
  AddOutputFilterByType DEFLATE text/html text/plain text/css\
 text/xml application/x-javascript text/javascript application/javascript
&lt;/IfModule>

&lt;IfModule mod_expires.c>
  ExpiresActive on
  ExpiresDefault                          "access plus 1 month"
  ExpiresByType text/html                 "access plus 0 seconds"
  ExpiresByType text/xml                  "access plus 0 seconds"
  ExpiresByType application/xml           "access plus 0 seconds"
  ExpiresByType application/json          "access plus 0 seconds"
  ExpiresByType application/rss+xml       "access plus 1 hour"
&lt;/IfModule></pre>
<p></code></p>
<p>Víc komentované konfigurace je v ukázkovém <a href="https://github.com/paulirish/html5-boilerplate/blob/master/.htaccess">.htaccess HTML5Boilerplate</a>.</p>
<p>Až budeme cachované soubory měnit, klienty přinutíme stáhnout si novou verzi souboru změnou jména. Stačí upravit query za otazníkem:<br />
<code>external.js?20110721</code></p>
<p>Nezapomeňte zkontrolovat zapnuté Keep-Alive (Apache má defaultně zapnutý) pro udržování otevřených spojení.</p>
<p>Výstup bychom měli začít odesílat co nejdřív. Pokud se v requestu provádí nějaká údržba, je dobré postupovat takto:</p>
<ol>
<li>Vytvořit výstup</li>
<li><strong>Odeslat výstup</strong></li>
<li>Provést údržbu (zvýšení čítačů, přepočet statistik apod.)</li>
</ol>
<p>Nebo ještě čistěji &#8211; přesunout údržbu do pravidelně volaných procesů.</p>
<p>PHP v továrním nastavení odešle výstup až na konci běhu skriptu. Dá se přinutit k okamžitému odeslání pomocí <a href="http://cz.php.net/manual/en/function.flush.php">flush();</a> (jednorázově), <a href="http://cz.php.net/manual/en/function.ob-implicit-flush.php">ob_implicit_flush();</a> (po dobu běhu skriptu) nebo <a href="http://cz.php.net/manual/en/outcontrol.configuration.php">příslušným konfiguračním příznakem</a>.</p>
<p>Této techniky jsem se musel zříct, protože ve vBulletinu se HTML výstup generuje až úplně nakonec. Můžeme ji ale využít třeba u AJAX požadavků.</p>
<p>Nainstaloval jsem taky <a href="http://cz.php.net/manual/en/book.apc.php">APC</a>, opcode cache pro PHP, nakonec s touto <a href="http://cz.php.net/manual/en/apc.configuration.php">konfigurací</a>:</p>
<p><code>
<pre>
apc.shm_size="128" ; velikost cache v MB.
  ; Pokud APC nepoužívá mmap, nastavit <a href="http://www.imminentweb.com/technologies/tune-apc-improve-php-performance">podle tohoto</a>
apc.stat="0" ; APC přestává při každém požadavku ověřovat, jestli se soubor nezměnil.
  ; Pro staging server zapnout
apc.ttl="86400" ; životnost opcode cache
apc.user_ttl="86400" ; životnost user cache (proměnných)
apc.lazy_functions="1"
apc.lazy_classes="1"
 ; Dvě nové featury <a href="http://tekrat.com/2009/03/10/apc-lazy-loading-initial-support/">přidané vývojáři Facebooku</a>, lazy loading funkcí a tříd
</pre>
<p></code></p>
<p><strong>HTML</strong><br />
Požadavky jsou drahé, takže pokud je to možné, spojte všechny JS soubory do jednoho, všechny CSS do jednoho, a všechny obrázky do jednoho image spritu.</p>
<p>HTML je možné minifikovat pomocí CSSMin nebo YUI Compressoru, ale pozor na signifikantní whitespace. Na Webtrhu minifikace začala žrát odstavce (oddělené novými řádky), kdykoliv jsem editoval příspěvek.</p>
<p><strong>Javascript</strong><br />
Javascript blokuje render a načítání kvůli document.write. Proto se dřív doporučovalo: <a href="http://developer.yahoo.com/performance/rules.html#js_bottom">Přesuňte JS až na konec stránky</a>. Dnes existuje lepší metoda.</p>
<p>Přestaňte používat document.write a načítejte JS asynchronně pomocí knihovny jako <a href="http://labjs.com/">LABjs</a> nebo <a href="http://requirejs.org/">Require.js</a>. Pro Webtrh jsem zvolil LABjs, nedělá nic jiného a gzipovaná má jen 2,2 kB.<br />
Javascript se pak načítá mimo ostatní requesty na stránce a neblokuje je.</p>
<p>Kód musí být připravený pro minifikaci. Minifikátory jsou různě agresivní, od extra agresivního <a href="http://dean.edwards.name/packer/">Dean Edwards Packeru</a> přes hodně doporučovaný <a href="http://developer.yahoo.com/yui/compressor/">YUI Compressor</a> až po mírumilovný <a href="http://www.crockford.com/javascript/jsmin.html">JSMin</a> od Douglase Crockforda.</p>
<p>Kód zabalený Packerem nefungoval správně a jelikož rozdíl mezi minifikátory <a href="http://compressorrater.thruhere.net/">je zanedbatelný</a>, nevěnoval jsem se tomu a zvolil JSMin.</p>
<p><strong>Překvapivé překážky při přeskládávání JS</strong><br />
(V nouzi pomůže aliterace. :)</p>
<p>Při spojování souborů do jediného se vyskytla chyba v syntaxi, protože poslední deklarace v jednom ze spojovaných souborů nebyla ukončená středníkem. První deklarace z následujícího souboru se tedy stala součástí předchozí deklarace a syntax error byl na světě:<br />
<code>callMe()callMeToo();</code></p>
<p>Jakmile začnete načítat všechny skripty na stránce asynchronně a zároveň máte ve stránce inline skripty, začnou okamžitě v konzoli vyskakovat chyby. Inline skripty se totiž najednou rozběhnou PŘED načtením zdrojů.<br />
LABjs poskytuje řešení ve formě metody wait():<br />
<code>
<pre>$LAB
.script('external.js')
.wait( function() {
  // na předchozím souboru závislé inline skripty
});</pre>
<p></code><br />
To s sebou ale přineslo několik neočekávaných záludností, které mě přiměly k emotivním commitům v Gitu. :)</p>
<p>Problém č. 1: Pokud je external.js načtený z cache a je dlouhý, <strong>inline skripty se spustí dřív, než se interpretuje kód z externího souboru</strong>.<br />
Řešení: <code>setTimeout(executeInlines, 1);</code></p>
<p>Problém č. 2: <strong>Inline skripty ztratí globální scope, na kterém závisí.</strong> Zároveň jsou deklarované jako <a href="http://javascript.crockford.com/private.html">privátní proměnné</a> a nelze je uchopit výčtem<br />
<code>for(var prop in this) {}</code><br />
Čisté řešení: Zbavit kód závislosti na globálním scope. V ideálním případě bych skripty přepsal a zbavil <a href="http://metatv.cz/index.php?iden=22358044&#038;porad=eclub">chybné závislosti na globálním stavu</a>. Protože legacy kód má ale několik tisíc řádků, použil jsem regex/eval hack zmíněný dál. Šlo o <a href="http://blog.webtrh.cz/refactoring">záměrné rozhodnutí ponechat technický dluh</a>, abych se nezdržel na několik dnů až týdnů.<br />
Rychlé řešení: Projít inline kód regexpem a vybrat všechny názvy funkcí a lokálních proměnných. Předat je JS proměnné, a zkopírovat eval()em do globálního scope.<br />
Brutální, ale funguje.</p>
<p>Problém č. 3: Protože se asynchronní skript načítá nezávisle, <strong>je nutné explicitně stanovit závislosti všech událostí</strong>.<br />
Tohle zní nevinně, ale zabralo mi to celý den. vBulletin definuje dvě vlastní události, které se musí odpálit v určitém pořadí. Nikde to ale není explicitně napsané, natožpak nakódované.<br />
Protože na sebe skripty a DOM přestaly čekat, události se spouštěly v náhodném pořadí.<br />
Řešení: Identifikovat závislost a explicitně ji uvést do kódu:<br />
Událost č. 2 musí počkat na událost č. 1.</p>
<p><strong>Rozhraní</strong><br />
Pokud má akce jasný výsledek (jeden stav), můžeme <strong>zareagovat ještě před odesláním požadavku</strong>. Rozhraní se pak chová responzivněji, ačkoliv se reakční doba nezkrátila.</p>
<p>Okamžitý feedback jsem aplikoval v hlavním navigačním menu Webtrhu. Menu zareaguje na kliknutí ihned, ještě předtím, než se začne načítat nová stránka. <a href="http://webtrh.cz/forum">Vyzkoušejte to.</a></p>
<p><strong>Co dál</strong><br />
Zrychlování stránky se odehrává na mnoha úrovních a je to hodně zajímavá a uspokojující činnost. :)<br />
Nepodařilo se mi zatím ale dosáhnout původního cíle a zrychlit stránky pod desetinu sekundy.</p>
<p>Jak zrychlit načítání dál? Použít pro statický obsah <a href="http://code.google.com/intl/cs/speed/page-speed/docs/request.html#ServeFromCookielessDomain">doménu bez cookies</a>. Zvětšit <a href="http://blog.benstrong.com/2010/11/google-and-microsoft-cheat-on-slow.html">initial TCP congestion window</a>. Dál optimalizovat databázi. Agresivněji cachovat části stránek, alespoň pro nepřihlášené návštěvníky.</p>
<p>Jaké máte další nápady?</p>
<p><strong>Další čtení</strong></p>
<ul>
<li><a href="http://code.google.com/intl/cs/speed/page-speed/docs/rules_intro.html">Web Performance Best Practices</a></li>
<li><a href="http://developer.yahoo.com/performance/rules.html">Best Practices for Speeding Up Your Web Site</a></li>
</ul>
]]></content:encoded>
			<wfw:commentRss>http://blog.webtrh.cz/rychlost/feed</wfw:commentRss>
		<slash:comments>7</slash:comments>
		</item>
		<item>
		<title>Umění unit testování</title>
		<link>http://blog.webtrh.cz/unit-testy</link>
		<comments>http://blog.webtrh.cz/unit-testy#comments</comments>
		<pubDate>Tue, 07 Jun 2011 08:16:00 +0000</pubDate>
		<dc:creator>Martin</dc:creator>
				<category><![CDATA[Nezařazené]]></category>

		<guid isPermaLink="false">http://blog.webtrh.cz/?p=119</guid>
		<description><![CDATA[Rychlé zápisky z The Art of Unit Testing. Předpoklady Minimalizujte závislosti na globálních sdílených datech. Vytvářejte v kódu švy (seams), na které se testy napojí. Konkrétně Nepoužívejte statické metody a singletony. Kód, který je využívá, se špatně testuje. Když už &#8230; <a href="http://blog.webtrh.cz/unit-testy">Celý příspěvek <span class="meta-nav">&#8594;</span></a>]]></description>
			<content:encoded><![CDATA[<p>Rychlé zápisky z <a href="http://www.amazon.com/Art-Unit-Testing-Examples-Net/dp/1933988274/">The Art of Unit Testing</a>.</p>
<p>Předpoklady</p>
<ul>
<li>Minimalizujte závislosti na globálních sdílených datech.</li>
<li>Vytvářejte v kódu švy (seams), na které se testy napojí.</li>
</ul>
<p>Konkrétně</p>
<ul>
<li><a href="http://codebetter.com/jeremymiller/2005/07/20/tdd-design-starter-kit-static-methods-and-singletons-may-be-harmful/">Nepoužívejte statické metody a singletony.</a> Kód, který je využívá, se špatně testuje.</li>
<li>Když už používáte statickou metodu, nevolejte ji přímo, ale přes pomocnou nestatickou metodu, kterou lze přepsat potomkem.</li>
<li>Když už používáte singleton, oddělte od sebe samotný kontejner singletonu a jeho logiku. Tak můžete v testu přepsat logiku.</li>
<li>Neinstancujte objekty v metodách s logikou. Použijte jednoduchou tovární metodu, nebo objekt předejte klientovi přes konstruktor nebo pomocnou metodu (použijte <a href="http://blog.fossmo.net/post/Dependency-Injection-explained.aspx">Dependency Injection</a>).</li>
<li>Spoléhejte se na rozhraní, ne na konkrétní třídy.</li>
</ul>
<p>Best practices</p>
<ul>
<li>Testujte veřejný interface, ne implementaci.</li>
<li>Použijte jeden assert na test.</li>
<li>Pište testy nezávislé na sobě. Testy se nesmí volat navzájem, sdílet proměnné a nesmí spoléhat na pořadí.</li>
<li>Testy nemají obsahovat žádnou logiku. Žádné řídící prvky typu if, switch, while, for atd.</li>
<li>Testy musí být velmi jednoduché spustit a musí běžet automaticky &#8211; při buildu nebo pravidelně.</li>
<li>Testy musí být spolehlivé a spravovatelné, jinak přestanou plnit svoji roli.</li>
<li>Autor doporučuje testovací metody pojmenovávat podle vzoru<br />
<code>MethodUnderTest_TestingScenario_ExpectedResult();</code><br />
Neboli podle mnemotechnické pomůcky: Když volám metodu X s Y, musí vrátit Z:<br />
<code>X_Y_Z();</code></li>
</ul>
]]></content:encoded>
			<wfw:commentRss>http://blog.webtrh.cz/unit-testy/feed</wfw:commentRss>
		<slash:comments>6</slash:comments>
		</item>
		<item>
		<title>Motivační síla rychlých updatů</title>
		<link>http://blog.webtrh.cz/updaty-motivace</link>
		<comments>http://blog.webtrh.cz/updaty-motivace#comments</comments>
		<pubDate>Wed, 25 May 2011 14:27:19 +0000</pubDate>
		<dc:creator>Martin</dc:creator>
				<category><![CDATA[Nezařazené]]></category>

		<guid isPermaLink="false">http://blog.webtrh.cz/?p=101</guid>
		<description><![CDATA[Zveřejnili jsme třetí update za tři týdny. Je to skvělý pocit. Na čem vlastně děláme? Všechny změny hlavně vylepšují uživatelský zážitek při obchodování &#8211; něco, co jsme dlouho a moc zanedbávali. První update překopal od základů rozhraní obchodů (příhozy, editace). &#8230; <a href="http://blog.webtrh.cz/updaty-motivace">Celý příspěvek <span class="meta-nav">&#8594;</span></a>]]></description>
			<content:encoded><![CDATA[<p>Zveřejnili jsme třetí update za tři týdny. Je to skvělý pocit.</p>
<p>Na čem vlastně děláme?<br />
Všechny změny hlavně vylepšují uživatelský zážitek při obchodování &#8211; něco, co jsme dlouho a moc zanedbávali.</p>
<p>První update překopal od základů rozhraní obchodů (příhozy, editace). Druhý zpřehlednil centrum obchodů (přehled, čeho se kde účastním a jak si vedu). V posledním updatu jsme úplně přepsali notifikace (zprávy typu <em>Ztratili jste vedení v aukci</em>, <em>Vyhráli jste</em>). Přepsáním myslím texty, situace, ve kterých se posílají, i kód, který je obsluhuje.</p>
<p>Notifikace jsme psali s těmito pravidly na mysli:</p>
<ol>
<li>Předej informace co nejrychleji</li>
<li>Buď stručný</li>
<li>Buď přátelský</li>
<li>Vyzvi k akci</li>
</ol>
<p>Ad 1. Notifikace chodí nově preferenčně na email (místo do pošty) a nejdůležitější informace jsou už v předmětu. Není ani nutné je otvírat (srovnej <em>lákavé</em> předměty typu &#8222;Newsletter 04/11&#8243;).<br />
Ad 2. Čas je drahý, takže žádné zbytečné fráze. Všechno je jasné na první pohled.<br />
Ad 3. Stručnost ale nevylučuje přátelský tón. Nemá smysl někomu kazit den, když už prohrál v aukci. Popřejeme mu víc úspěchů do budoucna a dáme nějaký krátký tip.<br />
Ad 4. Všude, kde to dává smysl, rovnou píšeme, co uživatele čeká, co může nebo musí udělat. Jsou to většinou banální rady typu &#8222;<em>Vyhráli jste aukci: Zkontaktujte prodávajícího v poště nebo emailem, pošlete mu platbu a dokončete obchod.</em>&#8220; Nicméně věřím, že každá taková drobnost pomáhá uživatelům snížit kognitivní zátěž. Nemusí ani na chvíli přemýšlet, jaký je další postup, protože jim to rovnou píšeme.</p>
<p>Updaty jsou víceméně neviditelné, ale přesto mají obrovský vliv na naši morálku.</p>
<p>Získali jsme setrvačnost a jedeme!</p>
]]></content:encoded>
			<wfw:commentRss>http://blog.webtrh.cz/updaty-motivace/feed</wfw:commentRss>
		<slash:comments>5</slash:comments>
		</item>
		<item>
		<title>Proč stavíme umíněnou aplikaci</title>
		<link>http://blog.webtrh.cz/umineny-software</link>
		<comments>http://blog.webtrh.cz/umineny-software#comments</comments>
		<pubDate>Tue, 24 May 2011 17:00:09 +0000</pubDate>
		<dc:creator>Martin</dc:creator>
				<category><![CDATA[Nezařazené]]></category>

		<guid isPermaLink="false">http://blog.webtrh.cz/?p=106</guid>
		<description><![CDATA[Čím víc voleb aplikace uživateli předkládá, tím víc ho zatěžuje. A tím větší nerozhodnost prokazuje. Proto dávám přednost umíněnému softwaru (opinionated software), který rozhodne nepodstatné věci za uživatele a nechá mu jen několik opravdu důležitých rozhodnutí. Na Webtrhu jsme přešli &#8230; <a href="http://blog.webtrh.cz/umineny-software">Celý příspěvek <span class="meta-nav">&#8594;</span></a>]]></description>
			<content:encoded><![CDATA[<p>Čím víc voleb aplikace uživateli předkládá, tím víc ho zatěžuje. A tím větší nerozhodnost prokazuje. Proto dávám přednost umíněnému softwaru (<a href="http://www.google.com/search?hl=en&#038;num=100&#038;q=%22opinionated+software%22">opinionated software</a>), který rozhodne nepodstatné věci za uživatele a nechá mu jen několik opravdu důležitých rozhodnutí.</p>
<p>Na Webtrhu jsme přešli od nerozhodnosti k umíněnosti už před několika měsíci. Nejlépe je to vidět na aukcích. Dřív bylo možné schvalovat příhozy, automaticky schvalovat příhozy některých přihazující, naopak vylučovat přihazující z aukce, přihazovat veřejně nebo privátně, ručně nebo automaticky.</p>
<p>Všechny volby jsme v posledních měsících zrušili. A co se stalo?</p>
<p>Nic. Nedostali jsme jedinou stížnost a mohli jsme radikálně zjednodušit rozhraní pro prodávající i přihazující.</p>
<p>Nestavíme švýcarský nůž, ale aplikaci s vlastním názorem na obchodování přes internet. Je jasné, že tento přístup nám ztratí nějakou malou část uživatelů, kteří bez neexistující volby prostě nemůžou být, ale většina uživatelů díky tomu bude mít podstatně lepší uživatelský zážitek.</p>
<p>Nezahlťte uživatele volbami. Stavte umíněný software.</p>
<p>Doplnění: Článek <a href="http://flyosity.com/iphone/kill-the-settings-build-opinionated-software.php">Kill The Settings, Build Opinionated Software</a> obsahuje odkaz <a href="http://dlanham.com/ui/twitterrific/settings.jpg">na tento neuvěřitelný screenshot</a>. Nastavení před redesignem a po něm. :)</p>
]]></content:encoded>
			<wfw:commentRss>http://blog.webtrh.cz/umineny-software/feed</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
		<item>
		<title>Refactoring, neboli splácení technického dluhu</title>
		<link>http://blog.webtrh.cz/refactoring</link>
		<comments>http://blog.webtrh.cz/refactoring#comments</comments>
		<pubDate>Sat, 16 Apr 2011 08:00:48 +0000</pubDate>
		<dc:creator>Martin</dc:creator>
				<category><![CDATA[Nezařazené]]></category>

		<guid isPermaLink="false">http://blog.webtrh.cz/?p=63</guid>
		<description><![CDATA[Po Code Complete jsem do ruky vzal Refactoring od Martina Fowlera. Hlavní část knihy tvoří katalog refaktoračních technik, od základních Move Method, Rename Method až po větší změny struktury jako Replace Conditional with Polymorphism. Číst katalog celý je nuda, takže &#8230; <a href="http://blog.webtrh.cz/refactoring">Celý příspěvek <span class="meta-nav">&#8594;</span></a>]]></description>
			<content:encoded><![CDATA[<p>Po <a href="http://blog.webtrh.cz/code-complete">Code Complete</a> jsem do ruky vzal <a href="http://www.amazon.com/Refactoring-Improving-Design-Existing-Code/dp/0201485672/">Refactoring</a> od <a href="http://martinfowler.com/">Martina Fowlera</a>. Hlavní část knihy tvoří katalog refaktoračních technik, od základních <a href="http://refactoring.com/catalog/moveMethod.html">Move Method</a>, <a href="http://refactoring.com/catalog/renameMethod.html">Rename Method</a> až po větší změny struktury jako <a href="http://refactoring.com/catalog/replaceConditionalWithPolymorphism.html">Replace Conditional with Polymorphism</a>.</p>
<p>Číst katalog celý je nuda, takže si vybírám hlavně části popisující úmysl a snažím se pochopit, jak Martin Fowler přemýšlí. Hodně témat se opakuje z Code Complete:<br />
Úpravy programu tvoří mnohem větší část celého životního cyklu než samotné psaní.<br />
Kód se píše pro lidi, ne pro počítač.<br />
Hlavním způsobem snižování složitosti je <a href="http://blog.webtrh.cz/information-hiding">schovávání informací</a>.</p>
<p>Fowler má nějaké užitečné postupy. Například se snaží místo komentářů používat názvy metod. Pokaždé, když má potřebu něco okomentovat, se podívá, jestli komentovaný blok nemůže raději <a href="http://refactoring.com/catalog/extractMethod.html">extrahovat do nové metody</a> a dát mu jméno, které by jeho záměr popisovalo místo komentáře.</p>
<p>Ukázka je vidět přímo v popisu <a href="http://refactoring.com/catalog/extractMethod.html">Extract Method</a>.</p>
<p>Původní kód</p>
<pre>void printOwing() {
    printBanner();

    <strong>//print details</strong>
    System.out.println ("name:	" + _name);
    System.out.println ("amount	" + getOutstanding());
}</pre>
<p>přepíše na</p>
<pre>void printOwing() {
    printBanner();
    <strong>printDetails(getOutstanding());</strong>
}

void printDetails (double outstanding) {
    System.out.println ("name:	" + _name);
    System.out.println ("amount	" + outstanding);
}</pre>
<p>Jiný postřeh: Jediné místo, kam podle něj (v kontextu OOP/Javy) patří <em>switch</em>, je tovární metoda. Všude jinde by měl být nahrazený právě <a href="http://sourcemaking.com/design_patterns/factory_method">factory method</a> a polymorfismem.</p>
<p><strong>Technický dluh</strong><br />
Refactoring mě přiměl k zamyšlení nad <a href="http://www.martinfowler.com/bliki/TechnicalDebt.html">technickým dluhem</a>. Rozhodnutí odbýt návrh a vývoj bude mít důsledky v budoucnu, až program budeme chtít upravit, přidat novou platební metodu, upravit formulář apod.</p>
<p>Srozumitelnější kód se lépe spravuje, tak proč jej nepsat rovnou? Můžou k tomu vést různé úmysly. Fowler má moc pěkný kvadrant důvodů pro vznik technického dluhu:</p>
<p><img src="http://blog.webtrh.cz/wp-content/uploads/2011/04/techDebtQuadrant.png" alt="Reckless vs Prudent, Deliberate vs Inadvertent" title="Technical Debt Quadrant" width="512" height="384" class="alignnone size-full wp-image-67" /></p>
<p>Technický dluh může vzniknout záměrně nebo neúmyslně, z ledabylého nebo rozvážného přístupu. Je nutné snažit se učinit veškerá rozhodnutí o technickém dluhu explicitně, s vědomím budoucí zátěže.</p>
<p>Refaktoring je <em>vylepšování existujícího kódu</em>, jak zní podtitul knihy, a to vlastně není nic jiného než <em>splácení technického dluhu</em>. Nižší technický dluh (tedy lepší návrh) vede k nižším splátkám, tj. levnějším modifikacím a opravám.</p>
<p>Ze širšího pohledu je Code Complete (a <a href="http://www.amazon.com/Clean-Code-Handbook-Software-Craftsmanship/dp/0132350882/">Clean Code</a>) o tom, jak psát software s co nejnižším dluhem (tedy dobře spravovatelný), Refactoring je o splácení existujícího dluhu.</p>
]]></content:encoded>
			<wfw:commentRss>http://blog.webtrh.cz/refactoring/feed</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>Šetři můj mozek a obnažuj toho co nejméně</title>
		<link>http://blog.webtrh.cz/information-hiding</link>
		<comments>http://blog.webtrh.cz/information-hiding#comments</comments>
		<pubDate>Fri, 15 Apr 2011 08:00:46 +0000</pubDate>
		<dc:creator>Martin</dc:creator>
				<category><![CDATA[Nezařazené]]></category>

		<guid isPermaLink="false">http://blog.webtrh.cz/?p=75</guid>
		<description><![CDATA[Některým může tento článek připadat jako zbytečný truismus. Nicméně na dubnové Ruby(/Python) středě jsem se dostal do sporu s Pythonisty, kteří obhajovali neexistenci private a protected členů argumentem, že &#8222;jsme přece všichni rozumní lidé&#8222;. Stačí použít podtržítko před názvem a &#8230; <a href="http://blog.webtrh.cz/information-hiding">Celý příspěvek <span class="meta-nav">&#8594;</span></a>]]></description>
			<content:encoded><![CDATA[<p>Některým může tento článek připadat jako zbytečný truismus. Nicméně na dubnové Ruby(/Python) středě jsem se dostal do sporu s Pythonisty, kteří obhajovali <a href="http://mail.python.org/pipermail/python-list/2008-June/thread.html#545309">neexistenci private a protected členů</a> argumentem, že &#8222;<a href="http://mail.python.org/pipermail/tutor/2003-October/025932.html">jsme přece všichni rozumní lidé</a>&#8222;. Stačí použít podtržítko před názvem a všichni ví, že ten člen nemají používat, a pokud ano, jen na vlastní nebezpečí.</p>
<p>Někteří šli ještě dál a tvrdili, že schovávání je v interpretovaných jazycích úplně k ničemu. Když někdo bude chtít zavolat metodu, zavolá ji přes reflection či podobnou vlastnost jazyka, nebo ji natvrdo prohlásí za <em>public</em>, protože má k dispozici zdroj.</p>
<p>Ale o to přece vůbec nejde.</p>
<p>Schovávání implementace a členů není důležité proto, aby na ně nikdo nesahal, ale proto, aby na ně nikdo, kdo s třídou pracuje, <strong>nemusel myslet</strong>! Aby si mohl uvolnit omezenou kapacitu lidského mozku pro důležitější úkoly. Aby viděl jen interface a nemusel zároveň přemýšlet o implementaci. Aby mohl přemýšlet &#8211; místo o datových typech, algoritmech a databázi &#8211; o problému v jazyce reálného světa &#8211; &#8222;zákazník, faktury, doba dodání, DPH, reklamace&#8220;.</p>
<p><strong>Každý prvek v programu by měl obnažovat jen minimální sadu vlastností, potřebnou pro komunikaci se světem.</strong></p>
<p>Skrývání je sexy.</p>
<p><img src="http://blog.webtrh.cz/wp-content/uploads/2011/04/hiding-is-sexy.jpg" alt="" title="Hiding is sexy" width="600" height="399" class="aligncenter size-full wp-image-94" /></p>
<p>Uvolnění mozkové kapacity pro vyšší úroveň abstrakce je nejdůležitější důvod pro schovávání informací (a psaní tříd a metod s jednoznačným účelem, psaní metod s nízkou cyklomatickou komplexitou, automatizované testy a&#8230;). Koneckonců to je hlavní důvod, proč se neustále pohybujeme k vyšším jazykům (ASM k C k Pythonu) a ne naopak.</p>
<p>P.S.: To není článek proti Pythonu.</p>
]]></content:encoded>
			<wfw:commentRss>http://blog.webtrh.cz/information-hiding/feed</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>Javascript a CSS končí?</title>
		<link>http://blog.webtrh.cz/javascript-a-css-konci</link>
		<comments>http://blog.webtrh.cz/javascript-a-css-konci#comments</comments>
		<pubDate>Thu, 14 Apr 2011 10:31:13 +0000</pubDate>
		<dc:creator>Martin</dc:creator>
				<category><![CDATA[Nezařazené]]></category>

		<guid isPermaLink="false">http://blog.webtrh.cz/?p=42</guid>
		<description><![CDATA[Co mají společného Javascript a CSS? Každý, kdo s nimi delší dobu pracuje, dokáže vyjmenovat, jak by se oba jazyky daly vylepšit. Někteří vzali vylepšování do svých rukou, a tak vznikl CoffeeScript a Sass. CoffeeScript CoffeeScript je jazyk inspirovaný Ruby &#8230; <a href="http://blog.webtrh.cz/javascript-a-css-konci">Celý příspěvek <span class="meta-nav">&#8594;</span></a>]]></description>
			<content:encoded><![CDATA[<p>Co mají společného Javascript a CSS? Každý, kdo s nimi delší dobu pracuje, dokáže vyjmenovat, jak by se oba jazyky daly vylepšit. Někteří vzali vylepšování do svých rukou, a tak vznikl CoffeeScript a Sass.</p>
<p><strong>CoffeeScript</strong><br />
<a href="http://jashkenas.github.com/coffee-script/">CoffeeScript</a> je jazyk inspirovaný Ruby a Pythonem, odstraňuje nedostatky JS a přidává některé užitečné nové funkce. Namátkou<br />
<a href="http://jashkenas.github.com/coffee-script/#loops">Comprehensions</a></p>
<pre>countdown = (num for num in [10..1])</pre>
<p><a href="http://jashkenas.github.com/coffee-script/#operators">Nové operátory <em>is, isnt, not, and, or,</em> existenční operátor <em>?</em></a></p>
<pre>if band?
    volume = 10 if band isnt SpinalTap</pre>
<p>Pohodlnější práci s třídami a objekty, bezpečnější deklaraci proměnných (globální proměnné už nelze deklarovat omylem, zapomenutím <em>var</em>, ale pouze explicitně) atd.</p>
<p>CoffeeScript se překládá přímo do JS.</p>
<p><strong>Sass</strong><br />
<a href="http://sass-lang.com/">Sass</a> je nadmnožina CSS, která z čistě deklarativního CSS dělá procedurální jazyk s proměnnými a funkcemi. Umožňuje třeba definovat základní hodnoty do proměnných a provádět s nimi psí kusy pomocí <a href="http://sass-lang.com/docs/yardoc/Sass/Script/Functions.html">specializovaných funkcí</a></p>
<pre><strong>$margin: 16px;
$blue: #3bbfce;</strong>
.border {
  padding: <strong>$margin / 2;</strong>
  margin: $margin / 2;
  border-color: <strong>darken($blue, 9%);</strong>
}</pre>
<p>Vytvořit základní, opakující se deklarace a měnit je</p>
<pre>@mixin <strong>left($dist)</strong> {
  float: left;
  margin-left: $dist;
}

#data {
  <strong>@include left(10px);</strong>
}</pre>
<p>Nebo dědit vlastnosti od dřív definovaných selektorů</p>
<pre><strong>.error</strong> {
  border: 1px #f00;
  background: #fdd;
}
.badError {
  <strong>@extend .error;</strong>
  border-width: 3px;
}</pre>
<p>Sass se překládá do CSS.</p>
<p>Nepřehání ale zprávy o smrti JS a CSS?<br />
Rails, jeden z významných frameworků pro tvorbu webových aplikací, se <a href="http://www.rubyinside.com/rails-3-1-adopts-coffeescript-jquery-sass-and-controversy-4669.html">rozhodl ve verzi 3.1 přejít</a> právě na CoffeeScript a Sass. Tím jsou obě nadstavby definitivně legitimní součástí vývojářských nástrojů.</p>
<p>Nahrazení JS a CSS začíná.</p>
]]></content:encoded>
			<wfw:commentRss>http://blog.webtrh.cz/javascript-a-css-konci/feed</wfw:commentRss>
		<slash:comments>4</slash:comments>
		</item>
		<item>
		<title>Code Complete &#8211; Ultimátní kniha o správném kódu</title>
		<link>http://blog.webtrh.cz/code-complete</link>
		<comments>http://blog.webtrh.cz/code-complete#comments</comments>
		<pubDate>Fri, 01 Apr 2011 10:29:56 +0000</pubDate>
		<dc:creator>Martin</dc:creator>
				<category><![CDATA[Nezařazené]]></category>

		<guid isPermaLink="false">http://blog.webtrh.cz/?p=29</guid>
		<description><![CDATA[Dočetl jsem Code Complete od Steva McConnella. Je to nejužitečnější kniha o programování, kterou jsem dosud četl. Na necelých devíti stech stránkách se McConnell věnuje třem velkým tématům &#8211; řízení softwarového projektu (vytvoření požadavků, design, konstrukce, management), psychologii programování a &#8230; <a href="http://blog.webtrh.cz/code-complete">Celý příspěvek <span class="meta-nav">&#8594;</span></a>]]></description>
			<content:encoded><![CDATA[<p>Dočetl jsem <a href="http://www.amazon.com/Code-Complete-Practical-Handbook-Construction/dp/0735619670/">Code Complete</a> od Steva McConnella. Je to nejužitečnější kniha o programování, kterou jsem dosud četl.</p>
<p>Na necelých devíti stech stránkách se McConnell věnuje třem velkým tématům &#8211; řízení softwarového projektu (vytvoření požadavků, design, konstrukce, management), psychologii programování a především psaní kódu, který je čitelný, spravovatelný a snižuje složitost programu.</p>
<p><strong>The first goal of programming is managing complexity</strong><br />
Tuto větu čtete mnohokrát a McConnell zkoumá krocení složitosti z mnoha úhlů &#8211; jak správně navrhovat třídy, jejich rozhraní a implementaci, jak rozvrhnout kód do funkcí, jak používat a nazývat proměnné (4 úžasné kapitoly), jak organizovat příkazy a deklarace a používat řídící struktury (6 kapitol) a k čemu používat komentáře v kódu.</p>
<p>Věnuje se i vyšším, nekódovacím procesům, které ovlivňují konečnou kvalitu programu &#8211; programování v páru, revizím kódu, testování, debuggování, refaktorování, ladění a integraci.</p>
<p>Všechna témata kulminují v posledních třech kapitolách. <em>Self-Documenting Code</em> shrnuje mikrotechniky důležité pro psaní čitelného a samovysvětlujícího kódu. <em>Personal Character</em> mluví o vlastnostech a návycích důležitých pro to, aby se programátor neustále zlepšoval, a <em>Themes in Software Craftsmanship</em> je shrnutí těch nejdůležitějších principů z nadhledu.</p>
<p><strong>Bohatá bibliografie</strong><br />
Nemůžu opomenout bohatou bibliografii, která je uvedená v každé podkapitole. Nejde o suchý výčet knih podle klíčových slov, ale o komentovaný výběr toho nejpřínosnějšího, co si o daném tématu můžete přečíst (do 2004, roku vydání druhé edice).</p>
<p>Na konci knihy McConnell shrnuje nejdůležitější knihy, které by podle něj měl přečíst každý programátor.</p>
<p><strong>V češtině jako Dokonalý kód</strong><br />
Code Complete vyšel v češtině jako <a href="http://knihy.cpress.cz/knihy/pocitacova-literatura/programovani/dokonaly-kod-umeni-programovani-a-techniky-tvorby-software/listovani/">Dokonalý kód</a>. Podle zběžného zhlédnutí ukázek a porovnání s originálem se mi překlad zdá trochu těžkopádný, občas zavádějící a nepříliš dobře vysázený. Bubliny v bočním sloupci, které v originále upozorňují na důležitá místa v ukázkách kódu, český vydavatel převedl do inline komentářů, což jednoznačně snížilo přehlednost.</p>
<p>Některé věty jsou v češtině méně srozumitelné či nepřesné:</p>
<blockquote><p>Using > instead of >= or < instead of <= is analogous to making an off-by-one error in accessing an array or computing a loop index.</p></blockquote>
<blockquote><p>Operátor > místo operátoru >=, či operátor < místo operátoru <= je stejnou chybou jako nepozorné překročení mezí pole při opakovaném zvyšování hodnoty cyklu.</p></blockquote>
<p>Některé jsou přeložené chybně.</p>
<blockquote><p>This ordering convention conflicts <strong>with the C-library convention</strong> of putting the modified parameter first.</p></blockquote>
<blockquote><p>Tato konvence uspořádání parametrů je v rozporu <strong>s konvencí</strong> pro upravované parametry.</p></blockquote>
<p>A narazil jsem i na větu, která z originálu vypadla úplně:</p>
<blockquote><p>Put the case you normally expect to process first. <strong>This is in line with the general principle of putting code that results from a decision as close as possible to the decision.</strong> Here&#8217;s a code example&#8230;</p></blockquote>
<blockquote><p>Nejprve vždy uvádějte příkazy, které zpracovávají běžné alternativy. Následující ukázka&#8230;</p></blockquote>
<p>Pokud volíte mezi překladem a originálem, sáhněte jednoznačně po originálu. Kniha je opravdu čtivá a srozumitelná.<br />
Pokud ale volíte mezi překladem a nepřečtením, sáhněte po překladu.</p>
<p><strong>Pro koho kniha je?</strong><br />
Je kniha i pro pokročilé programátory? Správný návrh rozhraní třídy, pojmenovávání proměnných, používání <em>if</em>, to už mám přece dávno za sebou.</p>
<p>Existuje velká šance, že jste se některými otázkami, o kterých se mluví v Code Complete, nezabývali explicitně. Buď jste přejali postupy a konvence z nějakého velkého projektu, nebo si potichu nacházeli vlastní. Některá z vašich rozhodnutí mohla být podvědomá. Code Complete ty otázky zdůrazní a umožní vám si na ně znovu, tentokrát vědomě odpovědět.</p>
<p>McConnell každopádně počítá i s pokročilými programátory a pravidelně upozorňuje na podkapitoly, které je nejspíš nebudou zajímat a na podkapitoly, které pro ně budou užitečné.</p>
<p>Já knihu přečetl od začátku do konce a během čtení jsem doslova cítil, jak se můj kód a mé uvažování o programech zlepšuje.</p>
<p>Rozhodně <a href="http://www.amazon.com/Code-Complete-Practical-Handbook-Construction/dp/0735619670/">Code Complete</a> doporučuju programátorům všech úrovní, ale kvůli kapitolám a bibliografii o vedení projektu, psychologii programování a o vlivu pracovního prostředí na výkonnost i všem projektovým a softwarovým manažerům a majitelům firem, které programátory zaměstnávají.</p>
]]></content:encoded>
			<wfw:commentRss>http://blog.webtrh.cz/code-complete/feed</wfw:commentRss>
		<slash:comments>3</slash:comments>
		</item>
		<item>
		<title>Pseudonymní příhozy &#8211; kompromis mezi soukromím a transparentností?</title>
		<link>http://blog.webtrh.cz/pseudonymni-prihozy</link>
		<comments>http://blog.webtrh.cz/pseudonymni-prihozy#comments</comments>
		<pubDate>Thu, 24 Feb 2011 12:53:59 +0000</pubDate>
		<dc:creator>Martin</dc:creator>
				<category><![CDATA[Nezařazené]]></category>

		<guid isPermaLink="false">http://blog.webtrh.cz/?p=14</guid>
		<description><![CDATA[U příhozů v aukcích řešíme od začátku spor mezi transparentností a soukromím. Na jednu stranu účastníci aukce mají právo vědět, kdo stojí proti nim. Nemusí nutně znát jeho jméno, ale měli by vidět, jak dlouho je na Webtrhu a jaké &#8230; <a href="http://blog.webtrh.cz/pseudonymni-prihozy">Celý příspěvek <span class="meta-nav">&#8594;</span></a>]]></description>
			<content:encoded><![CDATA[<p>U příhozů v aukcích řešíme od začátku spor mezi transparentností a soukromím. Na jednu stranu účastníci aukce mají právo vědět, kdo stojí proti nim. Nemusí nutně znát jeho jméno, ale měli by vidět, jak dlouho je na Webtrhu a jaké má hodnocení. Na druhou stranu by nemělo být možné jedním dotazem v Googlu najít všechny obchody, kterých se účastnil XY.</p>
<p>Vyřešili jsme to zavedením volitelných anonymních příhozů, při kterých je identita přihazujícího úplně skrytá.</p>
<p>Uvažujeme ale o lepším řešení &#8211; pseudonymních příhozech. Jméno přihazujícího by bylo schované před vyhledávači, třeba bychom zobrazovali jen první a poslední písmeno. A vedle pseudonymu obchodní hodnocení a datum registrace. S trochou práce by samozřejmě bylo možné identitu odhalit, ale už by nešlo zkoumat aktivitu křížově.</p>
<p>Učinili bychom tak zadost soukromí přihazujících i transparentnosti aukce.</p>
]]></content:encoded>
			<wfw:commentRss>http://blog.webtrh.cz/pseudonymni-prihozy/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Bodování příspěvků</title>
		<link>http://blog.webtrh.cz/bodovani-prispevku</link>
		<comments>http://blog.webtrh.cz/bodovani-prispevku#comments</comments>
		<pubDate>Sun, 20 Feb 2011 20:32:07 +0000</pubDate>
		<dc:creator>Martin</dc:creator>
				<category><![CDATA[Nezařazené]]></category>

		<guid isPermaLink="false">http://blog.webtrh.cz/?p=12</guid>
		<description><![CDATA[Včera jsem potichu na živé verzi spustil bodování příspěvků. Zatím nezvýrazňuje příspěvky, ani neposkytuje hodnocení diskusí (ačkoliv to se v pozadí už počítá). Slouží to v této chvíli pouze jako anonymní pochvalné zamručení, ale lidé to už dnes začali zlehka &#8230; <a href="http://blog.webtrh.cz/bodovani-prispevku">Celý příspěvek <span class="meta-nav">&#8594;</span></a>]]></description>
			<content:encoded><![CDATA[<p>Včera jsem potichu na živé verzi spustil bodování příspěvků. Zatím nezvýrazňuje příspěvky, ani neposkytuje hodnocení diskusí (ačkoliv to se v pozadí už počítá). Slouží to v této chvíli pouze jako anonymní pochvalné zamručení, ale lidé to už dnes začali zlehka využívat.</p>
<p>Za čtyři roky Webtrhu si lidé poslali jen necelých 5 000 hodnocení. Uvidíme, jak se to změní s novým systémem bodování.</p>
]]></content:encoded>
			<wfw:commentRss>http://blog.webtrh.cz/bodovani-prispevku/feed</wfw:commentRss>
		<slash:comments>3</slash:comments>
		</item>
	</channel>
</rss>

