tag:blogger.com,1999:blog-34087455070912324222024-03-05T20:54:38.210+01:00Robert DreslerVývoj software není jenom o kódování ...Robert Dreslerhttp://www.blogger.com/profile/16401744220939465418noreply@blogger.comBlogger48125tag:blogger.com,1999:blog-3408745507091232422.post-62700170822907962592022-01-30T18:43:00.001+01:002022-01-30T18:51:38.283+01:00Starý junior, mladý senior<div class="separator" style="clear: both;"><a href="https://blogger.googleusercontent.com/img/a/AVvXsEgQnbZDKSU6y816pmVml9VS-2uaCM-3Ck9n4e-wGyvqfMVAR85VQgxWu-fIUYoFbVC9UIeLmDRC9iyauEo9oYo_yZrItV71GTPcm6z7ocTjE2VcC4LbTbbTuKGRHsuGktpgRyJECvI0d8ztEapP0oqWpA_SZzC5H1744u5tD842WRHUHfkhk-LO4y3qMw" style="display: block; padding: 1em 0; text-align: center; "><img title="Image by https://www.amazingviralnews.com/" border="0" data-original-height="289" data-original-width="516" src="https://blogger.googleusercontent.com/img/a/AVvXsEgQnbZDKSU6y816pmVml9VS-2uaCM-3Ck9n4e-wGyvqfMVAR85VQgxWu-fIUYoFbVC9UIeLmDRC9iyauEo9oYo_yZrItV71GTPcm6z7ocTjE2VcC4LbTbbTuKGRHsuGktpgRyJECvI0d8ztEapP0oqWpA_SZzC5H1744u5tD842WRHUHfkhk-LO4y3qMw"/></a>
</div>
<p><i>Seniorita je pojem z oblasti společenských vztahů. Vyjadřuje nadřazenost osoby nebo skupiny na základě vyššího věku nebo délky zastávání určité pozice. Takže senior je buď člověk staršího věku nebo pracující déle na nějaké pozici. Junior je autonymum.</i>
</p>
<p>Tímto příspěvkem se pokusím odpovědět na tyto komplexní otázky:
</p>
<ul>
<li>Jak je definována "kvalita vývojáře"?</li>
<li>Jak vlastně délka profesní kariéry souvisí s vlastní kvalitou vývojáře?</li>
</ul>
<p>Dlouho jsem přemýšlel nad tím, jak téma uchopit. Nakonec jsem dal dohromady několik vstupů:
</p>
<ul>
<li>moje pozorování kolegů a toho, co se mi na jejich profesním chování líbí,</li>
<li>reakce lidí na můj <a href="#vox_populi">anketní tweet</a>,</li>
<li>seznam znalostí a dovedností, které považuji za důležité.</li>
</ul>
<p>A výstupem se stal <b>Honza</b>.
</p>
<p>Honza je kompendiem zkušeností a profesní efektivity. Je to kombinace mnoha profesních rolí - architekt, analytik, programátor, manažer, projekťák, atd. A také je to někdo, kdo reálně neexistuje. Je to ideál vývojáře, na kterém si zkusíme popsat, co všechno může mít na naši práci pozitivní vliv.
</p>
<p>Honzův profil by nám tedy mohl pomoci s odpovědí na první otázku. Na tu druhou si odpovíme ke konci příspěvku.
</p>
<h3>Honza a práce</h3>
<p>Honza je pracovitý a vytrvalý. To je základ.</p>
<p>Nevyhýbá se úkolům. Samozřejmě chápe, že práce bude vždy více než je dostupného času. Snaží se proto správně pracovat s prioritami. Rozumí, že každá záležitost obnáší investici ve formě času a generuje určitou hodnotu. Nenechá se odlákat od aktuálního prioritního úkolu pouze tím, že se právě objevil méně prioritní ale zato atraktivnější úkol.</p>
<p>Umí dotahovat úkoly ke zdárnému konci. Nenechá se odradit překážkami. Je orientovaný na výsledek. Ne však na úkor kvality. Má soubor profesních zásad, které dodržuje i pod projektovým tlakem. Na druhou stranu ví, kdy je z nich možné a vhodné mírně ustoupit a jaké to bude mít důsledky. Ty je potřeba správně komunikovat.
</p>
<p>Má vybudované návyky, které mu pomáhají dělat práci efektivně. Umí si den rozdělit do delších bloků hluboké práce bez vyrušování. Umí si organizovat inbox a backlog přes všechny své profesní role. Reaguje na pracovní požadavky podle jejich důležitosti. Umí říkat NE.
</p>
<h3>Honza a kolegové</h3>
<p>S Honzou je příjemné pracovat.</p>
<p>Čím komplexnější projekt, tím větší tým a tím důležitější chemie mezi lidmi. Honza si důležitost vztahů uvědomuje. Je empatický. Chápe rozdíly v typologiích osobností. Dokáže být asertivní.</p>
<p>Nezdůrazňuje svoji senioritu v týmu. Respekt si buduje svojí profesionalitou a tím, že respektuje ostatní. Povzbuzuje své kolegy k samostatnosti a k tomu nebát se zkoušet nové věci a hledat optimálnější řešení. Spoluvytváří pozitivní atmosféru, ve které se všem dobře pracuje. Svůj názor se snaží prosadit věcným způsobem.</p>
<p>Honza je pokorný. Nemá ve zvyku neustále hledat problémy pouze u druhých, když se něco nepodaří. Začně tím, že si vyhodnotí svůj podíl na problému jako první. Chápe, že i on dělal, dělá a bude dělat chyby. Nevymlouvá se, když se mu něco nepovede. Vysvětlí okolnosti, které vedly k jeho chybě a upraví své pracovní postupy a chování tak, aby se stejná chyba v budoucnu neopakovala.</p>
<p>Snaží se konfliktům předcházet a pokud už nastanou, tak je zmírňovat. Pokud něco nefunguje, neuchyluje se k osobní kritice kolegů. Je věcný. Nepomlouvá. Snaží se aktivně hledat příčiny problémů a ty pak konstruktivně řešit. Dokáže konstruktivně přijmout zpětnou vazbu na svoji práci. Pokud sám zpětnou vazbu poskytuje, pak nekonfliktním způsobem. Kolegové tak nemají pocit, že jsou kritizováni, ale že jsou podporováni k lepším výsledkům.
</p>
<p>Honza zná základní principy koučinku a umí je v praxi použít. Pomáhá tím kolegům v uvědomění si jejich aktuální profesní situace a toho, kam by se mohli posunout a jakým způsobem. Takto přirozeně tým rozvíjí a pomáhá jeho členy motivovat.</p>
<p>Mluví otevřeně a transparentně. Buduje důvěryhodné prostředí, nemanipuluje s informacemi, poskytuje je všem konzistentním způsobem. Kolegy nezdržuje přílišným tlacháním na poradách.</p>
<h3>Honza jako architekt řešení</h3>
<p>Honza už chápe, že zákazník na začátku projektu často přesně neví co chce. Honzu netrápí, že nemá často přesné zadání. Chápe to jako příležitost pomáhat zákazníkovi už od začátku s hledáním řešení. Co jej občas trápí je, když se po něm chce estimace příliš hrubého zadání. Je si vědom, že taková estimace v ranné fázi projektu je pouze loterie, která se hraje hlavně proto, aby měl zákazník rámcovou představu o nákladnosti projektu. Nesnaží se dodat konkrétní číslo, ale spíše rozpětí optimistického a pesimistického odhadu. Rozloží si problém na menší celky a ty estimuje zvlášť. Umí zákazníkovi vysvětlit rizika takové estimace a obsažené stupně volnosti.</p>
<p>Honza se snaží aktivně porozumět rizikům projektu. Tato rizika srozumitelně popíše, navrhne protiopatření a vykomunikuje je směrem k zákazníkovi. Zkušenost mu velí, že největší rizika vznikají při integraci aplikace s externími systémy a při závislosti na úkolech, které musí zajisti zákazník sám.
</p>
<p>Honza má zkušenosti s agilními projekty i vodopádem. Pracoval v režimu Fix-time-fix-price i Time-&-Material. Dokáže je porovnat z různých perspektiv. Preferuje agilní přistup, ale chápe, že každá metodologie je vhodná pro jiný typ projektu. Chápe, že zadavatel má určitý přístup k řešení projektů, který někdy nelze úplně změnit. Nejdříve si tedy nechá vysvětlit problém, který je potřeba řešit a teprve potom navrhuje typ metodiky. Ne obráceně. Umí vyargumentovat vhodnost jednotlivých přístupů a zohlednit připomínky zákazníka.
</p>
<p>Honza zná principy Scrumu, Kanbanu, extrémního programování i vodopádu. Je si vědom, že málokdy se na projektu jedná o jednu striktní metodiku. Často dochází k hybridnímu modelu s prvky více metodik současně. Umí v takovém prostředí fungovat. Dokáže poznat, kdy to způsobuje problémy a kdy naopak to projektu prospívá. Uvědomuje si, že získávání zpětné vazby na práci týmu od zákazníka je klíčové pro úspěch projektu v každé metodice.
</p>
<h3>Honza jako analytik</h3>
<p>Honza dobře chápe, že za vznikem dobrého softwarového produktu je obvykle symbióza správného technického řešení a pochopení byznysových potřeb. Aktivně se snaží porozumět byznysové doméně. Chápe, že jednoznačný doménový glosář redukující používání synonym je základem plynylé komunikace a snižuje míru neporozumění v rámci projektového týmu.
</p>
<p>Honza umí naslouchat potřebám zákazníka, pomáhat s návrhem řešení a formalizovat požadovanou funkcionalitu ve formě use cases. Rutinně používá UML a kreslí diagramy případů užití, aktivitní diagramy, sekvenční diagramy a další.
</p>
<p>Honza je schopen definovat funkcionální epiky a jejich rozpad na user stories. Nepodceňuje správnou formulaci všech tří hlavních částí story. Rozumí důležitosti formy a obsahu akceptačních kritérií, Definition of Ready a Definition of Done.
</p>
<p>Když je na projektu nějaká velká neznámá nebo vysoce komplexní část, umí si s tím poradit. Nepřeceňuje význam verbální diskuze. Pozná, kdy je lepší přestat mluvit a udělat první krok k řešení problémů. Raději udělá první krok špatným směrem, než dlouho váhat a neudělat žádný. I pozdější uvědomění si nesprávného postupu je progres.
</p>
<p>Honza nepodceňuje důležitost definice nefunkcionálních požadavků. Aktivně se zákazníkem řeší požadavky na zabezpečení, odezvu systému, propustnost, podporované prohlížeče, apod. Je si vědom toho, že právě tyto záležitosti mají často zásadní vliv na architekturu řešení.
</p>
<h3>Honza jako technický vedoucí týmu</h3>
<p>Honza spolu s týmem nastavuje pravidla pro psaní kódu. Společně integrují nástroje pro statickou a dynamickou analýzu. Sdílejí si týmové šablony a code snippety. Snaží se zajistit rozumnou míru standardizace, která práci celého týmu zefektivňuje.
</p>
<p>Honza chápe důležitost automatizace CI a CD procesů. Proto trvá na jejich správném nastavení již od začátku vývoje.</p>
<p>Honzovi je jasné, že správně prováděná code review jsou velkým přínosem pro kvalitu výstupu. Zároveň dbá na to, aby způsob komunikace v rámci review byl profesionální a konstruktivní. Chce, aby to byl proces učení a společného hledání lepšího řešení.
</p>
<p>Honza si je vědom, že každý softwarový projekt je postupně zatížen technickým dluhem, se kterým se musí pracovat. Zná postupy jak redukovat míru jeho vzniku už ve fázi návrhu. V týmu aktivně používají Boyscout-rule. Zároveň však dokáže poznat, kdy je už další umořování technického dluhu ekonomicky neefektivní.</p>
<p>Komunikuje technické záležitosti srozumitelným způsobem produkťákům a mecenášům projektu tak, aby zajistil adekvátně robustní řešení. Větší refaktoring domluví jako technickou user story naplánovanou s vědomím zákazníka v souvislosti s funkcionální změnou v souvisejím kódu. Dělat refaktoring bez motivace rozšíření stávající funkcionality nebo optimalizace výkonu nepovažuje za opodstaněné.
</p>
<p>Honza nabádá kolegy, aby přicházeli s nápady na vhodné nástroje a knihovny, které by práci na projektu vylepšily. Nejdříve si však jejich použití odprototypují a posoudí jejich přínos. Je přiměřeně konzervativní v použití nových věcí. Mnohokrát již dříve zjistil, že vhodnost technologie se nedá posoudit hned, ale spíše později při aplikaci na komplexnější záležitosti. Použití takové neprověřené technologie považuje za riziko a tak s ním i nakládá.
</p>
<h3>Honza jako programátor</h3>
<p>Anatomii vývojového cyklu specifikace-analýza-návrh-implementace-verifikace má Honza stále v podvědomí. Snaží se tyto fáze ve svých postupech logicky oddělit.</p>
<p>Když začíná pracovat na novém úkolu, začne analýzou problému. Pokud problém obsahuje neurčitost, kterou potřebuje vyjasnit, neváhá sáhnout k prototypování. Udělá rychlý prototyp, který mu pomůže pochopit problém a ukáže možné cesty k řešení problému. Prototyp pak zahodí a nepodléhá lákadlu jeho použítí přímo v produkčním kódu.
</p>
<p>Součástí Honzovy analýzy je obvykle také rozpad problému do menších celků. Tyto menší celky jsou pak lépe uchopitelné. Veškeré nejasné a problematické části zadání strukturovaně sepíše a prodiskutuje s autorem požadavku.
</p>
<p>Ve fázi návrhu si rád pomůže nakreslením některého z UML diagramů. Pro statický pohled na řešení používá komponentový diagram a diagram tříd. Pro dynamický pohled aktivitní, sekvenční nebo stavový.
</p>
<p>Někdy mu také pomůže TDD přístup. Jednotkovými testy postupně definuje rozhraní komponenty a iterativně její sémantiku. Snaží se o konzistentní a dostatečně samopopisný názvy testů, které poslouží jako aktuální dokumentace ke komponentám. Ze složitosti zápisu jednotkových testů dostává okamžitě zpětnou vazbu na návrh komponent a jejich složitost.
</p>
<p>Honza si bez jednotkových testů nedokáže vývoj představit. Není však radikálním zastáncem 100% pokrytí kódu u komponent, u kterých je přínos jednotkových testů velmi malý oproti nákladům na jejich vytvoření a údržbu.
</p>
<p>Při návrhu komponent používá Honza kombinaci různých best practices a návrhových vzorů. Základem jsou pro něho SOLID principy. Bez použití IoC kontejneru a Dependency Injection si už nedovede své projekty ani představit. Má rád volné vazby mezi komponentami, nízká čísla u metrik závislostí a vysokou soudržnost. Díky tomu může psát testy efektivním způsobem.
</p>
<p>Pro Honzu bylo přečtení knížky Clean Code důležitým profesním milníkem. Začal přemýšlet nad svým kódem jinak. Zaměřuje se na dobré pojmenování, zkracuje metody, snižuje cyklomatickou složitost, redukuje parametry, více přemýšlí nad ošetřením možných chybových stavů. Obecně se více dívá na kód z pohledu čtenáře než autora. Zásadní důraz klade na dobrou čitelnost a samodokumentovatelnost kódu. Ovládá nejpoužívanější techniky refaktoringu právě pro dosažení lepší struktury a udržovatelnosti kódu.
</p>
<p>Integračními testy si ověří funkčnosti přes celý aplikační stack.
</p>
<p>Otázky výkonu Honza řeší již při návrhu architektury. Rozumí také výkonostním aspektům frameworkových komponent a vlastního jazyka. Nenechá se však vlákat do pasti dopředné optimalizace při psaní komponent. Tu provádí až poté, co má nejdříve funkční řešení.
</p>
<p>Honza se snaží své hlavní softwarové nástroje ovládat pouze z klávesnice bez nutnosti použití myš. Aktivně se učí klávesové zkratky. Píše bez překlepů. Psaní na klávesnici pravidelně trénuje.
</p>
<h3>Honzovy znalosti jazyků a technologií</h3>
<p>Ve svém hlavním programovacím jazyce se cítí velmi komfortně. Na druhou stranu si uvědomuje, že získat hlubokou expertízu v použití hlavních knihoven platformy je běh na dlouhou trať. Aktivně proto hledá možnosti, jak si zvé znalosti rozšířit. Čte si blogy, porovnává různá řešení stejného problému na Stackoverflow, prototypuje alternativy, diskutuje s kolegy.
</p>
<p>Honza má rozsáhlé teoretické znalosti v oblasti softwarového inženýrství. Díky nim dokáže rychleji najít optimálnější řešení problému. Ví co hledá a umí si dát věci do souvislostí.
</p>
<p>Má zkušenosti s jazyky a technologiemi napříč celým stackem. Dokáže napsat aplikace běžící na serveru, v prohlížeči i na mobilních zařízeních. Díky takto širokému záběru chápe souvislosti a umí navrhnout správně komunikační rozhranní. Rozumí protokolům REST, GraphQL, gRTC i SOAP.
</p>
<p>Honza zná principy hlavních cloudových platforem. Umí navrhnout a nakonfigurovat ideální mix cloudových služeb podle potřeb daného projektu. Rozumí Dockeru a Kubernetes.
</p>
<h2>Jak dlouho je už Honza v oboru?</h2>
<p>A odpověď na druhou otázku je ... <i>Nevím.</i>
</p>
<p>Dle mého názoru se délka kariéry v IT často přeceňuje. Já sám znám několik relativně mladých vývojářů, kteří mají k Honzovi blíže než jiní, kteří ještě programovali v Turbo Pascalu. Ale rozhodně z toho nemůžeme dělat pravidlo.
</p>
<p>Co můžeme z tak komplexního Honzova profilu tedy vyvodit? Dostat se na vysokou úroveň mnoha dovedností vyžaduje spoustu času stráveného praktikováním. To bezesporu. U některých vlastností jsou navíc nutné i životní zkušenosti, které formují především sociální inteligenci.</p>
<p>Důležitou složkou naší osobnosti jsou charakterově volní vlastnosti. Spolehlivost, pracovitost, zásadovost, ... Jejich správné nastavení má zřejmě zásadní vliv na rychlost profesního růstu.</p>
<p>Velký dopad má také to, v jakém prostředí a týmu se vývojář vyvíjel. Při dobrém vedení se může začínající perspektivní vývojář během krátkého období hodně posunout. Proto je zřejmě výhodné, aby byli mladí ve více flexibilním prostředí s variabilnějšími projekty. Samozřejmě za asistence zkušených kolegů.
</p>
<h2>Zkusme být jako Honza ...</h2>
<p>... ale nestresujme se z toho, že takoví nejsme. Pracujme na sobě. Každý úkol je příležitostí se něco nového naučit, zlepšit se, zkusit jiný postup. Odměnou nám bude dobře odvedená práce a spokojenost. A o to přeci jde.
</p>
<h2 id="vox_populi">Vox populi</h2>
<p>Tady si můžete přečíst, co si o tématu myslí kolegové z Twitteru. Děkuji všem za reakce.
</p>
<blockquote class="twitter-tweet"><p lang="cs" dir="ltr">Chystám blogpost "Starý junior, mladý senior". Jaké dovednosti / charakteristiky podle vás nejvíce odlišují skutečně seniorního vývojáře od neseniorního? Díky za názor nebo RT.</p>— Robert Dresler (@rdresler) <a href="https://twitter.com/rdresler/status/1484777493185933315?ref_src=twsrc%5Etfw">January 22, 2022</a></blockquote> <script async src="https://platform.twitter.com/widgets.js" charset="utf-8"></script>
Robert Dreslerhttp://www.blogger.com/profile/16401744220939465418noreply@blogger.com1tag:blogger.com,1999:blog-3408745507091232422.post-20148081580984813622016-10-24T18:13:00.001+02:002016-10-24T18:28:23.401+02:00Jednoduchá složitost nebo složitá jednoduchost<div class="separator" style="clear: both; text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhA6TedXB0NoRYYkC_C8sAbYDdRzSSk7pR9uzRwd-WzWo7__w1vbX74kxUCoZalmP3iTu3J29A_yEr-iHGMfBm8mdcn1xUeJUgtkknJVthInmlWYLaZfOQkBkvmKDufe41U_MukCXh8818G/s1600/tangled_electricity.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhA6TedXB0NoRYYkC_C8sAbYDdRzSSk7pR9uzRwd-WzWo7__w1vbX74kxUCoZalmP3iTu3J29A_yEr-iHGMfBm8mdcn1xUeJUgtkknJVthInmlWYLaZfOQkBkvmKDufe41U_MukCXh8818G/s1600/tangled_electricity.png" /></a></div>
<p>Známe to všichni. Kód, který jsme dříve napsali, byl dobře čitelný a lehce upravitelný. Ten samý kód dneska? Nakynuté třídy, dlouhé metody, vysoká komplexita a zvyšující se náklady na požadované změny.
</p>
<p>Všude slýcháme, že musíme psát kód jednoduchý, dobře čitelný, s nízkou komplexitou. Dobře, ale co to vlastně v praxi znamená? Zjistil jsem, že my vývojáři si pod "jednoduchostí kódu" často představujeme dost rozdílné věci.
</p>
<p>Pojďme se společně podívat na několik řešení stejného problému a přemýšlet nad tím, co si vlastně pod "jednoduchým kódem" představujeme.
</p>
<h2>Řešíme "problém života"</h2>
<p>Jako ukázkový problém nám poslouží hra <a href="https://en.wikipedia.org/wiki/Conway%27s_Game_of_Life">Game of Life</a>, kterou zpopularizovaly akce typu Coderetreat. Zrovna minulou sobotu byl Global Day of Coderetreat 2016, takže pro mnohé účastníky čerstvá zkušenost.
</p>
<p>Hra definuje několik základních pravidel pro výpočet stavu buňky v příští generaci:
<ul>
<li>Any live cell with fewer than two live neighbours dies, as if caused by under-population. (<i>Under-population rule</i>)</li>
<li>Any live cell with two or three live neighbours lives on to the next generation. (<i>Survival rule</i>)</li>
<li>Any live cell with more than three live neighbours dies, as if by over-population. (<i>Over-population rule</i>)</li>
<li>Any dead cell with exactly three live neighbours becomes a live cell, as if by reproduction. (<i>Reproduction rule</i>)</li>
</ul>
</p>
<p>Výpočet je tedy funkcí aktuálního stavu buňky a počtu jejich živých sousedů. Pravidla nám trochu zatajují situace (Dead,x), kde x in {0,1,2,4,5,6,7,8}. U těch se předpokládá příští stav Dead.
Bude pro nás srozumitelnější, když si pro tyto případy zavedeme další "defaultní" pravidlo <i>No-reproduction rule</i>.
</p>
<p>Kód je sice v C#, ale to by pro vývojáře ze spřátelených platforem neměl být žádný problém. Jde tady přeci o společné principy čitelnosti, komplexity a OOP.
</p>
<h2>Testy až na prvním místě</h2>
<p>Jak už to u Test-First přístupu bývá, testy nám pomohou lépe pochopit problém a pokrýt celou množinu možných situací.
Tento článek ale není o TDD přístupu ani o návrhu struktury testovacích případů. Dovolím si proto zjednodušený zápis finální množiny testů do jednoho parametrického jednotkového testu:
</p>
<p>
<pre style="font-family:Consolas;font-size:13;color:black;background:white;"><span style="color:blue;">public</span> <span style="color:blue;">class</span> <span style="color:#2b91af;">NextGenerationStateCalculatorTests</span>
{
[<span style="color:#2b91af;">TestCase</span>(<span style="color:#2b91af;">CellState</span>.Live, 0, <span style="color:#2b91af;">CellState</span>.Dead, TestName = <span style="color:#a31515;">"Under-population rule: (Live,0) => Dead"</span>)]
[<span style="color:#2b91af;">TestCase</span>(<span style="color:#2b91af;">CellState</span>.Live, 1, <span style="color:#2b91af;">CellState</span>.Dead, TestName = <span style="color:#a31515;">"Under-population rule: (Live,1) => Dead"</span>)]
[<span style="color:#2b91af;">TestCase</span>(<span style="color:#2b91af;">CellState</span>.Live, 2, <span style="color:#2b91af;">CellState</span>.Live, TestName = <span style="color:#a31515;">"Survival rule: (Live,2) => Live"</span>)]
[<span style="color:#2b91af;">TestCase</span>(<span style="color:#2b91af;">CellState</span>.Live, 3, <span style="color:#2b91af;">CellState</span>.Live, TestName = <span style="color:#a31515;">"Survival rule: (Live,3) => Live"</span>)]
[<span style="color:#2b91af;">TestCase</span>(<span style="color:#2b91af;">CellState</span>.Live, 4, <span style="color:#2b91af;">CellState</span>.Dead, TestName = <span style="color:#a31515;">"Over-population rule: (Live,4) => Dead"</span>)]
[<span style="color:#2b91af;">TestCase</span>(<span style="color:#2b91af;">CellState</span>.Live, 5, <span style="color:#2b91af;">CellState</span>.Dead, TestName = <span style="color:#a31515;">"Over-population rule: (Live,5) => Dead"</span>)]
[<span style="color:#2b91af;">TestCase</span>(<span style="color:#2b91af;">CellState</span>.Live, 6, <span style="color:#2b91af;">CellState</span>.Dead, TestName = <span style="color:#a31515;">"Over-population rule: (Live,6) => Dead"</span>)]
[<span style="color:#2b91af;">TestCase</span>(<span style="color:#2b91af;">CellState</span>.Live, 7, <span style="color:#2b91af;">CellState</span>.Dead, TestName = <span style="color:#a31515;">"Over-population rule: (Live,7) => Dead"</span>)]
[<span style="color:#2b91af;">TestCase</span>(<span style="color:#2b91af;">CellState</span>.Live, 8, <span style="color:#2b91af;">CellState</span>.Dead, TestName = <span style="color:#a31515;">"Over-population rule: (Live,8) => Dead"</span>)]
[<span style="color:#2b91af;">TestCase</span>(<span style="color:#2b91af;">CellState</span>.Dead, 3, <span style="color:#2b91af;">CellState</span>.Live, TestName = <span style="color:#a31515;">"Reproduction rule: (Dead,3) => Live"</span>)]
[<span style="color:#2b91af;">TestCase</span>(<span style="color:#2b91af;">CellState</span>.Dead, 0, <span style="color:#2b91af;">CellState</span>.Dead, TestName = <span style="color:#a31515;">"No-reproduction rule: (Dead,0) => Dead"</span>)]
[<span style="color:#2b91af;">TestCase</span>(<span style="color:#2b91af;">CellState</span>.Dead, 1, <span style="color:#2b91af;">CellState</span>.Dead, TestName = <span style="color:#a31515;">"No-reproduction rule: (Dead,1) => Dead"</span>)]
[<span style="color:#2b91af;">TestCase</span>(<span style="color:#2b91af;">CellState</span>.Dead, 2, <span style="color:#2b91af;">CellState</span>.Dead, TestName = <span style="color:#a31515;">"No-reproduction rule: (Dead,2) => Dead"</span>)]
[<span style="color:#2b91af;">TestCase</span>(<span style="color:#2b91af;">CellState</span>.Dead, 4, <span style="color:#2b91af;">CellState</span>.Dead, TestName = <span style="color:#a31515;">"No-reproduction rule: (Dead,4) => Dead"</span>)]
[<span style="color:#2b91af;">TestCase</span>(<span style="color:#2b91af;">CellState</span>.Dead, 5, <span style="color:#2b91af;">CellState</span>.Dead, TestName = <span style="color:#a31515;">"No-reproduction rule: (Dead,5) => Dead"</span>)]
[<span style="color:#2b91af;">TestCase</span>(<span style="color:#2b91af;">CellState</span>.Dead, 6, <span style="color:#2b91af;">CellState</span>.Dead, TestName = <span style="color:#a31515;">"No-reproduction rule: (Dead,6) => Dead"</span>)]
[<span style="color:#2b91af;">TestCase</span>(<span style="color:#2b91af;">CellState</span>.Dead, 7, <span style="color:#2b91af;">CellState</span>.Dead, TestName = <span style="color:#a31515;">"No-reproduction rule: (Dead,7) => Dead"</span>)]
[<span style="color:#2b91af;">TestCase</span>(<span style="color:#2b91af;">CellState</span>.Dead, 8, <span style="color:#2b91af;">CellState</span>.Dead, TestName = <span style="color:#a31515;">"No-reproduction rule: (Dead,8) => Dead"</span>)]
<span style="color:blue;">public</span> <span style="color:blue;">void</span> Calculate__For_Given_CellState_And_Neighbours__Should_Return_Expected_CellState(<span style="color:#2b91af;">CellState</span> cellState, <span style="color:blue;">int</span> numberOfLiveNeighbours, <span style="color:#2b91af;">CellState</span> expectedNextGenerationCellState)
{
<span style="color:blue;">var</span> nextGenerationCellState = <span style="color:blue;">new</span> <span style="color:#2b91af;">NextGenerationStateCalculator</span>().Calculate(cellState, numberOfLiveNeighbours);
<span style="color:#2b91af;">Assert</span>.AreEqual(expectedNextGenerationCellState, nextGenerationCellState);
}
}
<span style="color:blue;">public</span> <span style="color:blue;">enum</span> <span style="color:#2b91af;">CellState</span>
{
Live,
Dead
}</pre>
</p>
<p>
Ve výsledku tedy máme celkem 2 [součastný stav buňky - Live, Dead] x 9 [počet sousedů 0 .. 8] = 18 testů.
Mohli bychom případně udělat rozpad struktury testů podle jednotlivých pravidel. Mohli bychom vylepšit pojmenování. A další. Tím se ale nechci zdržovat. Pojďme řešit implementaci.
</p>
<h2>A. První verze - ta "nejrychlejší"</h2>
<p>
Už si nepamatuju, jak jsem na svém prvním Coderetreatu pravidla implementoval já. Často ale vidím, že programátoři napíšou něco takového:
</p>
<p>
<pre style="font-family:Consolas;font-size:13;color:black;background:white;"><span style="color:blue;">public</span> <span style="color:blue;">class</span> <span style="color:#2b91af;">NextGenerationStateCalculatorA</span>
{
<span style="color:blue;">public</span> <span style="color:#2b91af;">CellState</span> Calculate(<span style="color:#2b91af;">CellState</span> cellState, <span style="color:blue;">int</span> numberOfLiveNeighbours)
{
<span style="color:blue;">if</span> (cellState == <span style="color:#2b91af;">CellState</span>.Live && (numberOfLiveNeighbours == 2 || numberOfLiveNeighbours == 3)
|| (cellState == <span style="color:#2b91af;">CellState</span>.Dead && numberOfLiveNeighbours == 3)) <span style="color:blue;">return</span> <span style="color:#2b91af;">CellState</span>.Live;
<span style="color:blue;">return</span> <span style="color:#2b91af;">CellState</span>.Dead;
}
}</pre>
</p>
<p>
Je to výsledek přístupu "Žij nebo Zemři". Náš pohled na problém je omezen na to, že stačí určit, kdy bude buňka v příští generaci Live. Pro všechny ostatní případy je Dead.
</p>
<p>
Problémem tohoto přístupu je ignorování narůstající složitosti podmínky pro Live. Případné další pravidlo by při tomto přístupu podmínku ještě více znepřehlednilo.
Implementace podmínky také nenese žádnou informaci o tom, jaká pravidla zahrnuje. Není zde žádné mapování kódu na požadavky.
Cyklomatická složitost (<a href="https://en.wikipedia.org/wiki/Cyclomatic_complexity">Cyclomatic Complexity</a>) této implementace je 6. Takže docela dost.
</p>
<p>
Kód je relativně krátký, ale je snadné jej pochopit a rozšířit? Zkusíme vylepšit expresivitu kódu ...
</p>
<h2>B. Pomůžeme si pojmenováním proměnných</h2>
<p>
<pre style="font-family:Consolas;font-size:13;color:black;background:white;"><span style="color:blue;">public</span> <span style="color:blue;">class</span> <span style="color:#2b91af;">NextGenerationStateCalculatorB</span>
{
<span style="color:blue;">public</span> <span style="color:#2b91af;">CellState</span> Calculate(<span style="color:#2b91af;">CellState</span> cellState, <span style="color:blue;">int</span> numberOfLiveNeighbours)
{
<span style="color:blue;">var</span> useSurvivalRule = cellState == <span style="color:#2b91af;">CellState</span>.Live && (numberOfLiveNeighbours == 2 || numberOfLiveNeighbours == 3);
<span style="color:blue;">var</span> useReproductionRule = cellState == <span style="color:#2b91af;">CellState</span>.Dead && numberOfLiveNeighbours == 3;
<span style="color:blue;">return</span> useSurvivalRule || useReproductionRule ? <span style="color:#2b91af;">CellState</span>.Live : <span style="color:#2b91af;">CellState</span>.Dead;
}
}</pre>
</p>
<p>
V kódu se nám už objevuje terminologie prvních pravidel. Konkrétně Survival a Reproduction. Zavedené lokální proměnné nám tak přidávají do kódu částečnou vazbu na naše zadání.
Ostatní pravidla ale v kódu explicitně uvedena nejsou.
</p>
<h2>C. Strukturujeme kód podle jednotlivých pravidel</h2>
<p>
<pre style="font-family:Consolas;font-size:13;color:black;background:white;"><span style="color:blue;">public</span> <span style="color:blue;">class</span> <span style="color:#2b91af;">NextGenerationStateCalculatorC</span>
{
<span style="color:blue;">public</span> <span style="color:#2b91af;">CellState</span> Calculate(<span style="color:#2b91af;">CellState</span> cellState, <span style="color:blue;">int</span> numberOfLiveNeighbours)
{
<span style="color:blue;">if</span> (cellState == <span style="color:#2b91af;">CellState</span>.Live && numberOfLiveNeighbours < 2) <span style="color:blue;">return</span> <span style="color:#2b91af;">CellState</span>.Dead;
<span style="color:blue;">if</span> (cellState == <span style="color:#2b91af;">CellState</span>.Live && (numberOfLiveNeighbours == 2 || numberOfLiveNeighbours == 3)) <span style="color:blue;">return</span> <span style="color:#2b91af;">CellState</span>.Live;
<span style="color:blue;">if</span> (cellState == <span style="color:#2b91af;">CellState</span>.Live && numberOfLiveNeighbours > 3) <span style="color:blue;">return</span> <span style="color:#2b91af;">CellState</span>.Dead;
<span style="color:blue;">if</span> (cellState == <span style="color:#2b91af;">CellState</span>.Dead && numberOfLiveNeighbours == 3) <span style="color:blue;">return</span> <span style="color:#2b91af;">CellState</span>.Live;
<span style="color:blue;">return</span> <span style="color:#2b91af;">CellState</span>.Dead;
}
}</pre>
</p>
<p>
Toto řešení nám sice zvedlo LOC, ale jeho struktura už více kopíruje jednotlivá pravidla. Opět nám však chybí informace o názvu jednotlivých pravidel a CC nám skočila na 10.
</p>
<h2>D. Extrahujme podmínky pro jednotlivá pravidla</h2>
<p>
<pre style="font-family:Consolas;font-size:13;color:black;background:white;"><span style="color:blue;">public</span> <span style="color:blue;">class</span> <span style="color:#2b91af;">NextGenerationStateCalculatorD</span>
{
<span style="color:blue;">public</span> <span style="color:#2b91af;">CellState</span> Calculate(<span style="color:#2b91af;">CellState</span> cellState, <span style="color:blue;">int</span> numberOfLiveNeighbours)
{
<span style="color:blue;">if</span> (UseUnderPopulationRule(cellState, numberOfLiveNeighbours)) <span style="color:blue;">return</span> <span style="color:#2b91af;">CellState</span>.Dead;
<span style="color:blue;">if</span> (UseSurviveRule(cellState, numberOfLiveNeighbours)) <span style="color:blue;">return</span> <span style="color:#2b91af;">CellState</span>.Live;
<span style="color:blue;">if</span> (UseOverPopulationRule(cellState, numberOfLiveNeighbours)) <span style="color:blue;">return</span> <span style="color:#2b91af;">CellState</span>.Dead;
<span style="color:blue;">if</span> (UseReproductionRule(cellState, numberOfLiveNeighbours)) <span style="color:blue;">return</span> <span style="color:#2b91af;">CellState</span>.Live;
<span style="color:blue;">return</span> <span style="color:#2b91af;">CellState</span>.Dead;
}
<span style="color:blue;">private</span> <span style="color:blue;">bool</span> UseUnderPopulationRule(<span style="color:#2b91af;">CellState</span> cellState, <span style="color:blue;">int</span> numberOfLiveNeighbours)
{
<span style="color:blue;">return</span> cellState == <span style="color:#2b91af;">CellState</span>.Live && numberOfLiveNeighbours < 2;
}
<span style="color:blue;">private</span> <span style="color:blue;">bool</span> UseSurviveRule(<span style="color:#2b91af;">CellState</span> cellState, <span style="color:blue;">int</span> numberOfLiveNeighbours)
{
<span style="color:blue;">return</span> cellState == <span style="color:#2b91af;">CellState</span>.Live && (numberOfLiveNeighbours == 2 || numberOfLiveNeighbours == 3);
}
<span style="color:blue;">private</span> <span style="color:blue;">bool</span> UseOverPopulationRule(<span style="color:#2b91af;">CellState</span> cellState, <span style="color:blue;">int</span> numberOfLiveNeighbours)
{
<span style="color:blue;">return</span> cellState == <span style="color:#2b91af;">CellState</span>.Live && numberOfLiveNeighbours > 3;
}
<span style="color:blue;">private</span> <span style="color:blue;">bool</span> UseReproductionRule(<span style="color:#2b91af;">CellState</span> cellState, <span style="color:blue;">int</span> numberOfLiveNeighbours)
{
<span style="color:blue;">return</span> cellState == <span style="color:#2b91af;">CellState</span>.Dead && numberOfLiveNeighbours == 3;
}
}</pre>
</p>
<p>
Extrahovali jsme podmínky pravidel do pojmenovaných privátních metod. Čitelnost se tím trochu zlepšila a snížili jsme CC hlavní metody na 5.
Pořád mi ale vadí, že podmínky a výsledný stav jednotlivých pravidel nejsou logicky lépe seskupeny.
Takto se nám v kódu 4-krát opakuje stejný pattern:
</p>
<p>
<pre style="font-family:Consolas;font-size:13;color:black;background:white;"><span style="color:blue;">if</span> (XRule(cellState, numberOfLiveNeighbours)) <span style="color:blue;">return</span> <span style="color:#2b91af;">CellState</span>.?;
</pre>
</p>
<h2>E. Sbližujeme podmínky pravidel a výsledné stavy</h2>
<p>
<pre style="font-family:Consolas;font-size:13;color:black;background:white;"><span style="color:blue;">delegate</span> <span style="color:blue;">bool</span> <span style="color:#2b91af;">RulePredicate</span>(<span style="color:#2b91af;">CellState</span> cellState, <span style="color:blue;">int</span> numberOfLiveNeighbours);
<span style="color:blue;">public</span> <span style="color:blue;">class</span> <span style="color:#2b91af;">NextGenerationStateCalculatorE</span>
{
<span style="color:blue;">public</span> <span style="color:#2b91af;">CellState</span> Calculate(<span style="color:#2b91af;">CellState</span> cellState, <span style="color:blue;">int</span> numberOfLiveNeighbours)
{
<span style="color:blue;">var</span> rules = <span style="color:blue;">new</span> <span style="color:#2b91af;">Dictionary</span><<span style="color:#2b91af;">RulePredicate</span>, <span style="color:#2b91af;">CellState</span>>
{
{ UnderPopulationRulePredicate, <span style="color:#2b91af;">CellState</span>.Dead },
{ SurviveRulePredicate, <span style="color:#2b91af;">CellState</span>.Live },
{ OverPopulationRulePredicate, <span style="color:#2b91af;">CellState</span>.Dead },
{ ReproductionRulePredicate, <span style="color:#2b91af;">CellState</span>.Live },
{ NoReproductionRulePredicate, <span style="color:#2b91af;">CellState</span>.Dead }
};
<span style="color:blue;">var</span> ruleKeyToApply = rules.Keys.First(rulePredicate => rulePredicate(cellState, numberOfLiveNeighbours));
<span style="color:blue;">var</span> nextGenerationState = rules[ruleKeyToApply];
<span style="color:blue;">return</span> nextGenerationState;
}
<span style="color:blue;">private</span> <span style="color:blue;">bool</span> UnderPopulationRulePredicate(<span style="color:#2b91af;">CellState</span> cellState, <span style="color:blue;">int</span> numberOfLiveNeighbours)
{
<span style="color:blue;">return</span> cellState == <span style="color:#2b91af;">CellState</span>.Live && numberOfLiveNeighbours < 2;
}
<span style="color:blue;">private</span> <span style="color:blue;">bool</span> SurviveRulePredicate(<span style="color:#2b91af;">CellState</span> cellState, <span style="color:blue;">int</span> numberOfLiveNeighbours)
{
<span style="color:blue;">return</span> cellState == <span style="color:#2b91af;">CellState</span>.Live && (numberOfLiveNeighbours == 2 || numberOfLiveNeighbours == 3);
}
<span style="color:blue;">private</span> <span style="color:blue;">bool</span> OverPopulationRulePredicate(<span style="color:#2b91af;">CellState</span> cellState, <span style="color:blue;">int</span> numberOfLiveNeighbours)
{
<span style="color:blue;">return</span> cellState == <span style="color:#2b91af;">CellState</span>.Live && numberOfLiveNeighbours > 3;
}
<span style="color:blue;">private</span> <span style="color:blue;">bool</span> ReproductionRulePredicate(<span style="color:#2b91af;">CellState</span> cellState, <span style="color:blue;">int</span> numberOfLiveNeighbours)
{
<span style="color:blue;">return</span> cellState == <span style="color:#2b91af;">CellState</span>.Dead && numberOfLiveNeighbours == 3;
}
<span style="color:blue;">private</span> <span style="color:blue;">bool</span> NoReproductionRulePredicate(<span style="color:#2b91af;">CellState</span> cellState, <span style="color:blue;">int</span> numberOfLiveNeighbours)
{
<span style="color:blue;">return</span> <span style="color:blue;">true</span>;
}
}</pre>
</p>
<p>
Zadefinovali jsme delegát <code>RulePredicate</code>, který popisuje, jak mají vypadat metody vyhodnocující podmínku pro pravidlo. Dictionary <code>rules</code> mapuje tyto podmínky na výsledné stavy.
Máme tak poměrně hezké přiřazení pojmenované podmínky a výsledného stavu pro jednotlivá pravidla. Za tento "funkcionální přístup" jsme odměněni hezkou jedničkou z CC.
</p>
<p>
Moc se mi ale nelíbí způsob procházení obecného <code>Dictionary</code>, kdy odkazujeme <code>Keys</code> abychom přistoupili k predikátům jednotlivých pravidel. Abstrakce pravidla stále není moc dobrá.
</p>
<h2>F. Tak dobře, zapouzdříme pravidla</h2>
<p>
<pre style="font-family:Consolas;font-size:13;color:black;background:white;"><span style="color:blue;">public</span> <span style="color:blue;">class</span> <span style="color:#2b91af;">NextGenerationStateCalculatorF</span>
{
<span style="color:blue;">private</span> <span style="color:blue;">readonly</span> <span style="color:#2b91af;">RuleBase</span>[] _rules;
<span style="color:blue;">public</span> NextGenerationStateCalculatorF()
{
_rules = <span style="color:blue;">new</span> <span style="color:#2b91af;">RuleBase</span>[]
{
<span style="color:blue;">new</span> <span style="color:#2b91af;">UnderPopulationRule</span>(),
<span style="color:blue;">new</span> <span style="color:#2b91af;">SurvivalRule</span>(),
<span style="color:blue;">new</span> <span style="color:#2b91af;">OverPopulationRule</span>(),
<span style="color:blue;">new</span> <span style="color:#2b91af;">ReproductionRule</span>(),
<span style="color:blue;">new</span> <span style="color:#2b91af;">NoReproductionRule</span>()
};
}
<span style="color:blue;">public</span> <span style="color:#2b91af;">CellState</span> Calculate(<span style="color:#2b91af;">CellState</span> cellState, <span style="color:blue;">int</span> numberOfLiveNeighbours)
{
<span style="color:blue;">var</span> ruleToApply = _rules.First(rule => rule.Predicate(cellState, numberOfLiveNeighbours));
<span style="color:blue;">var</span> nextGenerationState = ruleToApply.NextGenerationCellState;
<span style="color:blue;">return</span> nextGenerationState;
}
<span style="color:blue;">private</span> <span style="color:blue;">abstract</span> <span style="color:blue;">class</span> <span style="color:#2b91af;">RuleBase</span>
{
<span style="color:blue;">public</span> <span style="color:#2b91af;">RulePredicate</span> Predicate { <span style="color:blue;">get</span>; }
<span style="color:blue;">public</span> <span style="color:#2b91af;">CellState</span> NextGenerationCellState { <span style="color:blue;">get</span>; }
<span style="color:blue;">protected</span> RuleBase(<span style="color:#2b91af;">RulePredicate</span> predicate, <span style="color:#2b91af;">CellState</span> nextGenerationCellState)
{
Predicate = predicate;
NextGenerationCellState = nextGenerationCellState;
}
}
<span style="color:blue;">private</span> <span style="color:blue;">class</span> <span style="color:#2b91af;">UnderPopulationRule</span> : <span style="color:#2b91af;">RuleBase</span>
{
<span style="color:blue;">public</span> UnderPopulationRule()
: <span style="color:blue;">base</span>((state, neighbours) => state == <span style="color:#2b91af;">CellState</span>.Live && neighbours < 2, <span style="color:#2b91af;">CellState</span>.Dead)
{ }
}
<span style="color:blue;">private</span> <span style="color:blue;">class</span> <span style="color:#2b91af;">SurvivalRule</span> : <span style="color:#2b91af;">RuleBase</span>
{
<span style="color:blue;">public</span> SurvivalRule()
: <span style="color:blue;">base</span>((state, neighbours) => state == <span style="color:#2b91af;">CellState</span>.Live && (neighbours == 2 || neighbours == 3), <span style="color:#2b91af;">CellState</span>.Live)
{ }
}
<span style="color:blue;">private</span> <span style="color:blue;">class</span> <span style="color:#2b91af;">OverPopulationRule</span> : <span style="color:#2b91af;">RuleBase</span>
{
<span style="color:blue;">public</span> OverPopulationRule()
: <span style="color:blue;">base</span>((state, neighbours) => state == <span style="color:#2b91af;">CellState</span>.Live && neighbours > 3, <span style="color:#2b91af;">CellState</span>.Dead)
{ }
}
<span style="color:blue;">private</span> <span style="color:blue;">class</span> <span style="color:#2b91af;">ReproductionRule</span> : <span style="color:#2b91af;">RuleBase</span>
{
<span style="color:blue;">public</span> ReproductionRule()
: <span style="color:blue;">base</span>((state, neighbours) => state == <span style="color:#2b91af;">CellState</span>.Dead && neighbours == 3, <span style="color:#2b91af;">CellState</span>.Live)
{ }
}
<span style="color:blue;">private</span> <span style="color:blue;">class</span> <span style="color:#2b91af;">NoReproductionRule</span> : <span style="color:#2b91af;">RuleBase</span>
{
<span style="color:blue;">public</span> NoReproductionRule()
: <span style="color:blue;">base</span>((state, neighbours) => <span style="color:blue;">true</span>, <span style="color:#2b91af;">CellState</span>.Dead)
{ }
}
}</pre>
</p>
<p>
Hlavní metoda prohledá pole pravidel inicializovaných v konstruktoru třídy. Vybraného pravidla se pak zeptá na příští stav. CC = 1.
Při implementaci jednotlivých pravidel jsme si pomohli bázovou třídou <code>RuleBase</code>. Implementace konkrétního pravidla se nám pak omezí pouze na předání predikátu a nového stavu přes volání bázového konstruktoru.
</p>
<p>
Každé pravidlo je nyní reprezentováno dobře pojmenovanou třídou. Hlavní třída pouze definuje pořadí těchto pravidel a umí se doptat na výsledný stav buňky v příští generaci.
Celková komplexita problému je rozložena do více tříd s nízkou komplexitou. Přestože je kód delší, můžeme jej stále považovat za jednoduchý.
</p>
<h2>Jak tedy psát ten kód?</h2>
<p>
Možná si říkáte, kam jsme se to v tom vylepšování až dostali. Proč tak složitě na tak jednoduchý problém? Proč vytvářet tolik tříd?
</p>
<p>
Je to trénink. Test toho, jak vnímáme komplexitu kódu a které charakteristiky nás vlastně zajímají. Reálné problémy jsou samozřejmě složitější a správná redukce komplexity přinese výraznější benefity.
A příjemnější práci pro programátory.
</p>
<p>
<i>Přemýšlejme nad každým větvením programu, zda-li se náhodou nejedná o signál pro použití polymorfismu a separaci na úrovni tříd. Nízká CC by měla být našim základním požadavkem.</i>
</p>
<p>
<i>Preferujme, aby v našem kódu byla snadno dohledatelná struktura reálného problému, tedy našich (správně formulovaných) požadavků.</i>
</p>
<p>
<i>Nejrychlejší / nejkratší řešení často nebývá nejlepší. Zvažujme různé možnosti a přístupy. Psát "složitý kód" bývá jednoduché, zato psát "jednoduchý kód" často složité.</i>
</p>
<p>
Strach, lenost nebo neschopnost problém dekomponovat do více jednodušších tříd často vede k hromadám špaget. Nic proti špagetám, mohl bych je mít pořád. Ale v kódu se bez nich rád obejdu! :)
</p>
Robert Dreslerhttp://www.blogger.com/profile/16401744220939465418noreply@blogger.com3tag:blogger.com,1999:blog-3408745507091232422.post-81066505152047439982016-02-28T18:05:00.001+01:002016-02-28T18:05:26.310+01:00Požadavky na požadavky<p>Primárním cílem každého software je řešit problémy zákazníka nebo své cílové skupiny. Řešení je popsáno specifikací požadavků na systém.
Psát dobré požadavky a efektivně je spravovat není snadné. Vyžaduje to specifické dovednosti a spolupráci napříč celým týmem. Dobrá specifikace je ale stejně důležitá jako dobrý zdrojový kód.</p>
<p>Pojďme se společně podívat, jaké problémy nám mohou komplikovat práci s požadavky.</p>
<p><div class="separator" style="clear: both; text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEj3sQqk5bNw4jHigw5ILUHdt6aMMQctJ7DA1TWMzNlXiTdupfVNNVHduF7C-3eCDEA7j5N_qVc_LYHXtq7aZtcMCi5scbagmuyH-UMPU-Epso1lgKosDDya52wu8v8bUO36ZaYHAv7xH4Jq/s1600/Healthcare-IT-Usability-Comic-Strip%255B1%255D.gif" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEj3sQqk5bNw4jHigw5ILUHdt6aMMQctJ7DA1TWMzNlXiTdupfVNNVHduF7C-3eCDEA7j5N_qVc_LYHXtq7aZtcMCi5scbagmuyH-UMPU-Epso1lgKosDDya52wu8v8bUO36ZaYHAv7xH4Jq/s1600/Healthcare-IT-Usability-Comic-Strip%255B1%255D.gif" /></a></div></p>
<h2>Tohle není můj problém</h2>
<p>Programátor: <i>“Od analytiků dostáváme hrozné zadání. Jak podle toho máme něco naprogramovat!?”</i></p>
<p>Analytik: <i>“Vykomunikoval jsem to se zákazníkem, popsal hlavní ideu, navrhl postup a tím to pro mě končí. Programátoři ale chtějí, abych za ně promýšlel problém do úplných detailů. To je jejich práce. Na to nemám čas.”</i></p>
<p>Pokud mají dvě skupiny v naší firmě potřebu se vzájemně vyhraňovat, máme dost závažný problém. Týmové role nespolupracují efektivně. Chtějí si nadefinovat rigidní rozhraní místo snahy o spolupráci na nejlepším výsledku. Agilita je o společné zodpovědnosti za vše, co s vyvíjeným software souvisí. Včetně požadavků. Odolejme pokušení sortovat na ty, co dělají zadání a na ty, co podle zadání dělají konstrukci. Jsme jeden tým. Pokud můžeme, posaďme zákazníka, analytika, programátora, testera a další lidi do jedné kanceláře. Nebo je propojme nějakým efektivním komunikačním kanálem. Potřebujeme dobrou komunikaci, rychlou zpětnou vazbu a rychlé zapracování změn.</p>
<h2>Zrovna dodělávám kompletní specifikaci</h2>
<p>Projektový manažer: <i>“Výborně Karle, ta specifikace vypadá neprůstřelně, teď to necháme kluky naestimovat a můžeme podepsat smlouvu.”</i></p>
<p>Pokusy vytvořit kompletní specifikaci ještě před konstrukcí (up-front) možná fungují u malých věcí nebo u opakujících se podobných projektů. Často ale ani tam. U větších věcí s vysokým stupněm inovace a nejistoty jsou ale podobné ambice tvrdě trestány. Navýšením nákladů a frustrací ze zbytečné práce, kterou musíme často zahodit. Rigidní vodopádová snaha zakonzervovat požadavky je často naivní obranou proti neschopnosti efektivně provádět změny během konstrukce. A nebo je důsledkem striktní smlouvy o dílo, kde zákazník raději vsadí na jistotu “dodání funkcionality v požadovaném rozsahu”.</p>
<p>Buďme připraveni na změnu. Mějme na paměti celek, ale rozdělujme na podproblémy. Specifikujme vysokoúrovňové business požadavky. Analyzujme je podle priority a rozpracujme do podrobnějších produktových požadavků ve formě user stories. Prioritizované user stories nám vytvoří produktový backlog. User story ale zatím není zadání, na které čeká programátor. Je to pouze placeholder pro následnou detailní specifikaci.</p>
<p>Když se na user story dostane řada, začíná její detailnější analýza a definice požadavků. Očekávanými výsledky jsou popis chování systému (use cases), upřesnění UI (mock-ups) a nefunkcionální specifikace. Analytik analyzuje problém a navrhuje řešení v úzké spolupráci se zadavatelem. Využívá znalostí a spolupráce dalších rolí v týmu. V případě rizik, omezené znalosti technologií nebo možnosti více konceptů, je prováděno rychlé prototypování. Ty nejrizikovější věci by měly být odprototypovány na začátku projektu.</p>
<p>Dobrou praktikou je vytvoření test cases ještě před vlastní konstrukcí. V této fázi mohou test cases odhalit závažné nedostatky ve specifikaci požadavků a ušetřit tak spoustu peněz v případě pokračování špatným směrem. Pokud tester není schopen napsat kompletní a jednoznačné testovací případy, zřejmě ani programátor nebude schopen efektivní implementace. Zkušený tester prokoukne nedefinované alternativní větve, chybějící podmínky nebo neošetřené chybové stavy. Často jsou v detailech ukryta závažná projektový rizika.</p>
<h2>Nevíte někdo, jak to funguje?</h2>
<p>Analytik: <i>“Omlouvám se za hromadný email na všechny lidi ve firmě, ale nemůžu najít specifikaci business pravidel pro XY. Poradí mi někdo, prosím?”</i></p>
<p>Odpověď A: <i>“Aleši, to by mě taky zajímalo, až to zjistíš, dej mně prosím vědět.”</i></p>
<p>Odpověď B: <i>“Zkus složku SpecABC, jsou tam nějaké staré wordy. Kdyby to nebylo tam, tak něco možná bude na naší wiki. Jinak dělal to Lojza a ten už ve firmě není. Jak asi víš, z těch přesčasů mu nakonec hráblo. Pokud to nenajdeš, budeš to muset pochopit z kódu. Ale to ti fakt nezávidím. :)”</i></p>
<p>Na začátku každého projektu vše vypadá krásně a růžově. Lidé jsou nadšení. Všichni zúčastnění vědí o projektu téměř všechno. Nějaká specifikace možná existuje, ale její správě a aktualizaci se často nevěnuje příliš velká pozornost. Požadovaná funkcionalita se dodává rychle, všechno klape a management se poplácává po zádech. Všichni jsou happy.</p>
<p>Projekt roste, vyvíjí se, nová funkcionalita přibývá a stávající se mění, noví lidé přicházejí, původní odcházejí. Je nutná specializace, komplexita systému je už příliš vysoká. Začínají se zvyšovat náklady na správu všech projektových artefaktů. Kde máme aktuální informace? Co všechno se musí upravit kvůli novému požadavku? Jaká jsou rizika? Co vlastně máme před releasem otestovat?</p>
<p>Špatné nakládání se specifikací systému je jednou z nejrizikovějších forem softwarového technického dluhu. Členové týmu zdlouhavě dohledávají informace, dělají špatná rozhodnutí na základě nesprávných informací, vznikají duplicity, zvyšuje se chybovost, management je pod tlakem a přehazuje lidi podle toho, kde to nejvíce hoří. Lidé nemají možnost dělat práci kvalitně a proto frustrovaně odcházejí. Někdy může situaci dospět až k tomu, že údržba projektu je tak drahá, že se už dále nevyplácí a projekt je ukončen. Poslední ať zhasne.</p>
<p>Začněme správu požadavků řešit co nejdříve. Celý proces musí být co nejefektivnější a nejjednodušší. Složité postupy nefungují. Zde je <a href="http://www.capterra.com/requirements-management-software/">přehled Requirement Management Software</a>. Pokud máte s nějakým systémem větší zkušenost a můžete jej doporučit, přidejte prosím komentář.</p>
<h2>Výkonný systém s intuitivním UI</h2>
<p>Programátor: <i>Arnošt mi zase poslal zadání, ve kterém píše “vytvořit dostatečně výkonný modul s intuitivním ovládáním, podobný tomu z loňska, ale upravený pro letošní administrativu”. Jdu ho intuitivním způsobem poslat k šípku, podobně jako loni.</i></p>
<p>Jak psát efektivně požadavky je popsáno v <a href="http://www.processimpact.com/articles/qualreqs.html">Writing Quality Requirements</a>. Je to už sice hodně vousatý článek, ale přehledně shrnuje to nejdůležitější. Čemu se máme vyvarovat a na co se zaměřit. Jedná se o povinné čtení pro všechny vývojáře software.</p>
<p>Podobně jako jsme zvyklí revidovat kód, abychom našli problémy a sdíleli znalosti o implementaci, můžeme revidovat i požadavky. Analytik musí vysvětlit své chápání problému a důvody proč navrhl toto řešení. Pár tipů na review najdete v <a href="http://www.bridging-the-gap.com/requirements-review/">How to Conduct a Requirements Review.</a></p>
<p>Dobrý business analytik je vyladěnou kombinací doménových znalostí a analytických dovedností, viz. např. <a href="http://www.bridging-the-gap.com/business-analyst-skills-important/">What Business Analyst Skills are Important</a>. Ty je potřeba neustále procvičovat a vylepšovat. Jak rozvíjíte BA ve vašem týmu?</p>
<h2>Shrnutí</h2>
<p>Dobře definované požadavky na systém jsou prvním zásadním krokem pro kvalitní výsledek snažení celého týmu. Nesnažme se však všechno vymyslet a popsat hned na začátku. Riziko špatné specifikace je příliš vysoké. Změny pak budou bolet mnohem víc než při postupném iterativním vývoji.</p>
<p>Chápejme proces specifikace systému jako spolupráci celého týmu. Nechtějme programátory-opičky, kteří dostanou přesné zadání a jen klepou. To nefunguje. Chceme myslící bytosti, s určitou znalostí domény, aktivně zapojené do procesu vytváření software.</p>
<p>Specifikace je živá interaktivní dokumentace, která se musí efektivně udržovat po celou dobu života projektu. Úroky za macešský přístup k požadavkům jsou totiž příliš vysoké.</p>
<p>Podělíte se s námi o to, jak se daří spravovat požadavky u Vašeho projektu? Díky.</p>
Robert Dreslerhttp://www.blogger.com/profile/16401744220939465418noreply@blogger.com0tag:blogger.com,1999:blog-3408745507091232422.post-3837039355625584372015-05-23T12:38:00.001+02:002015-05-23T12:38:14.508+02:00Programátore, chceme tě mít on-site<div class="separator" style="clear: both; text-align: center;">
<img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEg6Pq4x0dxfcqoiRIxpXiqtg0TjaTnVoLwc_FBqyjT4WjNUbk2ITPSeGAW3VyRYjN2lCrrFCFQAKOh_8uVL0OCtk2WAe48XzNZIzx5aYXZlQORGUaVS-kFc-hcwJ7BG_fqxjdXtCK0C5VZi/s1600/247-support1%255B1%255D.png"
style="border:none;box-shadow:none;vertical-align:bottom;horizontal-align:center;" />
</div>
<p>
<i>
"Po nějaké době je možné dohodnout částečný home-office"<br/>
"Projekt je krátkodobý proto klient vyžaduje on-site"
</i>
</p>
<p>Ach jo, píše se rok 2015 a většina IT firem u nás stále není mentálně připravena a aktivně nepodporuje remote work. Vidí spásu v tom, že budou mít všechny ovečky pěkně pohromadě v budově, do které investovaly velké peníze. Ztrácejí tak možnost spolupracovat s lidmi, kteří mají odbornost, dostatek sebekontroly a požadovaný výsledek by mohli dodat dříve a ve vyšší kvalitě.
</p>
<p>Proč? Většina projektů v IT se zpožďuje, prodražuje se a původní estimace, pracně vytřepané z rukávu a několikrát pozměněné, se nám ve finále smějou do očí. Představa, že budou muset vysvětlovat vyšší náklady na projekt a ještě fakt, že tým pracoval remote, mnoho projekťáků děsí. Nebudeme si proto komplikovat situaci, co říkáte?
</p>
<p><i>"Práce remote není pro každého."</i> Pro koho tedy není? Pro někoho, kdo při on-site na rozdíl od remote odvádí výsledky? Aha, takže pracuje dobře jen pod dohledem nadřízeného. Chcete takového kolegu?
</p>
<p><i>"Jak mám jako vedoucí sledovat progres remote týmu?"</i> A jak jej sleduješ u on-site? Efektivní vývojové metodologie nejsou nijak zásadně závislé na tom, jestli transformátory kávy na kód sedí blízko sebe nebo stovky kilometrů. Mnohem více jsou závislé na dobré komunikaci, dostatečné zpětné vazbě a dobrých návycích členů týmu. Zkuste si remote pair work, je to fajn.
</p>
<p><i>"Když já opravdu nevím, co vlastně doma dělá."</i> Dělá to, co je typické pro tvůj tým a firmu. Pokud máš dobře motivované zaměstnance, jste orientovaní na výsledek a kvalitu, bude to dělat i vzdáleně. Prostě pokud ho práce baví, neměj strach. Pokud umíš řídit lidi, poznáš, že někdo do týmu nepatří.
</p>
<p><blockquote class="twitter-tweet" lang="en"><p lang="sk" dir="ltr">"Pokud nepovolíte svým lidem práci z domova jen kvůli strachu, že se bez vašeho dohledu budou flákat, jste chůva, ne manažer." <a href="https://twitter.com/hashtag/pracenadalku?src=hash">#pracenadalku</a></p>— Robert Dresler (@rdresler) <a href="https://twitter.com/rdresler/status/447271603299430400">March 22, 2014</a></blockquote>
<script async src="//platform.twitter.com/widgets.js" charset="utf-8"></script>
</p>
<p><i>"Komunikace není efektivní, navíc mě pořád ruší zprávy na messengeru"</i>. V dnešní době rychlých připojení k internetu a nástrojů pro spolupráci asi nebude problém ve vzdálenosti. Hledej problém někde jinde - v organizaci času a práce, v efektivitě týmových schůzek, ve schopnosti přepnout do distraction-free režimu.
</p>
<p><i>"Lidé, dokonce i programátoři, potřebují trávit společně čas"</i>. Tak určitě. Ale kolik vlastně?</p>
<p>Sedí tam hodně programátorů a všichni mají sluchátka, co je to? Open space.</p>
<p>IT firmo, chceš kvalitní lidi nebo je potřebuješ mít hlavně všechny pohromadě?</p>
Robert Dreslerhttp://www.blogger.com/profile/16401744220939465418noreply@blogger.com2tag:blogger.com,1999:blog-3408745507091232422.post-28314237889171458992014-05-31T14:17:00.002+02:002014-05-31T14:20:06.812+02:00Malými krůčky ke zvládnutí velkých úkolů<div class="separator" style="clear: both; text-align: center;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEicd_rlS-iSfuosc1faY5JK4fzO6mXXmnSPC58Y5s451VGUJRg3L1i6mLLLiAurlRkDW02WK1wqF-cicNvm0uHOepBwDnyRxjKPoISWrHhUhBJYWN2p2NKhYOLJMAAlwgvqLyjeyqIpjXJK/s1600/lego.jpg" style="border:none;box-shadow:none;vertical-align:bottom;horizontal-align:center;" /></div>
<p>Tento příspěvek je krátkou obhajobou dekompozice složitých problémů na malé koncové tasky. Práce s malými tasky totiž působí přímo blahodárně na často dost zatížené nervové soustavy členů projektového týmu. Pokud se váš projekt zasekává a dostává se do vážnějších problémů, zkuste se zamyslet nad tím, zda-li nebojujete s problémy, které jsou typické pro nezvládnutí správné dekompozice složitosti.</p>
<h2>Malý task</h2>
<p>Co je vlastně myšleno malým taskem? Pro mě je to task s dobou realizace do 4 hodin, ale ideálně kolem 2h. A nezávisle na tom, zda-li se jedná o práci analytickou, návrhovou, implementační, testování nebo úkoly spojené s podpůrnou infrastrukturou projektu a byrokracií (paper work). Velikost commitu v případě implementačního tasku by neměla překročit řádově desítky změněných řádků (počítáno jako LLOC). Na druhou stranu je počet změněných řádků kódu dost zavádějící metrika. Někdy můžeme půl dne hledat bug a výsledkem je změna na jednom řádku (+ nový původně padající test). Jindy děláme refaktoring a jeden rozsáhlejší rename vynutí změny na stovkách řádků.</p>
<h2>Ne vždy se to podaří ...</h2>
<p>Rozložení řešeného problému na malé postupné krůčky je efektivní a univerzální technika ve všech oborech lidské činnosti. Ve vývoji software je ale nutné mít vhodné podpůrné nástroje a efektivní postupy. Jinak se dobře míněná snaha o zvýšení efektivity práce změní ve znechucené trápení. Je nutné zajistit splnění několika základních podmínek:</p>
<p>
<ul>
<li>Pracovní postupy by neměly být zatíženy přílišným formalismem. Čím méně restriktivních opatření, tím lépe. Příliš formální metodiky jsou účinnou antikoncepcí proti vytváření malých tasků. Předpokládám, že agilita si vybojovala místo i ve vašem vývojovém týmu a proto bude tato podmínka bude splněna.</li>
<li>Používejte nástroj, který vám usnadní správu a vizualizaci tasků. Protože jsou malé, je jich také mnoho. Nástroj musí být intuitivní, rychlý a dostupný bez omezení. My jsme se rychle spřátelili s YouTrackem, který pro naše potřeby maximálně vyhovuje.</li>
<li>Vytvoření tasku musí být rychlé. Vybrat umístění (projekt, feature nebo user story), zadat název, stručný popis, akceptační kritéria a estimaci. To by mělo ve většině případů stačit. Někdy se při vytváření tasku zasekneme, neboť napsat dobré zadání je pracné. Ale zdržovat by nás mělo pouze naše myšlení a ne použitý nástroj.</li>
<li>Používejte pouze atributy, které potřebujete. Šablona tasku, která má desítky atributů je dobrá obvykle jen pro někoho, komu potřeba projektové formalizace způsobila neléčitelnou ztrátu zdravého rozumu. V jednoduchosti je síla, proto nejdůležitější položky musí být dostupné rychle, bez nutnosti překlikávání. Méně využívané položky by pak měly být schované na detailových kartách. A nepoužívané bez milosti odstraněny. Dvakrát si rozmyslete, než přidáte nový atribut.</li>
<li>Workflow tasku musí být jednoduché. Čím méně stavů tím lépe. Na našem posledním projektu jsme zvolili tyto: Backlog, Ready for Dev, Dev in Progress, Ready for Review, Review in Progress, Finished (+ Waiting) s vizualizací pomocí Kanban boardu. Pokud bychom neměli interní politiku o revidování každého tasku, pak bychom ještě dva stavy ušetřili. Některé typy tasků ale jedou v jiném režimu, např. task typu Bug nahlášený od testerů nebo v horším případě z produkce.</li>
<li>Mělo by být možné integrovat systém pro evidenci tasků s dalšími články vývojové infrastruktury. A to se správou repository, buildovacím serverem, IDE, CASE, apod. Např. k namapování změn v kódu na příslušný task pak pouze stačí odkazovat id tasku v commit message.</li>
</ul>
</p>
<h2>Ale když se to podaří ...</h2>
<p>A v čem jsou vlastně malé tasky šikovnější než ty velké obludy?</p>
<p>
<ul>
<li>Rychlé vyřešení tasku působí blahodárně na psychiku a dobrý pocit z dokončení je účinným motivátorem do další práce. Rozplizlé dlouhé tasky nás naopak demotivují, nevidíme na jejich vzdálený konec a vnášejí pochybnosti o naší pracovní efektivitě. Tak jako většina lidských činností je i vývoj software psychologickou hrou s naším podvědomím, snahou udržet nadšení, pozornost a správný kurz k požadovanému cíli.</li>
<li>Menší jednotky práce je snadnější přesně specifikovat. Problém jsme nuceni už při zadávání lépe promyslet a zadefinovat akceptační kritéria. Dobrým zadáním problému zvyšujeme pravděpodobnost správné realizace a efektivního review.</li>
<li>Přesnější estimace. Je dost deprimující, když se skutečná pracnost na hony liší od té odhadované. Malé úkoly trefíme mnohem lépe. Doporučuji mírně pesimistický přístup a zohlednit časovou rezervu. Udělat úkol dříve než se čekalo je povzbuzující. Máme ze sebe dobrý pocit a roste nám správným způsobem sebevědomí. Naopak výrazné přešvihnutí estimace nás dostává pod tlak, který často vyústí ve sníženou kvalitu výsledku.</li>
<li>Review menších změn je mnohem efektivnější. Je zřejmé, na co se zaměřit. Review trvá kratší dobu, takže reviewer je pozornější, neusíná a často i něco objeví. </li>
<li>Stává se méně často, že odcházíme domů a zůstane po nás nedokončený úkol. Já osobně nemám tyhle situace vůbec rád a když něco nedotáhnu do konce, přemýšlím nad tím ještě doma. A nejhorší je nedotahovat věci v pátek odpoledne.</li>
<li>Pokud zaneseme chybu nebo rozbijeme CI build, pak je problém mnohem lépe dohledatelný. Je rozdíl, pokud hledáte v commitu s 20 změněnými řádky nebo s 200.</li>
<li>Dostáváme rychlejší zpětnou vazbu a pokud se něco nepovede, nevracíme se příliš daleko dozadu. Víme, jak je nepříjemné zahodit kód, nad kterým jsme strávili dlouhé hodiny nebo dny. Obvykle je ale výhodnější špatný kód zahodit, než obhajovat jeho smysluplnost a tím jeho eutanázii pouze oddalovat a zvyšovat tak náklady na vývoj.</li>
<li>Malé tasky vnášejí do vývoje větší dynamiku a celý tým může sledovat postup řešení většího celku, třeba user story. Nestává se, že programátor dostane zadání, pár dnů o něm nevíte a pak se objeví s “vymazlenou” implementací, která se ale hodně odklonila od původního záměru a trpí mnoha nedostatky.</li>
<li>Jistě znáte techniku TDD, která nabádá ke krátkým implementačním cyklům se strukturou: 1. rozmysli si co chceš (napiš test), 2. naimplementuj to (napiš produkční kód), 3. zkontroluj, jestli změna nerozbila celek (všechny testy zelené), 4. vylepši fungující implementaci (refaktoring). Díky TDD dostáváme okamžitou zpětnou vazbu o stavu našeho kódu. Malý task by pak v tomto chápání mohl mít podobný efekt jako cyklus TDD, ale s větší granularitou. Nutí nás více rozmýšlet požadovaný výsledek, ten dostáváme již během několika hodin. Po uložení změn do repository získáme skrze CI build informaci o stavu celku. V rámci review můžeme řešení ještě vylepšit.</li>
</ul>
</p>
<p>S malými tasky můžeme dosáhnout velkých výsledků. A navíc velmi efektivním způsobem. A za každé dokončení tasku se můžeme nějak odměnit. Třeba procházkou k lednici, krátkou rozcvičkou nebo dobrým kafem. A život programátora bude zase o něco veselejší! ;)</p>Robert Dreslerhttp://www.blogger.com/profile/16401744220939465418noreply@blogger.com2tag:blogger.com,1999:blog-3408745507091232422.post-65521561425174131322014-05-04T16:10:00.000+02:002014-05-04T16:10:24.807+02:00Mýty o češtině v softwarových projektech<p>Pojďme společně rozkrýt několik mýtů pojících se k používání češtiny v softwarových projektech. Do mých názorů se promítají zkušenosti ze dvou zcela odlišných softwarových firem a světů. Dřívější firma byla orientovaná na regionální trh (ČR, SK) a všechny projekty byly realizovány v češtině. Stávající firma naopak dodává systémy do všech koutů světa a na vývoji pracují lidé z více států. Vývoj tedy logicky probíhá kompletně v angličtině.</p>
<p>Je potřeba přiznat, že ještě před několika lety bych určitě mluvil jinak a tento blogpost bych nenapsal. I z některých mých prehistorických příspěvků je zřejmé, jaký pasivní zastánce češtiny v kódu jsem dříve býval. :) Možná ne přímo zastánce, ale spíš ten, kterému čeština nijak výrazně nevadila. Byl jsem tak prostě zvyklý roky programovat a celé to zapadalo do požadavků na software realizovaných projektů. Domnívám se, že není problém své názory měnit na základě poučení z chyb a podle postupně získaných zkušeností. :)</p>
<h2>Mýtus "Programátor nepotřebuje umět výborně anglicky"</h2>
<p>Znalost angličtiny je jednou z klíčových dovedností programátora. Dalo by se říct, že je to takový meta-skill. Náš obor klade vysoké nároky na průběžné učení a rozšiřování profesní kvalifikace. Bez znalosti angličtiny je právě získávání nových dovedností a znalostí velmi problematické. Knížky, fóra, github, blogy, socsítě, návody, dokumentace, a další jsou studnicí informací, které mohou rozhodovat o úspěchu či neúspěchu celého projektu.</p>
<p>Zdrojový kód je důležitý komunikační prostředek celého týmu. Jazykové schopnosti členů týmu se výrazně projeví na kvalitě celého kódu. Špatné pojmenování je významným zdrojem programových chyb a nečekaných překvapení. Testy slouží jako interní dokumentace systému a jejich názvy musí být co nejvýstižnější.</p>
<p>Určitě nezastávám názor, že programátor, který neumí pořádně anglicky, není schopen vytvářet ve výsledku kvalitní aplikace. Věřím, že mnoho dobrých aplikací napsali a ještě napíšou lidé, kteří anglicky umí velice špatně. Ale mnohem větší procento dobrých programátorů angličtinu ovládá dobře. Je to stejné jako s jinými skilly. Nemusíte psát testy, používat TDD, CI, agilní metodiky, prototypování, iterativní vývoj, revize kódu, apod. a požadovaného výsledku také dosáhnete. Otázkou je v jaké kvalitě a s jakou efektivitou? A hlavně, kdo a jak bude schopen aplikaci dlouhodobě udržovat a rozvíjet?</p>
<p>Souvislost jazykové vybavenosti programátora a otázka pracovních příležitostí na zajímavých projektech je na samostatný blogpost. Určitě má zkušenosti každý, kdo se v poslední době zajímal o nějaké pracovní nabídky. Angličtina je již téměř všude must-have. A kde není, tam je to podezřelé. :)</p>
<h2>Mýtus "Čeština ve zdrojovém kódu nevadí"</h2>
<p><i>English. Lingua franca for programming.</i></p>
<p>Z pohledu někoho, kdo angličtinou příliš nevládne, je čeština jedinou šancí jak významu kódu porozumět. Já ale za ideální situaci považuji, když jediným místem ve zdrojových kódech, kde objevíme češtinu, jsou lokalizované resources. Čeština namíchaná s angličtinou snižuje čitelnost kódu. Do názvosloví se zanášejí patvary typu ObjednavkaFactory, ObjednavkaTovarna, getCena, apod. Neustále se řeší, co se má přeložit a kdy je lepší ponechat anglický ekvivalent. Pamatuji na situaci, kdy kolega pojmenoval třídu 'Kanalovna', protože pracovala s channels WCF služby. Jiným hezkým případem programátorské lidové tvořivosti budiž chybová hláška z přiloženého tweetu, kterou nedávno zpopularizoval Augi. Prostě hromada problémů způsobená díky pokusům sloučit dva nekompatibilní jazykové světy.</p>
<blockquote class="twitter-tweet" lang="en"><p>Lol, v iDnes aplikaci pro WP používají české názvy tříd a metod, s diakritikou! :) <a href="http://t.co/Sxkn2rOLMT">pic.twitter.com/Sxkn2rOLMT</a></p>— Augi (@AugiCZ) <a href="https://twitter.com/AugiCZ/statuses/436023774589517824">February 19, 2014</a></blockquote>
<script async src="//platform.twitter.com/widgets.js" charset="utf-8"></script>
<br />
<h2>Mýtus "Terminologie domény by měla být v češtině, protože v ní máme větší vyjadřovací možnosti"</h2>
<p>Nejčastější výjimky z pravidla “vše v angličtině” se dělají na úrovni názvů doménových objektů. Argumentem bývá terminologická složitost některých specifických domén, kdy je problém najít vhodný termín “alespoň v češtině”. Pokud ale najdeme vhodný termín v češtině, určitě ho najdeme také v angličtině. V některých případech se určitě vyplatí spolupracovat se zkušeným překladatelem. Doménu by měli dobře znát doménoví analytici a v potřebném rozsahu také programátoři. Kodéři bez znalostí souvislostí nemají obvykle v projektu příliš vysokou hodnotu. </p>
<p>Osobně vidím problém ještě někde jinde. A sice je nutné, aby každý projekt měl dobře definovaný doménový slovník, ze kterého vychází terminologie používaná v projektu. Z vlastní zkušenosti vím, jak velký problém to bývá. Pokud se už na začátku projektu nezadefinují jednoznačně pojmy, pak to dopadá tak, že se systém hemží synonymy a různými názvy pro stejnou entitu nebo vlastnost. Takové nejednoznačnosti výrazně komplikují pochopení a udržovatelnost systému.</p>
<h2>Mýtus "Každý softwarový projekt by měl být realizován v angličtině"</h2>
<p>Jsou projekty, u kterých je jasné, že jiná možnost než angličtina neexistuje. Např. děláte pro zahraničního zákazníka, ve vašem týmu se mluví více jazyky, máte globálnější ambice, vyvíjíte nějaký open-source nebo prostě jen chcete, aby váš kód pochopil i někdo nemluvící česky. Na druhou stranu jsou stále situace, kdy je nutné projekt realizovat ve větší míře v češtině. V případě, že máte pouze lokálního zákazníka, kterému nevadí, že nebude mít projektové artefakty v angličtině a současně nemáte tým, který by to v angličtině zvládl. Pak to zřejmě smysl má. Osobně si ale myslím, že takové ryze české projekty budou stále více v menšině. Uvědomělí zákazníci budou požadovat za svoje (nemalé) investice realizace projektů, které nebudou pevně svázané s lokálním jazykem.</p>
<h2>Mýtus "Dobrá kombinace je kód v angličtině a zbytek v češtině"</h2>
<p>Nevidím to jako úplně dobrý nápad. Takový hybrid asi nebude použitelný pro někoho, kdo nemluví česky. Při realizaci projektu se navíc budete muset neustále přepínat mezi češtinou a angličtinou. Rozhodněte se pro angličtinu a vytvářejte všechny projektové artefakty v angličtině. Zpočátku to možná bude trochu drhnout, ale vydržte, výhody jsou zřejmé.</p>
<h2>Mýtus "Kód v angličtině, komentáře v češtině"</h2>
<p>Raději dobře čitelný kód, který nepotřebuje (nedokumentační) komentáře. A pokud jsou přeci jen potřeba, pak bych rozhodně zůstal u angličtiny. Komentáře v češtině by se nejspíše staly nesmyslnými ostrůvky vítězství programátorova nacionálního cítění. U dokumentačních komentářů předpokládám, že budou vždy v angličtině.</p>
<p>A na závěr jeden bonbónek ...</p>
<h2>"Pro větší názornost jsem zdrojový kód přeložil do češtiny"</h2>
<p>Néé, jen to ne. Pokud k tomu autor překladu odborné literatury přidá ještě jako bonus diakritiku, pak takovou knížku dočte do konce zřejmě jen hodně otrlý jedinec. ;)</p>
<p>Jaký názor na symbiózu češtiny a angličtiny máte vy? Díky za komentář.</p>
Robert Dreslerhttp://www.blogger.com/profile/16401744220939465418noreply@blogger.com8tag:blogger.com,1999:blog-3408745507091232422.post-38924035762449703552014-04-26T08:41:00.000+02:002014-04-26T08:53:50.044+02:00Dopřejte vašemu kódu pořádnou revizi<div class="separator" style="clear: both; text-align: center;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgxRAT0J2t54yspWRuISSM1_k5Aif4fESPv7gnXHAiMf3Yj6ISKyHb3e1_i4gQmZWWbZf4W9z_wbLJ8jhLFA6DO5Kq1zBUQFwav3FJHZHEHcNFbdfFrFcae6W8bKpjFsMTsFlo3EdMmtcUG/s1600/714382108%5B1%5D.gif" style="border:none;box-shadow:none;vertical-align:bottom;horizontal-align:center;" /></div>
<p>Revize kódu (code review) patří mezi techniky, které mohou posunout vnitřní a vnější kvalitu vašeho systému do vyšší ligy. Musí se však dělat správně a efektivně. Revidování kódu může být časově náročné a od manažerů víme, že čas jsou peníze. Proto se systematické revidování používá především u projektů, kde je kvalita nadřazená brzkému dodání. Na druhou stranu, pokud jste někdy dělali na projektu, který se dostal do spirály smrti díky tragické kvalitě, jistě se shodneme na tom, že pojem “rychlý vývoj” je vždy relativní. Dobré revize v konečném důsledku čas a náklady na projekt snižují.</p>
<p>Revidovat kód lze mnoha způsoby. Ti co programují v páru, provádějí revizi kódu nepřetržitě již během jeho psaní. V ostatních případech jsou fáze psaní kódu a fáze revidování v čase odděleny. Čím více je revize opožděna za implementací, tím jsou ale případné nápravy komplikovanější. Revize se také liší stupněm formálnosti, rozsahem (např. pouze kritické části aplikace nebo všechno), počtem revidujících (jeden nebo celá skupina) a tím, zda-li je autor kódu přítomen nebo ne.</p>
<h2>Hlavní přínosy</h2>
<p>K čemu konkrétně jsou vlastně revize kódu dobré? Pomáhají nám v především v těchto záležitostech:
<ul>
<li>Ověřování splnění zadání.</li>
<li>Objevování chyb a případných rizik.</li>
<li>Zlepšování kvality návrhu.</li>
<li>Zlepšování čitelnosti kódu.</li>
<li>Zlepšování udržovatelnosti kódu.</li>
<li>Šíření znalostí a způsobu řešení problémů.</li>
<li>Zvyšování zastupitelnosti členů týmu.</li>
<li>Autor kódu dostává zpětnou vazbu ke svojí práci a díky ní se rychleji zlepšuje.</li>
</ul>
</p>
<p>Dobře revidovat kód je dovednost, kterou musíme neustále procvičovat a zlepšovat. Abychom zbytečně nemrhali časem, ale aby nám revize opravdu sloužily, musíme si pohlídat několik základních věcí. Sem s nimi ...</p>
<h2>Co mám vlastně revidovat?</h2>
<p>Co opravdu, ale opravdu nemáme jako programátoři rádi, jsou špatně zadané úkoly. Při implementaci už není prostor na neurčitost. Ta nás brzdí a blokuje. Psát jednoznačné a srozumitelné zadání je ctností dobrého analytika. “Chytře” zadaný úkol (mrkněte na <a href="http://www.mitvsehotovo.cz/2011/08/metoda-smart-jak-zadavat-ukoly-abyste-byli-spokojeni-s%C2%A0vysledkem/">SMART</a>) zvyšuje pravděpodobnost správného pochopení a odpovídající implementace a efektivní revize. Těžko ověříme splnění zadání, pokud je odbyté nebo nejasné. I jako revidující si vyžádejme upřesnění zadání, pokud je to potřeba. Revizí přebíráme stejnou zodpovědnost za úkol jako ten, kdo jej naimplementoval.</p>
<h2>Velký nebo malý úkol</h2>
<p><i>Revize malé změny - hodně připomínek, revize rozsáhlé změny - vypadá to dobře.</i></p>
<p>Pokud chceme mít revize opravdu smysluplné, dekomponujme problémy na pokud možno co nejmenší úkoly a ty revidujme odděleně. Implementace úkolu by neměla trvat více než jen několik hodin. Příliš rozsáhlé změny ukryjí defekty kódu, špatný design, bugy a jiné nedostatky. Snaha pochopit cizí kód (někdy i svůj) je vysoce náročná na soustředění a to jak víme není zadarmo. Po krátké době jsme unavení tak, že přepínáme na autopilota a pravděpodobnost přehlédnutí problému letí nahoru.</p>
<h2>Dohledatelný rozsah změny</h2>
<p>Rozsah revidované změny musí být jasně dohledatelný. Proto je vhodné, aby každý commit do repository byl logicky mapovaný právě na jeden úkol. Buildovací servery pak z takových commitů umí vyrobit ke každému úkolu přehledné reporty se zvýrazněním změn v jednotlivých souborech. Bez kvalitních podpůrných nástrojů a jejich vzájemné integrace se revize snadno změní ve zmatené prohlížení potenciálně změněných souborů.</p>
<h2>Dobrá kondice revizora</h2>
<p>Když se pořádně vyspíme, není pátek odpoledne a nemáme kofeinový deficit, pak máme nakročeno ke kvalitní revizi. Všechno je najednou mnohem jasnější. Prostě nemá smysl revidovat, když je člověk unavený. Je to podobné jako s programováním, jenom s tím rozdílem, že sice žádnou chybu nepřiděláme, ale ani žádnou neobjevíme.</p>
<h2>Potřebná úroveň znalostí</h2>
<p>Schopnosti a dovednosti revidujícího by neměly být výrazně nižší než schopnosti autora kódu. Mohlo by se pak totiž stát, že se mu zvolené řešení i kód bez výhrad líbí, přestože ve skutečnosti trpí mnoha nedostatky. A taková revize nemá žádný význam. Revidovat by proto měli ti zkušenější z týmu. Revidující by měl mít dobré znalosti použitých programovacích jazyků, frameworků, návrhových vzorů a principů, a mnoha dalších věcí. Jedním z přínosů revizí je právě to, že méně zkušení členové týmu získávají skrze zpětnou vazbu z revizí mnohem rychleji nové zkušenosti a tím se profesně zlepšují.</p>
<h2>Automatizujme</h2>
<p>Používejme nástroje pro statickou a dynamickou analýzu kódu, které se budou automatizovaně spouštět v rámci buildů hlídajících kvalitu. Co lze zkontrolovat automatizovaně to nemusíme revidovat. Šetřeme čas a soustřeďme se na záležitosti, které za nás programy nevyřeší.</p>
<h2>Optimalizujme workflow</h2>
<p>Pokud zatím revize nepoužíváte, zavádějte je opatrně. Hledejte ideální workflow, které bude kompatibilní s vašimi vývojovými procesy. Vyzkoušejte více variant a vyberte tu pravou. Až se vám revize dostanou pod kůži v rámci menšího týmu, teprve potom je zavádějte ve větším rozsahu. Revize kódu mají své opodstatnění jak v agilních, tak i především ve formálnějších metodikách. A není problém kombinovat revize více typů. Například my v rámci našeho projektu děláme některé úkoly v páru (okamžitá revize). Většinu úkolů ale revidujeme ad-post bez autora nebo při komplikovanějších věcech i s jeho přítomností. Velké implementační celky ještě revidujeme více formální revizí se softwarovým architektem zákazníka.</p>
<h2>Sociální aspekty revize</h2>
<p>S revizí kódu je to jako se ženou - ani nevíte jak a už jste v problémech. Je potřeba k ní přistupovat opatrně, lehce našlapovat a ve vyjadřování volit slovník gentlemana. Výstupem revizí by měly být připomínky, které zlepší kvalitu kódu a nezhorší vztahy v týmu. Případná kritika by měla být věcná, slušná a cílená na konkrétní problém. Žádné osobní útoky. Svojí nešikovností nebo dokonce špatným úmyslem, můžeme rozpoutat nepříjemné konflikty, které se projeví na fungování týmu. Velkým problémem je také nadřazený přístup zkušenějších vývojářů k těm méně zkušeným. Zdravě fungující tým by si měl s podobnými problémy poradit, ale i přesto buďte opatrní.</p>
<h2>Motivace odvádět kvalitní práci</h2>
<p>Dobře motivovaný tým chápe revize jako další prostředek ke zlepšení výsledků svojí práce. Na týmy s problematickou úrovní práce může mít zavedení revizí také velmi příznivý efekt. Programátoři, kteří kvalitu kódu do té doby příliš neřešili a v tichosti si něco bastlili, mají najednou nové starosti. Jejich kód začne někdo jiný číst a dokonce připomínkovat. Někdy i veřejně v rámci celého týmu. Dotyčný by musel být skutečný rebel, aby to v něm nehrklo a nezačal více přemýšlet nad tím co a jak píše. Najednou bude jeho práce srovnávána s kolegy a nikdo nechce patřit mezi ty, kteří jsou hodnoceni špatně. Opět pozor na sociální stránku zavádění revizí. Ať se vám v týmu nezačne příliš jiskřit.</p>
<h2>Jak vám to reviduje?</h2>
<p>Moje osobní zkušenosti s revizemi kódu jsou téměř výhradně pozitivní. Postupně jsme si vyladili vývojový proces tak, že díky revizím kódu těžíme z výše popsaných přínosů. Hodně jsme se vzájemně naučili. Jakmile někdo objeví nový trik, hned ho umí i revidující. Dost nám pomáhají revize se softwarovými architekty z Německa, kteří mají dlouholeté zkušenosti s vývojem jejich systému, do kterého aktuálně píšeme moduly. Jejich rady nás mnohokrát nasměrovaly k lepšímu řešení.</p>
<p>Za mě tedy revizím kódu jednoznačné ANO.</p>
<p>A jaké máte zkušenosti s revidováním kódu vy? Dobré nebo špatné?</p>Robert Dreslerhttp://www.blogger.com/profile/16401744220939465418noreply@blogger.com3tag:blogger.com,1999:blog-3408745507091232422.post-27950364591356065802014-01-19T08:23:00.000+01:002014-01-19T13:28:07.076+01:00Agilita v korporátním světě<p><b>
… aneb honba za nulovou chybovostí
</b></p>
<p>
<div class="separator" style="clear: both; text-align: center;">
<img border="0" height="200" width="632" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgZcxZxCI3pBn0T5Yl_xYjDlprg6VuI9tC5f6y8Z1NTowQ52Cpsy8Qp0NQFHY-1-bi3_1mbOXleu1IGQBaRXFV4B_lgggzerHzNyJqIstsG-Chn7HqppLzg8KwEROZ_TcvfgAqiW8eztAOQ/s1600/2009-02-21-agile-development-explained.png"
style="border:none;box-shadow:none;vertical-align:bottom;horizontal-align:center;" /></div>
</p>
<p>Aktuálně dělám na projektu, který je zajímavý z několika pohledů. Jedná se o software pro medical devices, kde jsou kladeny vysoké nároky na zajištění kvality. A neméně zajímavou skutečností je střet historicky vodopádového korporátního přístupu se sílícím vlivem agilních technik. Rád bych popsal zajímavé oblasti naší práce s důrazem na postupy, které nám pomáhají zajišťovat požadovanou kvalitu.</p>
<h2>Co vlastně děláme</h2>
<p>Na úvod stručně ke kontextu naší práce. Máme v Olomouci tříčlenný vývojový tým a pracujeme pro německou zdravotnickou korporaci Maquet. Konkrétně spolupracujeme se softwarovým oddělením na vývoji systému Tegris. Ten integruje ovládání různých zařízení používaných na operačním sále do jedné aplikace. Ovládat se dají například chytré operační stoly, speciální světla, HD kamery, endoskop a další. Systém má mnoho pokročilých funkcí pro nahrávání a streamování multisource videa. Zajišťuje také různé agendy potřebné při operacích. Jedná se o softwarové řešení dodávané spolu se speciálním hardware, kvůli vysokým nárokům na systém a požadavkům na mnoho speciálních karet a portů. Prostě být operován na sále s tak moderním vybavením musí být snem každého pacienta. Nebo raději ne. ;)</p>
<p>Prvním naším projektem byla integrace ovládání videokonferenčních systémů. Zjednodušeně řečeno jsme vyvíjeli modul, který umožňuje při operaci provádět videokonferenční hovory a ovládat je z Tegrisu.</p>
<p>Aktuálním druhým projektem je ovládání zařízení, která jsou připojená k nové hardwarové sběrnici. Na tu lze nyní připojit chytré světelné hlavy a HD kamery používané na operačním sále. Každé zařízení má své vlastní hardwarové ovládací panely. Nově tato zařízení půjdou ovládat také přes systém Tegris. A to je naším úkolem.</p>
<h2>Vývoj pro medical devices</h2>
<p>Vývoj software pro medical devices má svá specifika. Pokud chcete software dodávat do států EU, pak musíte být kompatibilní s hromadou direktiv sjednocených pod MDD. Jedná se o tak složitou byrokracii, že je jen pár lidí na světě, kteří ji mají kompletně nastudovanou a nechají si zaplatit slušný peníz za základní proškolení. Když chcete prodávat do USA, pak musíte být zase kompatibilní s direktivami vydávanými americkou FDA. Ve výsledku to vypadá tak, že potřebujete ve firmě alespoň jednoho člověka na plný pracovní úvazek, který zkoumá, co musí jednotlivé softwarové komponenty splňovat a jaké nároky jsou kladeny na samotný vývojový proces. Takovému člověku opravdu nezávidím. ;)</p>
<p>Pro nás to znamená, že veškeré vývojové fáze musí být standardizované. Všechny meziprodukty vývojového procesu (požadavky, návrh, kód, testovací případy, …) musí být revidovány někým nezúčastněným. Američané vyžadují navíc diskutabilní 100% pokrytí testy. Velký důraz je kladen na fázi akceptačního testování, testuje se v různých podmínkách (laboratorní, reálné) a před každým release. Veškerá snaha je cílena na dosažení co nejmenší chybovosti v produkci.</p>
<p>Medical devices jsou navíc klasifikovány do několika tříd podle závažnosti následků v případě poruchy takového zařízení. Třeba class I jsou zařízení, jejichž výpadek neohrožuje zdraví pacienta. Class III jsou naopak zařízení, jejichž špatná funkčnost může vést k těžkým následkům nebo smrti pacienta. Např. bylo by hodně nepříjemné, kdyby vynechával kardiostimulátor se speciálním software nebo kdyby se zasekl endoskop pro mozkové operace. Náš projekt řeší světla na operačním sále, ty jsou class II. Kdyby světla zhasla nechtěným zásahem obsluhy nebo z důvodu chyby software, asi by na operačním sále nebylo příliš veselo.</p>
<h2>Zadání a estimace projektu</h2>
<p>Součástí zadání je více jak stovka různě pracných funkcionálních a systémových požadavků na vyvíjený modul, podrobný popis komunikačního protokolu pro hardwarovou sběrnici a vizualizace UI. Z centrály jsme si dovezli reálné železo, které nám zabírá jednu stěnu naší malé kanceláře.</p>
<p>Bylo potřeba se seznámit s problémem, udělat si jednoduchý prototyp pro komunikaci se zařízeními a rychle dodat orientační estimaci, aby byl hlavní projekťák spokojený. Využili jsme agilní techniku odhadování v abstraktních story points. Poměřovali jsme nejdříve jednotlivé requirementy relativně podle předpokládané pracnosti a oceňovali je s využitím čísel od pana Fibonacciho - 1, 2, 3, 5, 8, 13, 21. Nakonec byl každý bod vynásoben bulharskou konstantou, která měla promítnout abstrakci do reálnějších člověkodnů.</p>
<h2>Specifikace architektury</h2>
<p>Jeden ze systémových požadavků si vynutil, aby většina business logiky ovládání (nízkoúrovňová komunikace, řízení přístupu, zjišťování stavu zařízení, synchronizace, apod.) byla oddělena od hlavního systému do samostatné aplikace. Tato aplikace musela být zpřístupněna jako služba, kterou mělo mít možnost využívat více klientů. Požadavek zásadně ovlivňoval architekturu řešení. Nakonec bylo potřeba navrhnout několik konceptů, ze kterých byl vybrán ten nejvhodnější.</p>
<p>Vítězný koncept se musel rozpracovat do několika různě abstraktních UML diagramů. Hlavní struktura systému je zachycena pomocí komponentového diagramu. Jednotlivé komponenty pak mají své poddiagramy stále ještě na úrovni poměrně abstraktních podkomponent. Specifikace musela obsahovat popis dalších technických aspektů zvoleného řešení.</p>
<p>Z pohledu agilních technik je použití UML vhodné pro lepší vzájemné porozumění při diskuzi o problému. Zároveň se ale nedoporučuje trávit kreslením diagramů příliš času. Důležitá zpětná vazba přichází totiž až ze samotné implementace. Čím je feedback pozdější, tím jsou případné změny dražší. S ohledem na typ našeho projektu jsme ale při realizaci nuceni používat UML poměrně často.</p>
<h2>Rozdělení do etap</h2>
<p>Rozplánovali jsme celý projekt na menší etapy, které vzdáleně připomínají agilní iterace. Liší se však zásadně tím, že nemají pevný časový rámec. Vybrané requirementy se musí vyřešit všechny. To je opět úlitba centrálnímu projektovému managementu. Nevýhodou je, že se celá etapa natahuje, nejde vrátit nevyřešené úkoly do backlogu a práce tolik neodsýpají. Paralelní práce na více etapách současně nám navíc moc nefungovaly. I tak ale považujeme rozdělení do etap za lepší přístup než čistě vodopádový model. Zpětnou vazbu o postupu prací dostáváme poměrně rychle a případné “vracečky” nejsou tak bolestivé. Etapa v ideálním případě trvá tak 15 pracovních dnů a prochází všemi níže popsanými fázemi.</p>
<h2>Analýza požadavků</h2>
<p>Rozdělení požadavků do etap bylo provedeno na začátku projektu. Přesun požadavků mezi etapami není příliš oblíbená činnost u centrálního managementu. Někdy ale není zbytí. Stává se poměrně často, že požadavek je potřeba upřesnit nebo zcela změnit. Pak je dobré, abychom měli “zákazníka” komunikačně co nejblíže. “Změnová řízení” jsou někdy otázkou hodin, jindy zase dnů. Někdy se musí chování upřesňovat s výrobním oddělením ve Francii.</p>
<p>Abychom si mohli naše domněnky rychle potvrdit nebo vyvrátit, pomáháme si prototypováním. Věříme, že s dostatkem informací o problému můžeme udělat lepší návrh. Navíc jsme záměrně naplánovali nejrizikovější požadavky do prvních etap realizace, kdy bylo prototypování nejvíc.</p>
<h2>Návrh</h2>
<p>Každá etapa má návrhovou fázi, kdy mapujeme řešené požadavky na use cases. Iterativním způsobem rozšiřujeme stávající design. Přidáváme (sub)komponenty a jejich vzájemné vztahy. Rozkreslujeme chování komponent do sekvenčních diagramů. Pokud je potřeba, pomůžeme si stavovým nebo aktivitním diagramem. Snažíme se držet na co nejvyšší nutné úrovni abstrakce. Až na úroveň diagramu tříd chodíme jen zřídka. Designové tasky většinou děláme ve dvojici. Je to pro nás efektivnější metoda, kdy nápady okamžitě diskutujeme, připomínkujeme a případně zahazujeme.</p>
<p>Vytvořený návrh musí projít přes design review, které se provádí za přítomnosti softwarového architekta z Německa. Někdy přímo v Německu a v poslední době se nám také daří dělat review i vzdáleně. Dostáváme zpětnou vazbu a rady od kolegů, kteří mají s podobnými systémy mnohem více zkušeností než my. Někdy sice s jejich argumenty úplně nesouhlasíme, ale to je v software development asi normální. Mnohdy je to bazírování na zdánlivých maličkostech, ale je v tom cítit německá preciznost, která se mi ve výsledku hodně líbí.</p>
<h2>Implementace</h2>
<p>Pokud se dostaneme přes design review, pak se celí natěšení vrháme do vlastní implementace. Snažíme se o TDD přístup, kterým zajišťujeme fázi návrhu na té nejnižší úrovni. Využíváme také Behavior-Driven Development techniku, která zahrnuje outside-in přístup, zlepšuje dokumentační aspekty testů a elegantně řeší problém jednoho assertu na test.</p>
<p>Jednotkové testy musí testovat třídy v izolaci. Používáme proto různé adaptéry abstrahující třídy frameworku, např. ISerialPortAdapter, ITcpClientAdapter, ITimerAdapter, ITaskAdapter. Asynchronní zpracování musí být v jednotkových testech převedeno na synchronní.</p>
<p>Hodně našich tříd musí být thread-safe. Snažíme se proto psát integrační testy, které testují třídy při paralelním přístupu z více vláken. Zatím nemáme příliš zkušeností se zátěžovým testováním, ale snažíme se to změnit.</p>
<p>Tegris je poměrně rozsáhlý systém, který má vysoké výkonnostní požadavky a jsou nutné značné optimalizace na straně implementace (vlákna, pooling, lazy). Error handling je samostatná kapitola, která nám zabrala jednu celou etapu. Systém se musí umět vzpamatovat sám z některých chybových stavů. A především chyba v jednom modulu nesmí ohrozit činnost systému jako celku.</p>
<p>Co se týče UI, tak děláme pouze dummy verzi, která je později nahrazena verzí finální dodávanou od designérské firmy. Systém je přizpůsoben pro dotykové ovládání. Myši nejsou na operačních sálech vítanou havětí. ;)</p>
<h2>Code review</h2>
<p>Code review si děláme nejdříve interně sami. Snažíme se, aby se vlastní implementace rozpadala na malé úkoly, které zaberou maximálně několik hodin práce. Takto granulované úkoly se ještě rozumně revidují. Ve větších úkolech se už revidující dost ztrácí. Review nám přináší velkou přidanou hodnotu. Občas odhalíme problém v implementaci nebo problematický design, připomínkujeme (ne)čistý kód, vysokou komplexitu, nešikovnou terminologii, apod. Velkou výhodou je to, že se v našem týmu udržuje povědomí o změnách, učíme se jeden od druhého dobré postupy a zvyšujeme vzájemnou zastupitelnost. Refaktoring není u nás sprostým slovem. Praktikujeme společné vlastnictví kódu. Bohužel se nám nedaří ve větší míře dělat pair-programming. Ale není všem dnům konec.</p>
<p>V závěru etapy je kód revidován kolegy z Neměcka. Dozvíme se zajímavé připomínky a dostaneme zpětnou vazbu od někoho, kdo se přímo na implementaci nepodílel. Za sebe opět hodnotím tento postup velice kladně.</p>
<p>Pokud dojde v rámci implementace ke změnám v designu, zanášíme je průběžně do UML modelu.</p>
<h2>Testovací případy</h2>
<p>Testovací případy (test cases) jsme si nejdříve psali sami, ale teď to rádi přenecháváme specialistům od našich západních sousedů. Každý požadavek musí být mapovaný na nějaký testovací případ. Testovací případy jsou zjednodušeně řečeno soupisy prerequisities, test steps a expected results. Měl by je psát někdo z QA oddělení a jsou prováděny ručně před každým vydáním aplikace. My si je musíme také projít před akceptací každé etapy.</p>
<p>Znám i zajímavější práci než psát testovací případy, ale na druhou stranu je to užitečný pohled na systém očima uživatele.</p>
<p>Zajímavostí je, že jsme v rámci projektu museli vyvinout poměrně komplexní simulační nástroj. Jedná se o chytrý fake, který se chová jako reálná zařízení. Umí simulovat chybové stavy, odebírat a přidávat zařízení za běhu a další situace, které by bylo drahé a někdy i velmi problematické navodit se skutečným zařízením. Tento simulační nástroj je určen na primární otestování testovacích případů před vlastním testováním v reálných podmínkách. Ani pro testery totiž není vždy možné se rychle dostat k drahému fyzickému zařízení.</p>
<h2>Infrastruktura</h2>
<p>Centrální projektový management používá pro podporu vývojového procesu systém Polarion, kterému se naše jednotka snaží spíše vyhýbat. ;) Náš tým si většinu času vystačí s nástrojem YouTrack, ve kterém uděláme rozpad celé etapy do malých tasků. Používáme něco na způsob Kanbanu se stavy Backlog, Ready to Dev, Dev in Progress, Ready for Review, Review in Progress, Finished. Každý task musí mít jasně daná akceptační kritéria. Žádné nekonkrétní, problematicky revidovatelné formulace.</p>
<p>Pro kreslení UML byl vybrán Enterprise Architect, který se nám podařilo postupně ochočit tak, aby pracoval pro nás a ne proti nám. Některé jeho features jsou ale opravdu pouze pro otrlé jedince.</p>
<p>Správu zdrojových kódů řešíme přes Mercurial, nad kterým kmitá TeamCity. Buildovací skripty jsou napsané v Rake (Ruby Make).</p>
<p>Pracujeme ve Visual Studio 2012 s ReSharper 7. Aplikace je napsaná v C# nad .Net 4.0, UI je ve WPF a služba je typu WCF. Jako testovací framework je využit NUnit a pro mockování RhinoMocks. Pokrytí testy měříme přes dotCover. Kódovací standardy nám hlídá policajt StyleCop a jiný policajt FxCop zase provádí statickou analýzu kódu.</p>
<h2>Pár slov na závěr</h2>
<p>Ještě nevíme, jak celý projekt dopadne. Netušíme, jaká bude výsledná chybovost v produkci. Doufáme však, že minimální. Děláme pro to maximum. Snažíme se využívat všech nám známých technik pro zajištění kvality. Získáváme tím už od začátku větší pocit jistoty a práce není stresující. Navíc je docela fajn pracovat pro firmu, která má v Programming Guidelines jako první uvedeno pravidlo:</p>
<p><i>“It is more important to write correct and maintainable code than supposedly quickly programmed code.”</i></p>
<p>Můžete se mrknout na komerční videa představující systém <a href="http://www.youtube.com/watch?v=yUoljipjmQs">Tegris</a> a novou generaci světel <a href="http://www.youtube.com/watch?v=NREss955fUw">Volista</a>.</p>Robert Dreslerhttp://www.blogger.com/profile/16401744220939465418noreply@blogger.com1tag:blogger.com,1999:blog-3408745507091232422.post-25897754696155167712014-01-12T16:00:00.000+01:002014-01-12T16:00:13.626+01:00Proč vývojáři odcházejí z IT firem<p>
<div class="separator" style="clear: both; text-align: center;"><img border="0" height="130" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEi4v7D0frImWSkjZfPrV3qMstM_4pHUc9YTHEoluL5iriKPmcXonk7A9mDzCBgc3LGKPnPyOhthwz-SV2l1ROQUxMAfWw2B-J9Slt_kO-cVNRmYek67kfFwl0DAtNG2zjoAV48qPADPIkcS/s1600/iquit.png" style="border:none;box-shadow:none;vertical-align:bottom;horizontal-align:center;" /></div>
</p>
<p>Brzy tomu bude rok, co jsem odešel z IT firmy, ve které jsem pracoval 13 let. Bylo to pro mě dost zásadní rozhodnutí a proto jsem si chtěl své důvody pro odchod porovnat s názory ostatních “nespokojenců”. Poptal jsem se komunity na devel.cz, <a href="http://devel.cz/otazka/duvody-pro-odchod-z-it-firmy">jaké (by) byly jejich důvody pro odchod z firmy</a>. Díky Jirkovi Kneslovi jsem také mohl nahlédnout do výsledků ankety o programátorské práci snů. </p>
<p>Nakonec vznikl tento příspěvek jako kompendium názorů několika desítek lidí z IT a jejich pracovních potřeb. Mohl by se stát checklistem pro ty, kteří programátory zaměstnávají a chtějí si je i do budoucna udržet.</p>
<h2>Dvě skupiny vývojářů</h2>
<p>Zřejmě má smysl rozdělit vývojáře do dvou logických skupin. Do té první by patřili lidé, kteří do práce chodí proto, aby něco vydělali a nemají potřebu se neustále učit nové věci. Ve své práci používají několik technologií a jazyků, které mají zvládnuté buď dobře nebo špatně. Mají každopádně své zaběhlé pracovní postupy a tyto postupy neradi mění. Mají pouze nonIT koníčky a doma počítač zapínají spíš pro zábavu než kvůli práci. Jsou to programátoři <b>usedlíci</b>.</p>
<p>Do druhé skupiny patří všichni ti, pro které je programováni víc než jen práce. Je to jejich vášeň a návyková droga zároveň. Nová technologie, nový jazyk nebo nový projekt v jejich těle vyvolávají příjemné chvění. Chtějí klouzat po technologické vlně a pořád se zlepšovat. Jejich počítače pracuji na plný výkon v práci i doma. Takoví programátoři jsou nadšení <b>dobyvatelé</b> nových technologií.</p>
<p>Každá skupina programátorů má své místo v oboru a je potřeba je obě respektovat a jejich případných předností využívat. Od práce, kterou jsou ochotni dělat usedlíci, by dobyvatelé rychle utekli. Naopak šikovní dobyvatelé obvykle zvládají novátorské úkoly s mnohem větší elegancí.</p>
<h2>Atraktivita práce</h2>
<p>Pracovní stereotyp působí jako infekce na motivaci a pracovní výkonnost. Programátorskou senilitu zajistí práce na dlouhodobém a nezajímavém projektu, ve kterém se navíc používají zastaralé technologie. Úplné peklo je pak udržovat legacy systém, jehož technologický dluh se rovná dvacetileté hypotéce. Dobyvatelé preferují raději pestrost krátkodobých projektů než pracovní agónii těch dlouhodobých. Firmy by měly být aktivní a hledat technologické výzvy pro nové projekty, díky kterým by využívaly a zvyšovaly potenciál svých lidí.</p>
<h2>Profesní růst</h2>
<p>Atraktivní pracovní náplň zřejmě podněcuje profesní růst. Firmy by navíc měly investovat do smysluplného školení lidí a podporovat firemní kulturu sdílení znalostí. Nabízet nějakou formu innovation time. Akceptovat, promýšlet a případně realizovat nápady na zlepšení od všech členů týmu. Skvělé je mít v blízkosti člověka, který v něčem vyniká a inspiruje ostatní. Firma by také měla vytvářet zdravou úroveň pracovního stresu, která napomáhá udržovat pracovní tempo a nutí lidi ke zlepšování. Na pocit sebeuspokojení už doplatilo hodně lidí i neexistujících firem.</p>
<h2>Smysl práce</h2>
<p>Dělat na projektu, kterému člověk nevěří, je demotivující. Rádi děláme práci, která přináší business value a na konci které najdeme spokojené uživatele. Ten pocit je někdy lepší než připsání výplaty nebo proplacení faktury na účet.</p>
<p>Zaručeným znechucovadlem práce je přeprocesované korporátní prostředí, ve kterém trávíte více času na poradách a řešením byrokracie, než samotnou činností, která vás baví.</p>
<h2>Kvalita práce</h2>
<p>Za svoji práci se nechceme stydět. Rádi bychom dodali produkt, který má vysokou vnitřní i vnější kvalitu. K životu programátora to sice patří, ale trávit příliš mnoho času bug huntingem je otrava. Pokud je produkt dlouhodobě ve špatném stavu, frustrace a stres se zvyšuje.</p>
<p>Je potěšující, kolik lidí z ankety preferuje prostředí, ve kterém se pracuje agilně, píšou se testy, dodržují se pravidla čistého kódu, zásady dobrého návrhu, apod. Na základě svých zkušeností totiž zjistili, že práce v takovém prostředí je baví a působí pozitivně na jejich nervový systém.</p>
<h2>Mezilidské vztahy</h2>
<p>Nakonec stejně nejčastějším důvodem pro odchod z firmy bývají samotní lidé, kteří znepříjemňují pracovní dobu. Ztráta důvěry k nadřízenému, nevhodné chování kolegů, nerespektování osobnosti a názorů, ponižování nebo osobní antipatie. Čím větší firma, tím větší procento “zmrdovosti”. Hodně programátorů proto z těchto důvodů preferuje menší firmy nebo volnonožství a práci na kontrakt.</p>
<p>Dobrotu také nedělá mix dobyvatelů a usedlíků v jednom vývojovém týmu. Mentální založení obou skupin je natolik odlišné, že nebudou mít zřejmě příliš společných tmelících prvků.</p>
<p>Rádi pracujeme s lidmi, se kterými jsme zároveň přátelé. Nemáme s nimi komunikační problém a máme naopak vzájemnou důvěru. A taková přátelství se mohou vytvořit třeba na teambuildingových akcích nebo při párovém programování.</p>
<h2>Projektové řízení</h2>
<p>Špatné projektové vedení může demoralizovat tým a úplně otrávit práci. Snem programátorů jsou firmy typu flat organization a self-managing týmy. Hierarchie není vrstvená a nešéfují lidé odtržení od reality skutečné práce. Lídry týmů jsou ti pracovně nejschopnější, kteří pracují po většinu času s ostatními.</p>
<p>Programátoři nemají rádi přílišný stres před dokončením projektu. Proto nemají rádi ani vodopádové vývojové procesy. Preferují naopak agilní postupy, při kterých dostávají informaci o stavu projektu ihned a během celého trvání projektu. Práce se tak dají lépe řídit a ve výsledku nejsou tolik stresující.</p>
<h2>Férovost firmy</h2>
<p>Férová firma dodržuje zákony, platí licenční poplatky, nepodplácí při výběrových řízeních, nevykazuje neprováděnou práci, nedodává odfláknuté produkty, nezneužívá evropské fondy, komunikuje otevřeně, platí včas závazky vůči zaměstnancům, atd. Férové firmě se dá prostě věřit. Férová firma přitahuje férové zaměstnance a vztahy se zákazníky zakládá na vzájemné důvěře. Naopak, nedá se očekávat, že v neférové firmě budou lidé spokojení.</p>
<h2>Pracovní podmínky</h2>
<p>Mít dobrý kávovar je v IT základ. Firmy nesmí zapomínat pravidelně upgradovat HW tak, aby nebyl slabým místem vývojářovy činnosti. Měl by mít k dispozici dobré SW nástroje, aby jeho práce byla efektivní a ne stereotypní. Pro dlouhodobý dobrý zdravotní stav programátora je nesmírně důležitá kvalitní židle, (pokud možno polohovací) stůl, ergonomický monitor, klávesnice, myš, apod.</p>
<p>Problém je mnohdy náročné dojíždění. Stále více lidí hledá kombinovaný home-office režim. Pak je však potřeba vyřešit specifika remote komunikace a organizace práce. Zpestřením pracovní rutiny může být občasné digitální nomádství a vzdálená práce z nějakého atraktivního místa.</p>
<h2>Peníze</h2>
<p>Peníze si možná nezaslouží být jako poslední téma. Ale věřte nebo ne, pro mnoho programátorů dobyvatelů není finanční ohodnocení v TOP3 jejich seznamu nejdůležitějších pracovních požadavků. Ten, kdo již dříve měnil práci z nefinančních důvodů, tomu jistě rozumí. Být totiž dobře zajištěný, ale přitom nespokojený programátor, není žádné terno.</p>
<p>Co si o tom myslíte vy?</p>Robert Dreslerhttp://www.blogger.com/profile/16401744220939465418noreply@blogger.com15tag:blogger.com,1999:blog-3408745507091232422.post-1347693738922639772014-01-03T20:35:00.000+01:002014-01-04T08:37:16.521+01:00Fenomén Coderetreat<style type="text/css">
.participant_cite { font-style : italic; margin-bottom : 10px; width : 95%; margin-left : auto; margin-right : auto; }
</style>
<p><b>
… aneb Den, který může změnit váš profesní život
</b></p>
<p>V sobotu 14. prosince 2013 proběhl další díl <a href="http://globalday.coderetreat.org/">Global Day of Coderetreat</a>. Tentokrát na více než <a href="http://goo.gl/maps/41wL7">165 místech po celém světě</a>. Možná by vás mohlo zajímat, proč se tahle akce stává rok od roku populárnější. Pojďme se na Coderetreat podívat očima účastníků akce, která proběhla na Vsetíně.</p>
<h2>První nakouknutí do říše testů</h2>
<div class="participant_cite">David: Jsem děsně rád za tuhle akci, že jsem prozřel, jak se vlastně píšou testy.</div>
<p>Akce je určena pro všechny programátory, kteří se chtějí naučit nebo se zdokonalit v technikách agilního vývoje. Důraz je kladen především na Test-Driven Development. Největší mentální dopad má akce samozřejmě na nováčky, pro které je to tak trochu výlet do říše za zrcadlem. Ovšem i ti zkušenější se vždy dozví něco nového a mohou si třeba vyzkoušet psaní testů v jiném programovacím jazyce.</p>
<h2>Test-First jako mentální blok</h2>
<div class="participant_cite">Zdenek: Již dříve jsem se naučil přemýšlet o psaní kódu tak, aby byl testovatelný. Dnes jsem si ale potvrdil, že mám velký mentální blok přemýšlet nejdřív o psaní testu a teprve potom o kódu.</div>
<div class="participant_cite">Helena: Aha, takže takhle se o tom má přemejšlet. Teď jsem konečně pochopila podstatu TDD.</div>
<p>Věřím, že velké procento SW projektů v dnešní době už má ve svých postupech psaní testů. Je ovšem rozdíl psát testy po implementaci a nebo ještě před ní. Začít nejdříve od testů je pro mnoho lidí velkou psychickou bariérou. Během celého dne se pokoušíme tuto bariéru postupně bourat a porozumět výhodám Test-First přístupu.</p>
<h2>Návrh a efektivnější implementace pomocí Test-First</h2>
<div class="participant_cite">Zdenek: Nejzajímavější částí bylo specifikování požadavků přes testy.</div>
<div class="participant_cite">Honza: Psát testy jako první je pro mě velký mentální obrat a může mi pomoci vyhnout se snaze o sice perfektní, ale mnohdy zbytečnou dopřednou implementaci.</div>
<p>Test-First přístup nás nutí nejdříve přemýšlet nad tím, co potřebujeme implementovat a pak teprve jak implementovat. Psaní testu je fáze návrhu, kdy dostáváme okamžitou zpětnou vazbu o testovatelnosti kódu. Implementujeme pouze to, co si vyžadují testy. Pěkně inkrementálně po malých krůčcích. Žádné zbytečné věci navíc, které aktuálně nepotřebujeme.</p>
<h2>Párové programování</h2>
<div class="participant_cite">Lenka: Líbilo se mi párové programování. Víc hlav víc ví a dovedu si představit, že bychom ho ve firmě používali.</div>
<div class="participant_cite">Sváťa: Úplně super bylo párové programování. I kdyby ta dvojice problém nevyřešila lépe, tak budou mít v budoucnu oba o problému mnohem větší povědomí.</div>
<div class="participant_cite">Jarda: Dnešní zkušenost mě utvrzuje v tom, že párové programování by se mělo určitě více využívat v praxi.</div>
<div class="participant_cite">Libor: Viděl jsem, jak Kuba perfektně ovládá svoje vývojové prostředí, jedna klávesová zkratka za druhou.</div>
<div class="participant_cite">Zdenek: Po pěti sešnách jsem si myslel, že už mě nic nepřekvapí. Ale tady kolega mi i v té poslední ukázal zcela jiný přístup, který byl téměř geniální.</div>
<p>Je u vás běžné, že přijdete za kolegou v práci a začnete řešit problém společně? Nebo jste spíše týmem individualistů? Během Coderetreatu pracujete v páru neustále. A každý blok s jiným parťákem. Zpočátku možná trochu nezvyklá a tudíž nepříjemná záležitost, ale postupem času se vám to začne líbit. Ztrácíte zábrany, učíte se komunikovat o problému, hledáte společně řešení, díváte se na problém optikou kolegy, poznávat jeho pracovní postupy. A tím vším se učíte nové věci, zlepšujete se a jste nuceni ze sebe dostat to nejlepší.</p>
<h2>Příjemná atmosféra na prvním místě</h2>
<div class="participant_cite">Marek: Byla zde velice přátelská atmosféra. To jsem u ajťáků nečekal. :)</div>
Vytvoření příjemné atmosféry je nejdůležitějším předpokladem pro úspěch celé akce. Pokud se lidé dokáží uvolnit, užijí si i ta nejnáročnější cvičení. Mezi účastníky jsou různě pokročilí programátoři, přesto byste nenašli žádné náznaky nadřazenosti nebo posměchu. Všichni si chceme den pořádně užít, naučit se něco nového a poznat nové lidi. Koncept celé akce je navržen tak, aby k dosažení těchto cílů maximálně napomáhal.</p>
<h2>Skrze kód spolu komunikujeme</h2>
<div class="participant_cite">Tomáš: Když si myslím, že je něco naprosto jasné, tak se to těm ostatním vůbec jasné zdát nemusí.</div>
<div class="participant_cite">Zdenek: U ping-pongu jsem si uvědomil, jak dobré je přesně se vyjadřovat. Kolega totiž dělal vše úplně doslova.</div>
<p>Nejoblíbenější aktivitou je obvykle ping-pong, při kterém ještě navíc vypínáme zvuk. Jeden z dvojice píše test a druhý musí napsat implementaci, která zaručí procházení testu. Nemluví se, proto je velmi důležité, aby bylo pouze z kódu zřejmé, co je záměrem testu. Správné názvy testů, principy čistého kódu a důraz na jednoduchost vyústí v kód, který je dobře čitelný a tím pádem i dobře pochopitelný a udržovatelný.</p>
<h2>Za hranicí komfortní zóny</h2>
<div class="participant_cite">Libor: Některé omezující požadavky mně opravdu zamotaly hlavu.</div>
<div class="participant_cite">Zdenek: Do příště se musím naučit UML, protože mám trochu hokej ve vazbách v class diagramech.</div>
<div class="participant_cite">Jarda: Zase jsem objevil své slabé stránky a mám určitě o čem přemýšlet.</div>
<div class="participant_cite">Marek: Naučím se pořádně klávesové zkratky svého IDE.</div>
<p>Všichni se na akci přicházíme naučit něco nového a jako bonus obdržíme zpětnou vazbu o tom, co nám ve skutečnosti moc nejde. Dělej hlavně to, co ti nejde (pokud to ovšem potřebuješ) neboli dostávej se mimo svoji komfortní bublinu tak často, jak jen to jde. Budeš se učit mnohem rychleji. </p>
<h2>Přenášení znalostí do praxe</h2>
<div class="participant_cite">Jarda: Už jen kdybychom u nás ve firmě zavedli psaní testů, tak by to byl velký pokrok.</div>
<div class="participant_cite">Roman: Z minulého CR jsem si odnesl spoustu věcí a aplikoval jsem je ve své praxi. Začal jsem psát mnohem více testy. Bez testů si dnes už některé věci vůbec nedokážu představit.</div>
<p>Coderetreat není pouze celodenní bojová hra, která skončí po poslední session. Je to především začátek procesu, během kterého se začnete na váš svět vývoje software dívat jinýma očima. Možná pak vyzkoušíte nějaké nové věci na reálných projektech a možná jednu sobotu zúročíte na další roky efektivnější práce.</p>
<h2>Závěrem</h2>
<p>Pokud se jednou rozhodnete, že se nějakého Coderetreatu zúčastníte, budu vám držet palce, aby vaše hodnocení vypadalo třeba nějak takto:
<div class="participant_cite">Zdenek: Dnes jsem si uvědomil, jakou pozitivní energií mě celá ta akce nabila, kolik nových témat a podnětů jsem si odnesl a kolik nových kamarádů jsem poznal.</div>
</p>
<p>
A tady je naše celá parta ve slušivých trikotech: <br/>
<div class="separator" style="clear: both; text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjjjFcJwYcxo2ZwcGH7het2x7Vu5KKH9ouZk42mGw7juj8SZkG4UDS5E8IkNqXnIC60Ia1MtXJdsboOv5yI13dIsZWgogeScyf4wUlatrJ47T8-K-awEA1L4kK_1eoXrtbBlmkj5NgqMBmk/s1600/spolecna.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjjjFcJwYcxo2ZwcGH7het2x7Vu5KKH9ouZk42mGw7juj8SZkG4UDS5E8IkNqXnIC60Ia1MtXJdsboOv5yI13dIsZWgogeScyf4wUlatrJ47T8-K-awEA1L4kK_1eoXrtbBlmkj5NgqMBmk/s320/spolecna.png" /></a></div>
</p>
<h2>Video - závěrečná retrospektiva</h2>
<p>
Na závěr akce jsou všichni účastníci požádáni, aby volně odpověděli na otázky:
<ul>
<li>Co jste se dnes naučili nového?</li>
<li>Bylo něco, co vás dnes překvapilo?</li>
<li>Bude něco, co začnete v budoucnu dělat jinak?</li>
</ul>
</p>
<p>Pokud si chcete zasadit výše uvedené výroky do širšího kontextu, určitě mrkněte na tohle video:</p>
<p><iframe width="560" height="315" src="//www.youtube.com/embed/Z11xxjWP2nk?rel=0" frameborder="0" allowfullscreen></iframe></p>
<h2>Poděkování</h2>
<p>Chtěl bych poděkovat:
<ul>
<li>Hlavnímu partnerovi, firmě <a href="http://gmchk.cz/">GMC Software Technology</a> za finanční pokrytí akce.</li>
<li>Partnerským firmám <a href="http://www.sabo-gmbh.de/en/">Sabo GmbH</a> a <a href="http://www.vrvs.cz/">Rozváděče Vsetín, s.r.o.</a> za dárky pro účastníky.</li>
<li><a href="https://twitter.com/jaroslavurban">Jardovi Urbanovi</a> za spoluorganizaci celé akce.</li>
<li><a href="https://twitter.com/ZdenekRejda">Zdenkovi Rejdovi</a> za pomoc s přípravou triček a nadšením pro akci.</li>
<li><a href="https://twitter.com/janbednarik">Honzovi Bednaříkovi</a> za zajištění videodokumentace.</li>
<li>Všem ostatním, kteří nám pomáhali a všem zúčastněným za vytvoření super atmosféry.</li>
</ul>
</p>
<p>Nashledanou příště …</p>
<h2>Odkazy</h2>
<p>Pokud se chcete o formátu Coderetreat dozvědět více, můžete také navštívit:
<ul>
<li><a href="http://coderetreat.cz/">coderetreat.cz</a></li>
<li><a href="http://coderetreat.org/">coderetreat.org</a></li>
<li><a href="http://www.robertdresler.cz/2012/12/1-vsetinsky-code-retreat.html">Global Day of Coderetreat 2012 na Vsetíně</a></li>
</ul>
</p>Robert Dreslerhttp://www.blogger.com/profile/16401744220939465418noreply@blogger.com0tag:blogger.com,1999:blog-3408745507091232422.post-60248068184695360832013-09-23T06:35:00.000+02:002013-09-23T06:35:17.745+02:00Snižování rizikovosti softwarových projektů<p><b>
… aneb díky zpětné vazbě rychleji kupředu
</b></p>
<div class="separator" style="clear: both; text-align: center;">
<img src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhhaqswTazHUB8N0nN_QyDKiXpDahjnvKFAcnVqATu9GjGi_BjzGhCtYVTgKkb7TIVRhzEZrNnywfgeLv3Bq0rl5RR8F9WHSI3PfAylJJ1LpMRVT9oKQfm_OMADDIRH2tQj7BXAA7PrSi07/s320/TalkingBubbles.png"
style="border:none;box-shadow:none;vertical-align:bottom;horizontal-align:center;" height="40pt" />
</div>
<p>
<i>
Děláme to dobře? Bude se zákazníkovi a uživatelům výsledek líbit? Máme hodně nebo málo bugů? Stíháme harmonogram projektu? Jaká jsou v projektu největší rizika? Ustojí architektura systému reálnou zátěž? ...
</i>
</p>
<p>Množství neúspěšných softwarových projektů je pro nás varováním, abychom byli obezřetní a neustále hledali způsoby, jak rizikovost vývoje software snižovat. Důsledkem neúspěšného zvládání rizik mohou být obrovské finanční ztráty při produkování nestabilního software. Za dobrý výsledek se nedá považovat ani software rigidně splňující původní požadavky, avšak uživatelsky nepřátelským způsobem. A v mnoha případech dokonce projekty umírají ještě dříve, než se dostane prvotní verze mezi reálné uživatele.
</p>
<p>Jsem přesvědčen, že kouzelnou instancí úspěšných projektů je mimo jiné i kvalitní zpětná vazba. Je nutné, abychom byli schopni zpětnou vazbu získávat v co nejkratší době a nezkreslenou a to navíc po celou dobu trvání projektu. Díky zpětné vazbě lépe držíme správný směr a rychleji řídíme projekt směrem k úspěšnému výsledku. Dále popisuji vybrané techniky, které nám pomohou tuto drahocennou komoditu lépe získávat.
</p>
<h2>Jednotkové testy (Unit Tests)</h2>
<div class="separator" style="clear: both; text-align: center;">
<img src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgaaDREgu6XrRZE1R2heGSEPKYq2dlDWYZzj_hYDNo9MYUBcittfF8xML81j1AcbDsRyGK4kk1hinBSvhIHigbMekfJZknpLjkwi0ZpYiylykxdsHLkK_-dBT0CcFKFylCmdwXpT7U48ZFa/s1600/unittests.png" style="border:none;box-shadow:none;vertical-align:bottom;horizontal-align:center;"
height="180pt" />
</div>
<p>Zdrojový kód je živý organismus, který prochází neustálým vývojem a změnami. Má-li být projekt úspěšný, je kvalitně navržený zdrojový kód s minimální chybovostí naprosto esenciálním požadavkem. Psaní jednotkových testů je technikou, která nám dává do rukou prostředek pro získávání zpětné vazby o stavu kódu v řádech desítek sekund.
</p>
<p>Zpětná vazba je dvojího typu. Dokážeme ověřit, zda-li kód opravdu dělá to, co od něj očekáváme - na co není napsaný test, to jako by v systému ani neexistovalo. Za druhé, dostáváme důležitou informaci o kvalitě návrhu tříd a potažmo celého systému. Na oba indikátory bychom měli být schopni rychle reagovat a problémy řešit.
</p>
<p>Programování bez psaní jednotkových testů je mizerná loterie, ve které se obvykle prohrává. Vede k objevování chyb složitějším způsobem a v pozdějších fázích vývoje. Vkrádá se nejistota a strach zasahovat do existujícího kódu, který není pokrytý testy. Téměř se nerefaktoruje, vznikají duplicity a logickým vyústěním je zvyšování nákladů na celý projekt. Bez testů není možné aplikovat některé z dále popsaných technik.
</p>
<p>Podobně jako jednotkové testy, potřebuje náš projekt testy integrační. Jedná se o kategorii testů, které prověřují vzájemnou spolupráci více reálných tříd v požadovaných scénářích.
</p>
<h2>Průběžná integrace (Continuous Integration)</h2>
<div class="separator" style="clear: both; text-align: center;">
<img src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjJD7KWLDXYYTbLSGtXKIDzAhnKP8Y12m4eFitipvQsNkF3OC-3VMzu0FzWXuQj4su3vJtNJS4U6YDrcu6LgGd1RIGlsWaityfWuTkRbrcx-PC9K6_fYVMgUg-67NMgG9utdOwXBopc5-Vm/s1600/ci.png" style="border:none;box-shadow:none;vertical-align:bottom;horizontal-align:center;"
height="180pt" />
</div>
<p>Podívejme se na práci programátora z perspektivy celého vývojového týmu. Jeho chyby totiž mohou nepříznivě ovlivnit zbytek týmu. Nesoustředěný, spěchající nebo unavený kodér promítne změny na server a odchází domů (v horším případě vypíná telefon a odjíždí na třítýdenní zahraniční dovolenou). Nevšimnul si ale, že aplikace nejde zkompilovat nebo že rozbořil pár jednotkových testů. Jiný člen týmu si vezme změny ze serveru a v ten okamžik má problémy i on. Nezkompiluje, prohodí pár jadrných slov (které ve slovníku spisovné češtiny nenajdeme) a začne hledat pachatele. Nakonec se situace nějak vyřeší, ale zpomalení lidí a někdy celého týmu je vždy nepříjemné a drahé.
</p>
<p>Řešením je zavedení techniky průběžné integrace. Jedná se o kontrolní mechanismus, který po každém promítnutí změn na server spustí posloupnost ověřovacích kroků. Běžně se provádí kompilace celého projektu, spouští se jednotkové testy, hlídají se pravidla kladená na formátování kódu, provádí se statická analýza kódu, apod. V řádu několika minut dostává programátor, který změny propagoval na server, zpětnou vazbu o tom, že jeho balík změn je nebo není problematický. V zájmu celého týmu by měl na případný problém okamžitě reagovat a uvést verzi na serveru do korektního stavu. Nebrzdit zbytek týmu musí být nejvyšší prioritou.
</p>
<p>Týmy, které nemají rozjetý CI mechanismus, se často dostávají do záseků. Reakce na problémy se prodlužují. Dohledávání příčin je složité, protože není vždy snadné určit, který balík změn problém způsobil. Každá propagace změn na server je provázena lechtivým pocitem v podbřišku. Strach a nejistota dlouhodobě paralyzují práci týmu. Není také zřejmé, zda-li je aktuální serverová verze v dobrém stavu a tedy nasaditelná např. do testovacího prostředí.
</p>
<h2>Revize (Reviews)</h2>
<div class="separator" style="clear: both; text-align: center;">
<img src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhRLlvomzHkpnieaiE7mTaPZKnj4PuOFPqhWRafyBKb4xjkBxIq-ts8r9WbdAHlKylHkZrT8v9e78t4d4NkzbpqkyTYr4b3H5viJFTRQ3XGupGkO9xVYYA0a15vhUw9aMSUxFlVcrNYGUdp/s1600/reviews.png" style="border:none;box-shadow:none;vertical-align:bottom;horizontal-align:center;"
height="180pt" />
</div>
<p>Často nedoceňovanou technikou je vzájemné revidování práce. Revidovat můžeme specifikaci požadavků, návrh řešení, zdrojový kód nebo jiné výstupy vaší práce. Odpůrci argumentují vysokou časovou náročností a tedy malou ROI. Pokud to však myslíme s kvalitou aplikace vážně, je tato technika nepostradatelná. Téměř vždy je pohled na řešený problém očima někoho jiného užitečný. Např. při revizi kódu můžeme připomínkovat použitý algoritmus, řešit čitelnost kódu, objevit chyby nebo jiná potenciálně problematická místa. Revizemi si členové týmu vzájemně předávají zkušenosti, učí se a zvyšují bus-factor (zastupitelnost) vývoje částí aplikace.
</p>
<p>Kdy a v jakém rozsahu je vhodné provádět revize? Vždy, když je dokončen úkol menšího rozsahu. Ideálně práce, která se vejde do jednoho dne. V méně zkušených týmech mohou být revize delší - objeví se více připomínek. Např. v našem týmu je poměr času strávený prací a její revizí asi 10 : 1. Poměr kolísá v závislosti na složitosti úkolu a aktuální míře “hnidopišství” revizora. Preferujeme spíše méně formální revize, buď za účasti programátora (při složitějších věcech, kde je vhodný vysvětlující komentář) nebo bez něj.
</p>
<h2>Párové programování (Pair Programming)</h2>
<div class="separator" style="clear: both; text-align: center;">
<img src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEg_bp7u5wZSKkpRcTdA3uWl6fTCNVfQwb4B41wmFbt1Tt-fS7YjgfdkFNCab1b8jfgTJU7Ccb36LFmFIC-MR0S_EioeSi0IcyBHX6qOesBVLnB533FfChvRaCBvwdDTI9HNy_AiB83LKNqG/s1600/pp.png" style="border:none;box-shadow:none;vertical-align:bottom;horizontal-align:center;"
height="180pt" />
</div>
<p>
Některé věci se lépe dělají ve dvou - třeba programování. Práce v páru je kontinuální diskuze nad problémem a zvoleným řešením. Zpětná vazba je okamžitá. Dochází k vzájemnému revidování a téměř s určitostí bude výsledek společné práce vždy kvalitnější než při individuálním přístupu. Revidování je elementární činností této techniky a platí pro něj všechna pozitiva popsaná výše.
</p>
<p>Ne všechny týmy mají vhodné prostředí pro aplikování této techniky. Efektivita je přímo úměrná “sociální kompatibilitě” členů týmu. Někdo je natolik introverdní, že práce ve dvojici jej stresuje a nedokáže ze sebe dostat to nejlepší. Také ne každý úkol je vhodné dělat ve dvojici. Obecně se dá říci, že čím je úkol složitější, tím je párování užitečnější.
<h2>Zákazník na pracovišti (On Site Customer)</h2>
<div class="separator" style="clear: both; text-align: center;">
<img src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhxyKpD5z_J586jWiJL0Rgy5bVPeyjjWULckzQvroC7Y8oElHaWyR5xyWV8ge8p1WiuFQjMojclpGNSf5mkdxLZe4t5wqY2LylXARDgqkVCiheRN2FjJKO_KDaj6SudZ8mtpf2vIFhWMWee/s1600/osc.png" style="border:none;box-shadow:none;vertical-align:bottom;horizontal-align:center;"
height="180pt" />
</div>
<p>Zákazník přesně ví co chce, co nejpodrobněji nadefinuje požadavky na systém, udělá se analýza, pak estimace, podepíše se smlouva. Vývojový tým dostane zadání, několik měsíců na něm dělá bez asistence zákazníka a poté, jako mávnutím kouzelného proutku, představí zadavateli funkční a skvělé řešení. … Tak a teď tu o Červené karkulce.
</p>
<p>Dobrá tedy, domluvíme raději pravidelné týdenní pracovní porady se zástupcem zadavatele. Lepší, ale stále to není ono. Co takhle mít schopného člověka od zákazníka k dispozici kdykoliv? Mít možnost mu zavolat nebo se s ním sejít ihned, jak si to situace vyžádá? Mnohem lepší. Nebo raději, kdyby fyzicky seděl s týmem v jedné místnosti? Ideální.
<p>Zákazník nám platí a pouze na jeho hodnocení záleží, zda-li bude náš projekt úspěšný. Na začátku vývoje obvykle nemáme dostatečně jasnou představu o tom, jak by měl výsledek vypadat. A i když máme, tak se v průběhu určitě změní. To je zákon softwarového vývoje. Zafixovat požadavky na začátku a dogmaticky trvat na jejich dodržování je možná dobré s ohledem na dodržení podmínek smlouvy, ale málokdy pro výslednou kvalitu. Nebraňme se změnám zadání, buďme na ně připravení. Je naprosto legální, že požadavky se v čase vyvíjí podle toho, jak se tým i zadavatel učí rozumět problémové doméně. Zapojme zákazníka co nejvíce do vývojového procesu a budou z toho profitovat obě strany.
</p>
<p>U některých typů projektů, kdy nemáme skutečného zákazníka, je také vhodné zadefinovat interního zákazníka, který bude vystupovat v podobné roli jako skutečný zákazník. Bude zastupovat uživatele vyvíjené aplikace a bude zodpovědný za akceptaci výsledku. Měl by nám být nápomocen při diskuzích a připomínkování a neměl by být z našeho vývojového týmu.
</p>
<h2>Akceptační testování</h2>
<div class="separator" style="clear: both; text-align: center;">
<img src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgDhrWFS750yRPbJQTF3s9Ir19EXkt9VEBRjLn2FxLUB49w8lqRtcgrtA1gzbvpAC_j0X3Ds1DIs2hMc0gc9k1Ndh9e116tdCsAVZ1GIKzEEnVoC7VRaKJ46HgznamShsu-o9-hZIEvUG5o/s1600/at.png" style="border:none;box-shadow:none;vertical-align:bottom;horizontal-align:center;"
height="180pt"/>
</div>
<p>Akceptační testování je nezbytný proces pro ověření toho, že aplikace dostála závazkům vyplývajících z požadavků. Akceptační testy tvoří zároveň aktuální dokumentaci k systému. Ideální akceptační testy jsou automatizované, tedy kdykoliv snadno spustitelné. Pokud má aplikace GUI, pak zřejmě bude nutné akceptační testy provádět také ručně. Akceptační testy měl psát zástupce zákazníka ve spolupráci s členy QA týmu. Ne programátor.
</p>
<p>Správně napsané akceptační testy dodají kvalitní zpětnou vazbu o použitelnosti a stabilitě aplikace. Procházení jednotlivých testovacích případů je také měřítkem celkového postupu projektu. Získáváme informaci o tom, kolik práce je hotovo a kolik ještě zbývá. Ale znáte to, Paretův princip náš optimismus ve finále stejně zchladí. :)
</p>
<h2>Malé verze (Small Releases)</h2>
<div class="separator" style="clear: both; text-align: center;">
<img src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEj13RLP8AE5g-hyINo5gdDZufR2cn6Goy2FixKguYWXEobTXU1VqkquGrG7QrdH4f7krySl3o17CQeHaJLBpcqJXl5hSSfjoG3Lxf1BkrBgaumOWyMTOdTD0xiXC3-fAeOT-t6uOuRRaJb3/s1600/sr.png" style="border:none;box-shadow:none;vertical-align:bottom;horizontal-align:center;"
height="180pt" />
</div>
<p>Hodně projektů se prodražilo a mnohé úplně zkrachovaly, protože se dostaly do obrovských problémů s vydáním první funkční verze. Na první pohled vypadá snaha uvolnit “superverzi” aplikace jako dobrý nápad. Projektový tým chce vydat aplikaci až v okamžiku, kdy bude splňovat všechny must-have požadavky a ty budou navíc propracovány do nejmenších detailů. Ale my to takhle určitě nedělejme.
</p>
<p>Vývoj software je jako většina profesí především o emocích, motivaci, komunikaci, důvěře a dalších netechnických záležitostech. Lidem se mnohem lépe plní rozsáhlejší úkoly, pokud jsou rozděleny na více menších. A navíc každý úkol by měl být zakončen dosažením cíle. Naším prvořadým cílem je vydat aplikaci a dostat ji k uživatelům. Teprve v tomto okamžiku má naše práce nějakou reálnou hodnotu. Do té doby nemáme nic.
</p>
<p>Uživatelé ocení, pokud jim brzy dodáme verzi aplikace, která jim přináší nějaký užitek. Navíc rychle získáme zpětnou vazbu z reálného provozu, která je pro nás nejcennější. Vydávejme verze tak často, jak je potřeba. Funkcionalita nemusí být dotažena k dokonalosti, ale nesmíme vypouštět bugy. Pro časté automatizované uvolňování verzí je nutné mít vybudovánu kvalitní infrastrukturu pro Continuous Delivery. Jde o automatizaci vytváření verze, spouštění validačních mechanismů, nasazování do testovací prostředí a ve finále také do produkce. Obsahuje některé procesy známé z Continuous Integration.
</p>
<h2>Prototypování (Prototyping)</h2>
<div class="separator" style="clear: both; text-align: center;">
<img src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgVHy-Kmj0w1mqNtfJh1WAJS6sMkH6f1q26hjcyol2EWNULE_gC8-eGhv4XUQ4GsAHgiO2xyq5yL8SupmoXNHC8c3ui4kYoJKyPq0e5nEQGCJxMGxppqVA41gAreoZHNIwl3m5QTaL_Q0Cc/s1600/prot.png" style="border:none;box-shadow:none;vertical-align:bottom;horizontal-align:center;"
height="180pt" />
</div>
<p>Softwarové projekty jsou plné rizikových míst. Rizikem se může stát například použití nové technologie, návrh architektury, problematický framework, komunikace s novým fyzickým zařízením, napojení na špatně zdokumentovanou službu, apod. Zkušenosti vývojářů se projeví právě ve schopnosti dopředu tato rizika vytipovat a prověřit. Nejrizikovější části projektu řešme co nejdříve. Jako vhodná metoda pro validaci rizik se obvykle jeví prototypování.
</p>
<p>Prototyp je zjednodušená a tedy levná varianta aplikace nebo její části, která nám pomůže prověřit potenciální riziko. Při vytváření prototypu není nutné trvat na vysoké interní kvalitě. Důležitá je především rychlost vytvoření a získání zpětné vazby o problému. Po ověření problému život prototypu končí. Produkční kód se začne budovat znovu, tentokrát v produkční kvalitě.
</p>
<p>Často se prototypuje uživatelské rozhraní. V takovém případě nejde ani tak o prověřování rizika, zda-li něco nepůjde, ale spíše o ujasnění představy o výsledném produktu. Levně můžeme připravit více variant řešení.
</p>
<h2>Minimální tržní produkt (Minimum Viable Product)</h2>
<div class="separator" style="clear: both; text-align: center;">
<img src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEi1zp8RoxpPEte6ifUYR6xnBUj23ZRlrHTLUvKMt5QLOCn-BuaApwAEFZ40UnVIeCAvlvroiaObB6DOGvSwh3rCQStzuFqEg2U4WWU-WINEYDvp7NjickGoUuNzoya-Wc3G6J96UYSore38/s1600/mvp.png" style="border:none;box-shadow:none;vertical-align:bottom;horizontal-align:center;"
height="180pt" />
</div>
<p>Jak už bylo popsáno výše, měli bychom se vyhnout snaze dodat veškerou zamýšlenou funkcionalitu najednou. Vývoj by byl zdlouhavý a zpětnou vazbu z reálného provozu bychom získali příliš pozdě. Technika Minimum Viable Product nabádá k tomu, abychom zadefinovali minimální rozsah funkcionality, který reprezentuje vizi vašeho produktu, tu rychle vyvinuli a nasadili do provozu. Získáme tak ohlasy od skutečných uživatelů z reálného provozu. Začneme se rychle učit, jak na produkt uživatelé reagují, jaké by se hodily další funkce a které funkce jsou nevyužívané a tedy nadbytečné. Ideální použití je v situaci, kdy je uživatelská spokojenost skutečně naším prvořadým cílem. To znamená vždycky. Státní IT projekty se nepočítají. ;)
</p>
<p>Další členové rodiny technik pro získávání zpětné vazby od skutečných uživatelů jsou Win-loss Analytics, Beta Programs, Focus Groups nebo Market Interviews.
</p>
<h2>Iterace (Iterations)</h2>
<div class="separator" style="clear: both; text-align: center;">
<img src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjubfUGnaC8p4AYMyXcGNRSc0gXe_N0ozSGVJx-rwiUEx6TMxtBnY7KZnqIqe3wwCxFfZDfAePPnI4U1hYjbXvUgXlHDxDzz-gggogjmrvn-L6HkoQw9TLsDp5jN0_ML419Um8oGWV0_QrY/s1600/it.png" style="border:none;box-shadow:none;vertical-align:bottom;horizontal-align:center;"
height="180pt" />
</div>
<p>Rozdělit řešení rozsáhlého projektu na menší části s jasně definovanými akceptačními kritérii je základem úspěchu softwarového projektu. Zapomeňte na smrtící vodopád a naučme se organizovat práci do iterací. Iterace dostanou náš tým do potřebného pracovního rytmu a získáme důležitou zpětnou vazbu o jeho rychlosti a možnostech. Každá iterace (doporučená délka 1-3 týdny) začíná plánováním úkolů včetně estimace, pokračuje realizací a končí předvedením výsledků a retrospektivou.
</p>
<p>První iterace mohou být o sesbírání potřebných informací, vytváření vývojové infrastruktury, zavádění agilních technik, prototypování, vytvoření základních projektových artefaktů, apod. V dalších fázích už řešíme konkrétní požadavky a začínáme produkovat první validní výstupy. Jako první si zvolme nejprioritnější nebo nejrizikovější požadavky, které nás donutí implementovat vertikálně skrze všechny vrstvy aplikace. Učíme se tak co nejrychleji rozumět všem aspektům realizace naší aplikace.
</p>
<h2>Komunikace v týmu (Team Communication)</h2>
<div class="separator" style="clear: both; text-align: center;">
<img src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhPaX__y9DZ1C-pZUumQssNGifIBw_1QgoDC2OEkG0Wpd1PJM3jXvbW8dH6EHbJ5B7o47cembhsboTgx4MNtquN_6Rk_meo7H5cVqT8HivvMJUDM22YYuWVE7PK25uWn1bfK53IO47HLOs1/s1600/com.png" style="border:none;box-shadow:none;vertical-align:bottom;horizontal-align:center;"
height="230pt" />
</div>
<p>
<i>Jejda, ty děláš na stejném úkolu jako já! <br />
Vy jste poslední dny dělali tenhle úkol?! Ten má ale aktuálně nízkou prioritu! <br />
Na pár dnů jsem se zasekl s tímhle. -- Proč neřekneš, zrovna tohle jsem nedávno řešil! <br />
</i>
</p>
<p>Dochází k podobným zmatkům i u vás. Nevíte přesně, kdo na čem aktuálně dělá? Pak je nezbytné zlepšit komunikaci v týmu. Je na zodpovědnosti vedoucího týmu, aby zajistil optimální komunikační prostředí a vzájemnou informovanost všech členů.
</p>
<p>Využívejme techniky společných plánovacích schůzek, díky kterým všichni vědí, co se bude dělat a co je prioritní. Zabudujme do svého pracovního dne krátké týmové stand-up rychloporady. Jedná se o efektivní způsob, jak se vzájemně informovat o aktuálně řešených úkolech a problémech. Nezapomínejme na společné retrospektivy, kde se dozvídáme o úspěšnosti plnění našich plánů. Na retrospektivách je také prostor pro diskuzi nad pracovními postupy, které používáme. Nebojme se zahodit postupy, které nefungují a pouze nám přinášejí zbytečnou zátěž.</p>
<p>Postupnými malými změnami v našich pracovních postupech můžeme ve výsledku dosáhnout velkého zlepšení. A o to nám přeci jde. Vím to, protože jste tento článek dočetli až sem. ;)
</p>Robert Dreslerhttp://www.blogger.com/profile/16401744220939465418noreply@blogger.com4tag:blogger.com,1999:blog-3408745507091232422.post-59269796647700575142013-09-14T09:47:00.000+02:002013-09-14T09:47:53.129+02:00Život s debuggerem<b>… aneb debugování jako indikátor problémových postupů</b>
<p>
Byl pátek třináctého, navíc 256. den v roce - svátek programátorů a já jej oslavil téměř 10-tihodinovou programovací šichtou. Po celý den jsem se pokoušel striktně dodržovat TDD přístup. Padající test, nejmenší nutná implementace, zelenáč. A takhle pořád dokola. Jako když rytmicky dýcháte - nádech a výdech. Práce šla od ruky a unit testy rodily produkční kód pěkně podle plánu. Za celý den jsem použil debugger snad jen dvakrát. V kontextu událostí jsem si utvítnul trochu provokativní tvít:
</p>
<blockquote class="twitter-tweet"><p>Dělejte všechno pro to, abyste nemuseli používat debugger. <a href="https://twitter.com/search?q=%23dev&src=hash">#dev</a></p>— Robert Dresler (@rdresler) <a href="https://twitter.com/rdresler/statuses/378528181193416704">September 13, 2013</a></blockquote>
<script async src="//platform.twitter.com/widgets.js" charset="utf-8"></script>
<p>
Akce rodí reakci a ta také přišla. Twitter je plný šikovných lidí se spoustou zkušeností z praxe a já jsem za jejich reakce moc rád. Zároveň je Twitter omezený na 140 znaků a to se pak těžko argumentuje. Dejte mi šanci utvítnutou myšlenku trochu vysvětlit formou tohoto příspěvku.
</p>
<p>Dopředu je potřeba přiznat, že bych se bez možnosti debuggování aplikace určitě neobešel. Na druhou stranu pozoruju, že s postupným profesním vývojem se u mě nutnost používání tohoto nástroje postupně snižuje. Snažím se hledat postupy, které vnášejí do vývoje aplikace větší jistotu a menší chybovost.
</p>
<h2>Unit testy a TDD</h2>
<p>K jedné z největších revolucí v mých pracovních návycích došlo v okamžiku, kdy jsem začal psát unit testy. Potenciál unit testů využijeme naplno až v kombinaci s TDD nebo nějakou jinou test-first technikou. Ta nás nutí přemýšlet dopředu o struktuře a funkcionalitě kódu. Rozkládat komplexnost řešení na malé samostatné scénáře použití. Jedním z klíčových aspektů je postupná, iterativně přidávaná funkcionalita. I při budování rozsáhlé aplikace metodou malých přírůstků je pravděpodobné, že budete mít stav věcí pod neustálou kontrolou. Určitě mnohem více, než když nakódujete desítky řádek kódu a pak se je snažíte najednou otestovat a integrovat.
</p>
<p>Krůčky jsou tak elementární, že téměř ani není nutné spouštěný test debugovat. Třídy jsou testovány v izolaci a pokud navíc dodržujeme např. SOLID, rozpadá se nám funkcionalita do malých tříd s jasně definovanými zodpovědnostmi. Takové třídy se pak dobře testují. Práce bez debuggeru je mnohem rychlejší.
</p>
<h2>Integrační testování</h2>
<p>Jistota z unit testů se přenáší do integračních testů, které jsou cílené na ověření spolupráce mezi více reálnými třídami. V případě dobře navržených rozhraní a podpory IoC kontejneru je celý proces integrace, opět po postupných krůčcích, transparentní a méně náchylný k chybám. Máme odzkoušené jednotlivé třídy? Pak zřejmě bude fungovat i jejich kompozice.
</p>
<p>Při integraci se do akce dostávají také frameworky třetích stran. Míra nutnosti použití debuggeru pak bude zřejmě odvislá od naší znalosti jejich API a také od toho, jak dobře použitelné tyto frameworky jsou. Nerozumím používanému frameworku? Asi si hodně užiju debugování.
</p>
<h2>Čistý, přehledný a jednoduchý kód</h2>
<p>Programátor dospívá v okamžiku, kdy se mu přestává líbit složitý kód a začíná hledat prostředky zajišťující jednoduchost. Skrze kód komunikujeme s počítačem a s ostatními členy týmu. A je to podobné jako jiné formy komunikace. V případě, že něčemu skutečně rozumíme, umíme to vyjádřit jednoduše a jasně. Dobré komunikační dovednosti posouvají programátora na vyšší úroveň a zvyšují jeho hodnotu pro týmovou spolupráci.
</p>
<p>Pokud nezměníme firmu nebo náš projekt nekrachne, pak nás vlastní kód bude pronásledovat ještě dlouhé roky. Určitě znáte ten pocit, kdy se po delší době vrátíte ke staršímu kódu a nerozumíte mu. Dokonce se k němu někdy nechceme ani znát. To jsem opravdu napsal já? No nic, nezbývá než refaktorovat.
</p>
<p>Že se nám podařilo napsat nesrozumitelný kód poznáme podle toho, že jsme nuceni často spouštět debugger a krokovat, abychom pochopili sémantiku kódu.
</p>
<h2>Rychlost nebo kvalita</h2>
<p>Vždy preferujme dobrý návrh a udržovatelnost kódu nad rychlostí jeho vytváření. U dlouhodobých projektů se nám to vrátí mnohonásobně.
</p>
<p>Někde na fóru jsem četl myšlenku:<p/>
<p>
<i>Jednou z nejdůležitějších dovedností programátora je schopnost psát jednoduché kousky kódu správně napoprvé, bez nutnosti používat debugger.</i>
</p>
<p>Tato myšlenka nám dává návod, jak být současně rychlí. Naučit se malé elementární programátorské problémy řešit napoprvé správně a kompozicí z nich budovat složitější. Získat jistotu v základech naší práce - v algoritmizaci.
</p>
<h2>Diagnostika</h2>
<p>Dobře zvolená diagnostika aplikace nám může ušetřit časově náročné ladění aplikace skrze debugger. Logování chování aplikace a především podrobný kontext chyby je neocenitelným pomocníkem pro rychlou navigaci k problémovému místu. Nespoléhejme se na důvěryhodnost hlášení od uživatelů, zajistěme si automatizovaně dostatek informací k problémům sami.
<h2>Techniky na detekci a předcházení chybám</h2>
<p>Debugger je deratizérský nástroj určený pro odchyt otravných, obvykle v pátek odpoledne se objevujících, bugů. Ještě před použitím vlastního ladění nebo ihned poté co jsme chybu přes debugger detekovali, můžeme zkusit chybu izolovat. Na chybový scénář napíšeme jednotkový nebo integrační test. Fixnutí bugu tak odpovídá stavu, kdy nám začne procházet nově napsaný test.
</p>
<p>Mnohem levnější, než nahánět bugy nahlášené od testerů a uživatelů, je bugům aktivně předcházet. Výše popsané techniky můžeme doplnit o revize kódu nebo přímo programovat v páru a tím code review dělat v reálném čase. Důležité je samozřejmě používat jednotné kódovací standardy a jmenné konvence, které urychlují orientaci a porozumění kódu všem členům týmu a snižují riziko špatného použití. Využívejme nástroje na statickou analýzu kódu, které umí najít spoustu potenciálně rizikových míst. Neignorujme kompilační warningy. Jsou to tiše tikající časované bomby, které se mohou změnit v nepříjemné chyby. Praktikujme společné vlastnictví kódu, které pomáhá šířit znalosti v týmu a kontinuálně vylepšuje code base. Využívejme průběžnou integraci na buildovacím serveru. Zlepšujme komunikaci na všech úrovních struktury projektového týmu.
</p>
<h2>Závěrem</h2>
<p>Debugger jako nástroj má samozřejmě své opodstatnění. Ve vlastním zájmu bychom se ho měli naučit ovládat efektivně a znát všechny jeho možnosti. Zároveň je však třeba si uvědomit, že jeho časté nadužívání může indikovat zásadnější problémy v našich postupech a dovednostech. Vystupme občas z pracovního stereotypu a přemýšlejme nad tím, jak naši práci zefektivnit tak, abychom debugger - nástroj poslední záchrany - nemuseli používat příliš často.
</p>
Robert Dreslerhttp://www.blogger.com/profile/16401744220939465418noreply@blogger.com4tag:blogger.com,1999:blog-3408745507091232422.post-73100146923558804982012-12-09T11:53:00.001+01:002012-12-10T12:44:47.116+01:001. Vsetínský Code Retreat<b>... aneb Trávit celou sobotu psaním kódu, který každou hodinu stejně zahodíte? Jste blázni! :)</b>
<p>
<div class="separator" style="clear: both; text-align: center;"><img border="0" height="60" width="60" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjGdu7B__XETInR7-iIZT0d9xWoLOOTzYhYREeGFZdLZnow4Rw-0p2HglMUI-BjPIcY4Fz1XU5dIvnmIz4RMjvc8ExNn8RlwLt0j-74GgbH2hvL3mHlu7PEWuIBXDdUSGTUBrD7ofxkL-ZB/s320/images%255B1%255D" style="border:none;box-shadow:none;vertical-align:bottom;horizontal-align:center;" /></div>
</p>
<p>Podobné reakce manželek, přítelkyň a okolí zaznamenali účastníci 1. Vsetínského Code Retreatu,
když se snažili doma vysvětlit proč jedou na celou sobotu někam na Vsetín. Popsat základní koncept celosvětově populární
akce Code Retreat není totiž úplně jednoduché. Ani programátorům, natož "nevyvolenému" zbytku populace. Sami účastníci možná také
úplně netušili, do čeho se to vlastně pouštějí. Přál bych vám však vidět nadšení, které v průběhu
akce narůstalo rychlým tempem. Na konci již nikdo nepochyboval, že investovat celou sobotu do akce tohoto typu, byl výborný nápad.</p>
<p>Vsetínský Code Retreat byl jednou ze stovky akcí, které proběhly během soboty 8.12.2012 po celém světě v rámci Global Day of Code Retreat.
K již tradiční pražské akci se letos premiérově přidal právě Vsetín. A jaké to u nás vlastně bylo?</p>
<h2>Socializing</h2>
<p>Úspěšnost akcí tohoto typu je velmi závislá na přístupu jednotlivých účastníků. Na jejich ochotě experimentovat, uvolnit se, spřátelit se s ostatními
a podporovat pozitivní atmosféru. Za proaktivní přístup jsou po právu odměněni novými zážitky, zkušenostmi a změnou paradigmat
programátorské profese. Koncept CR je postaven tak, aby maximálně podporoval sociální rozměr akce. Úvodní seznámení,
střídání partnerů během párovém programování, oběd a afterparty, přispívají k tomu, že mezi lidmi vznikají trvalejší přátelství.
Je to i jeden z důvodů, proč lidé jezdí na své třetí a čtvrté Code Retreaty, proč vstávají ve tři hodiny ráno a jedou přes celou republiku v -10°C.</p>
<p>Na Vsetín přijeli kluci z Brna, Uherského Brodu, Frenštátu a dokonce i jeden Pražák! Viděl bych to jako začátek pěkné tradice,
kdy z hlavního města budou jezdit programátoři k nám na vesnici. ;) Pro všechny kódující účastníky to byla premiérová účast na CR.
Pro mě zase premiéra v roli facilitátora. </p>
<h2>Languages</h2>
<p>Akce není omezena na konkrétní programovací jazyk ani platformu. Tato pestrost je dokonce silnou stránkou konceptu CR.
Programátoři se díky párování seznámí s jazyky, ke kterým se do té doby báli už jenom přiblížit. Ztratí zbytečné zábrany a předsudky.
A naopak získají chuť vyzkoušet nový jazyk a tím si rozšířit znalosti a technologický přehled. Pozorovat kolegu, který hbitě píše kód
v "exotickém" jazyce, je velmi inspirující.</p>
<p>Na Vsetíně se kódovalo v jazycích C#, Java, JavaScript, Python, PHP, CoffeeScript, F#. Ohlášený experiment napsat část Game Of Life pomocí
uložených databázových procedur MS SQL Serveru se nakonec nekonal. :)</p>
<h2>Sessions</h2>
<p>Kódovacích bloků je celkem šest (tři dopoledne, tři odpoledne), trvají 45 minut, vždy se začíná od prázdného projektu, řeší se Game of Life
a každý blok je specifický výběrem aktivit a rozvíjí jiný druh dovedností. Pro vsetínský CR jsem aktivity namíchal takto:</p>
<p><b>Session #1</b></p>
<p>Game of Life Basics<br/>
Navigator - Driver</p>
<p>První blok byl určen k seznámení s pravidly Game of Life. Programátoři si zvykali na párové programování, kdy jeden z dvojice psal kód (driver)
a druhý spolupracoval na analýze a návrhu řešení a dělal průběžné review (navigator). Bezprostřední reakce při následné krátké retrospektivě byly
velmi pozitivní. Partneři vzájemně konfrontovali své styly nahlížení na problém a návrhy řešení. Někteří si poprvé přičichli k neznámému jazyku.
Tak jako později pokaždé, na konci bloku se veškerý kód zahodil. Mám však tajné informace, že někteří si kód uložili do archivu, aby se s ním mohli
pochlubit doma svým přítelkyním. :)</p>
<p><b>Session #2</b></p>
<p>Simple Design<br/>
Baby Steps<br/>
English</p>
<p>Před druhým blokem byly účastníkům připomenuta 4 pravidla jednoduchého návrhu. Byli také seznámeni s konceptem testy řízeného návrhu, který byl
ztěžejní po zbytek dne. Aktivita Baby Steps nutí psát testy a implementaci po nejmenších nutných krůčcích definovaných metodikou TDD.</p>
<p>Programový kód musel být kompletně anglicky, bez českých elementů.</p>
<p>Pro někoho byl požadavek na test-first přístup nový a nezvyklý. Častým problémem, který jsme pak rozebrali v následné retrospektivě, byly názvy testů.
Objevovaly se názvy testovacích metod, ze kterých nebyl zřejmý účel testu. TDD metodika chápe psaní testů jako akt návrhu. Je tedy nutné si uvědomit,
že dobrým názvem vše začíná. Každý test řeší obecně tři základní věci: 1. operaci, která se testuje, 2. kontext před provedením operace, 3. očekávaný výsledek
(testovaný stav po operaci). Tyto informace by měly být zakódovány do dobrého názvu testu. V další části dne se ukázalo, že vymyslet správný název
testu je poměrně náročná záležitost.</p>
<p><b>Session #3</b></p>
<p>Paper Only (10 min)<br/>
No Mouse (No Touchpad)</p>
<p>Programátoři byli přinuceni prvních 10 minut pracovat pouze s papírem. Promýšlení návrhu bez hurá stylu okamžitého kódování,
se stalo velmi oblíbeným. Papír byl tak nezbytnou pomůckou po zbytek dne.</p>
<p>Pro někoho se stala extrémně náročnou aktivita No Mouse. Časté sahání na myš je pro programátora kontraproduktivní. Většina IDE má velmi
dobrou podporu pro ovládání z klávesnice. Mnoho programátorů však neumí dostatečně efektivně této podpory využívat. Jeden z výrazných přínosů
párového programování je právě v tom, že se učíte od drivera jeho efektivní postupy v ovládání z klávesnice. Objevujete nové možnosti a finty, které
zařazujete do vašeho profesního portfolia. Na konci bloku jsme diskutovali o výhodách znalosti code snippetů, šablon, klávesových zkratek,
různých doplňků do IDE a nástrojů obecně. Naše produktivita roste v závislosti na tom, jak dobře se naučíme ovládat nástroje, které ke své práci používáme.</p>
<p><b>Session #4</b></p>
<p>Ping Pong<br/>
Mute</p>
<p>Během prvního odpoledního bloku se hrál pingpong s vypnutým zvukem. Jeden z dvojice psal failující test, druhý musel dopsat procházející implementaci.
A protože se nesmělo mluvit, jedinou komunikací byly prostředky kódu a především názvy metod, proměnných a pojmenovaných konstant. Programátoři si
uvědomili důležitost expresivity kódu. A nakonec jsme se shodli, že tento blok byl jeden z nejzajímavějších v rámci celé akce.</p>
<p><b>Session #5</b></p>
<p>Only 4 Lines per Method<br/>
No Conditional Statements<br/>
No Naked Primitives</p>
<p>Začalo přituhovat a ukázalo se, že tento blok byl hodně náročný. Psát krátké metody není zas takový problém. Je nutné si pouze uvědomit, že krátké bloky kódu
jsou mnohem čitelnější a udržovatelnější. S využitím refaktorizačních technik je navíc strukturování kódu efektivní.</p>
<p>Problémem ale bylo omezení na nepoužívání rozhodovacích příkazů. Vynechat <b>switch</b> nás nutí více přemýšlet o polymorfismu. Nepoužívat <b>if</b>
je však hardcore technika. V této aktivitě nebyly dvojice příliš úspěšné. Každý však ocenil, že No Ifs vás přinutí se na četnost rozhodovacích bloků
v kódu podívat jiným pohledem. Pro zájemce přikládám link na GitHub s řešením
<a href="https://github.com/saruye/game-of-life/tree/master/%5Bcoderetreat%5D%20no%20if/src/main/java/de/socramob/gol">GoF v Javě bez ifů</a>.</p>
<p>Nepoužívání holých primitiv (např. int, bool) v rozhraní tříd bylo také inspirativní. Použití výčtového typu namísto boolean hodnot zlepšuje
čitelnost kódu. Obecně byla tato aktivita zaměřena na vhodnější používání abstrakcí namísto zveřejňování implementačních detailů. </p>
<p><b>Session #6</b></p>
<p>Changing Requirements<br/>
Configurable Rules<br/>
Cell Age</p>
<p>Poslední blok byl již více odpočinkový. Účastníci se párovali tak, aby si ještě vyzkoušeli neznámé jazyky. Dvojice zkoušely implementaci dalších pravidel.
Přibylo pamatování věku živé buňky (počet iterací, které přežila) a vznikaly experimenty jako "superdůchodce" (pokud buňka přežila alespoň tři iterace, byla nezničitelná).</p>
<h2>Closing Circle</h2>
<p>Závěrečná retrospektiva byla pro mě osobně nejinspirativnější částí celé akce. Každý z účastníků měl za úkol shrnout, co se během akce naučil, co ho překvapilo
a co využije ve své praxi. Bylo velmi zajímavé poslouchat, co si kdo z akce odnášel, co jej inspirovalo a kde objevil své slabší stránky. Atmosféra akce
a složení lidí (kamarádů) přispělo k tomu, že výpovědi byly velice upřímné a tudíž zajímavé. Bylo více než zřejmé, že se všem akce líbila. Věřím, že se s většinou lidí setkám i příště a že budou myšlenky Code Retreat sami dále propagovat.</p>
<h2>Acknowledgement</h2>
<p>Rád bych na tomto místě poděkoval těm, kteří mně pomohli s organizací akce:
<li>Firmě <a href="http://www.magion.cz/">Magion system, a.s.</a>, která akci podpořila finančně.</li>
<li><a href="https://twitter.com/alesroubicek">Alešovi Roubíčkovi</a> za nakopnutí k uspořádání Code Retreatu, za pomoc s propagací a za poskytnutí
organizačního know-how.</li>
<li>Panu Romanu Mlýnkovi z Agentury pro ekonomický rozvoj Vsetínska, o. p. s., díky jehož ochotě a pomoci s přípravou vše proběhlo technicky hladce.</li>
</p>
<h2>Links</h2>
<ul>
<li><a href="http://www.slideshare.net/rdresler/code-retreat-vsetin-12082012">Prezentace z akce na Slideshare</a></li>
<li>České stránky o Code Retreat <a href="http://www.coderetreat.cz">www.coderetreat.cz</a></li>
<li>Domovský server Code Retreat <a href="http://www.coderetreat.org">www.coderetreat.org</a></li>
<li>Stránka akce na <a href="http://srazy.info/coderetreat/2715">srazy.info</a></li>
<li>Pražský partnerský Code Retreat na <a href="http://devblog.cz/2012/12/global-day-of-code-retreat-2012/">devblog.cz</a></li>
</ul>
<p>
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhSX2vv4qneYEO7f-OVznXAMW6U0wGA7CGtIbp4RZeVGCAX3sA-xCdws1jK8YfFC3_tp6sV7a1f-qBByCHOlvB8htau3NZcOS2NjBe4Zy9uNL60aFgxHre_YdrnV_7_dNq4V-H3UGbO10yG/s1600/IMGP4459-24.jpg" imageanchor="1" style="margin-left:1em; margin-right:1em"><img border="0" height="207" width="320" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhSX2vv4qneYEO7f-OVznXAMW6U0wGA7CGtIbp4RZeVGCAX3sA-xCdws1jK8YfFC3_tp6sV7a1f-qBByCHOlvB8htau3NZcOS2NjBe4Zy9uNL60aFgxHre_YdrnV_7_dNq4V-H3UGbO10yG/s320/IMGP4459-24.jpg" /></a></div>
</p>Robert Dreslerhttp://www.blogger.com/profile/16401744220939465418noreply@blogger.com5tag:blogger.com,1999:blog-3408745507091232422.post-88469874089931968292012-11-23T21:18:00.000+01:002012-11-24T06:36:27.063+01:00DevFest Story<p>
<div class="separator" style="clear: both; text-align: center;"><img border="0" width="100" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEj0YoTPi3NjHBizsYRtlrThLvx3wdV1-YgDmYID-XUKDONSF1OP3AreiQZgxoeV2Aek-1Gt8dWZwgTOiJBjFpxvR7j90gWmSg3QgTIMk9kL3LBWZPl-TIyiyC-JNyKAqjl1Xlud459HuyR9/s200/devfest-logo%255B1%255D.png"
style="border:none;box-shadow:none;vertical-align:bottom;horizontal-align:center;" /></div>
</p>
<p>
V sobotu 10. listopadu 2012 proběhla v Praze zajímavá vývojářská konference
<a href="http://www.devfest.cz/">DevFest</a>. Asi měsíc před tím mě oslovil Pavel Vybíral z pořádající agentury a nabídl mi
možnost na konferenci přednášet. Vystoupit na nějaké menší konferenci mě vždy lákalo. Že to ale bude akce s tak velkou účastí ajťáku mi začalo docházet až poté,
co jsem účast přislíbil. ;)</p>
<p>
Ve volbě tématu jsem měl od pořadatelů poměrně volnou ruku. "Vyberte něco z toho, o čem blogujete a twítujete". Na Twitteru se snažím psát vývojářské rady a tipy
(jak kdysi řekl v nadsázce <a href="https://twitter.com/kolman">Dan Kolman</a> "moudra"), které sbírám během své praxe a při čtení všemožných ajťáckých i neajťáckých materiálů. Blog se mi profiluje
od původně čistě kodérských problematik směrem k peopleware a týmové spolupráci. Po 10 letech kódování a postupného objevování praktik dobrého návrhu a psaní
čitelného kódu je pro mě zamýšlení se nad lidskými aspekty vývoje software příjemnou změnou.
</p>
<p>
S ohledem na vysokou návštěvnost a pozitivní zpětnou vazbu k blogpostu
<a href="http://www.robertdresler.cz/2012/10/dusevne-uprimny-programator.html">Duševně upřímný programátor</a>,
jsem se rozhodl přednášku zaměřit na charakterové vlastnosti, které profilují dobrého vývojáře. Pokusil jsem se také vysvětlit základy v přístupu k naší profesi.
Vývojář by si měl uvědomit, že jeho nejdůležitější dovedností je schopnost rozkládat a zjednodušovat řešený problém. Osvojovat si techniky řízení složitosti,
které mají úzkou vazbu na techniky pro zajištění kvality. Trénovat dovednosti pro psaní kódu podobně jako trénují sportovci.
Být hladový po informacích o technologickém vývoji. Přemýšlet nad efektivností používaných pracovních postupů.
A také dbát na svoje zdraví a zajistit si tak dlouhodobou použitelnost. Přednáška tak byla určená pro všechny vývojáře, nezávisle na vývojové platformě.
</p>
<p>
K dispozici jsou <a href="http://www.slideshare.net/rdresler/urychlovae-vvojova-profesnho-rstu#">slajdy přednášky na Slideshare</a> a
<a href="http://www.youtube.com/watch?v=Kb1UmdpWBww">video na YouTube</a>.
</p>
<p>Upozornění: Přednáška obsahuje sex! Pouze pro vývojáře staří 18 let! :)</p>
<h2>Něco ze zákulisí</h2>
<p>
Připravovat se na přednášku v bytě se třemi dětmi je slušný víceboj. Ještě větší adrenalin je pak vlastní vystoupení. Hodně jsem bojoval s nervozitou
a asi to je na videu znát. Nějakou dobu mně trvalo, než jsem se uvolnil. Možná si ještě vzpomenete, jak jste se při vašem prvním vystoupení
před tolika lidmi cítili vy. ;) Každopádně jsem za tuto zkušenost moc rád.
</p>
<p>
Dopředu jsem se těšil, že se osobně setkám s lidmi, které znám zatím pouze z Twitteru. Respektované prezentátory
<a href="https://twitter.com/steida">Dana Steigerwalda</a> a <a href="https://twitter.com/jiriknesl">Jirku Knesla</a>,
"virtuální kamarády" <a href="https://twitter.com/AugiCZ">Augiho</a>, <a href="https://twitter.com/topascz">Tomáše Pastorka</a>,
<a href="https://twitter.com/novoj">Honzu Novotného</a>, <a href="https://twitter.com/OndrejMirtes">Ondru Mirtese</a> a další.
Ty první jsem nezastihl a ty druhé zase nepoznal podle profilovek. :) Snad někdy příště.
Nakonec jsem byl na celé akci jenom pár hodin, protože na mě padla megaúnava z nevyspání a z náročného dopoledního cestování.
</p>
<p>Velký dík patří organizátorům za přípravu atraktivního programu a zvládnutí celé akce!</p>Robert Dreslerhttp://www.blogger.com/profile/16401744220939465418noreply@blogger.com9tag:blogger.com,1999:blog-3408745507091232422.post-19363898984244336572012-10-04T19:31:00.000+02:002012-10-05T08:12:06.685+02:00Duševně upřímný programátor<p>
<div class="separator" style="clear: both; text-align: center;">
<img border="0" height="100" width="155" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEj68h-T0u0dy33NCjQfeJGIgOAGqUVJ1r-NoLO6yv6DEbEILN-rNM146wkytEvom3o6gQ5mK9iqjI4KLxLbyWfkiXwImza6tUr_Pi6py5AbWUs4mlOAkOhghWitc6LlK_R5YASClTb8FcBa/s200/divadlo%255B1%255D.gif"
style="border:none;box-shadow:none;vertical-align:bottom;horizontal-align:center;" /></div>
</p>
<p>Rád hledám charakteristiky, které popisují dobrého programátora nezávisle na konkrétních technologiích a programovacích jazycích.
V knize <a href="http://www.cc2e.com">Code Complete</a> od Steva McConnella jsem narazil na skvělou pasáž, která se věnuje povahovým vlastnostem dobrého vývojáře.
Rád bych se zastavil u jedné z nich. U <i>duševní upřímnosti</i>. Musím uznat, že jsem si během své vývojářské praxe prošel většinou nešvarů pramenících z jejího nedostatku. Některé odstraňuji dokonce doteď. :)</p>
<h2>Nebuďte falešný expert</h2>
<p>Pokud máte dostatek duševní upřímnosti, nesnažíte se působit jako expert, pokud jím v dané oblasti nejste. Jedná se o jakousi
intelektuální skromnost, díky které se budete lépe rozvíjet. Je vhodnější přiznat, že s danou technologií nemáte dostatek zkušeností,
že danou část frameworku neznáte, že si nejste jistí určitou definicí. Pokud přistupujete k problému s vědomím, že umíte spíše méně,
je pro vás přirozenější naslouchat ostatním a tím se více učit.</p>
<p>Zkuste si kvantifikovat při každé otázce, jakou úroveň jistoty v ní máte. Pozor, pokud často dosahujete ve svých očích 100%, zbystřete.
Může se jednat o narcismus! :)</p>
<h2>Přiznejte se k chybě</h2>
<p>Duševně upřímný programátor se k chybě přizná rychle a rozhodně. Postaví se k ní chlapsky (programátorky prominou) čelem. Kroutit se
a obhajovat chybu je zbabělé. Někdo si dokonce myslí, že když chybu nepřizná, okolí si bude myslet, že není jeho. :) Nefér
přístup k řešení chyby může dojít až tak daleko, že dotyčný získá pověst pyšného a přezíravého programátora. A takové pověsti je pak
těžké se zbavit.</p>
<p>Udělat chybu není ostuda. Pokud však není způsobena nedůsledností. Každopádně je nutné se vždy z chyby poučit a
přijmout opatření, aby se neopakovala. </p>
<h2>Neignorujte varování</h2>
<p>Oblíbeným sportem je ignorování warningů při sestavování aplikace. Přehlížíme varování, která mohou způsobit v budoucnu velké problémy.
Častokrát hledáme přičiny problémů v aplikaci a přehlížíme, že nám překladač mává signalizačními tyčemi přímo před očima. Nedostatek
duševní upřímnosti se zde projevuje naší bohorovností v přehlížení varování. "To neděláš dobře s těmi sirkami, Jaromíre!" :)</p>
<h2>Snažte se dobře porozumět svému programu</h2>
<p>"Zkusím si spustit program, abych vůbec pochopil, jak to tam dělám." A metodou pokusů a omylů a s využitím debuggeru zjišťujeme, jak náš vlastní
program pracuje. Prostě mu nerozumíme. Přičin může být mnoho - nečitelný kód s vysokým stupněm složitosti, chybějící jednotkové testy s dokumentační
funkcí, výpadky paměti, apod. </p>
<p>Pokud si připustíte, že programu nerozumíte a je potřeba zahájit nápravná opatření, jste na dobré cestě. Pusťte se do vylepšení návrhu,
zlepšení čitelnosti, pokrytí testy. Prostě zvyšujte jednotlivá kritéria vnitřní kvality kódu. Jedině s tímto přístupem napíšete příští
kód v lepší kvalitě již napoprvé.</p>
<h2>Informujte reálně o aktuálním stavu</h2>
<p>Nestíháte, ale nechcete to přiznat? Říkáte vedoucímu raději to, co by chtěl slyšet, místo objektivní skutečnosti? Pak dostáváte do problémů
nejen sebe, ale právě i vedoucího. Jeho zodpovědností je řídit projekt a pokud je informován špatně, dělá špatná rozhodnutí.
Pokud byste včas přiznali, že máte problémy, například že vám z objektivních příčin klesá produktivita,
dobrý projekťák se vám vždy bude snažit pomoci.</p>
<p>Většina agilních vývojových metodologií napomáhá tomu, aby se informace o problémech a překážkách v postupu projektu dostaly co nejefektivněji
od členů týmu k vedoucímu. Informujte o problémech na denních scrum schůzkách nebo i dříve.
Buďte aktivní v řešení vyvstalých problémů. Vaše upřímnost bude oceněna a získáte v očích ostatních větší kredit.</p>
<h2>Dávejte realistické časové odhady a buďte neústupní</h2>
<p>Představte si, že jste požádáni o odhad pracnosti nové funkcionality. Pohovoříte s kolegy, sečtete jednotlivé odhady a dodáte celkové číslo.
Vedení se vyleká a přitlačí vás, abyste udělali "lepší" a hlavně nižší odhad. Pokud půjdete přes svoje přesvědčení a magicky snížíte odhad,
aniž byste definovali jaké ústupky musíte udělat, je to zle. Lžete opět sami sobě a necháváte se přitlačit do kouta. V případě realizace
byste se zřejmě dostali do časového presu, následného stresu a včasné dokončení projektu může být ohroženo.</p>
<p>Trvat na svém se musí každý vývojář naučit. Málokdo to umí už od začátku. S postupným získáváním praxe se přesnost odhadů zlepšuje.
Vysvětlete vedení, že fyzikální zákony (konkrétně časové) ještě měnit nedokážete a případné kompromisy by byly podobně špatné. Pokud je
projekt pro vaši firmu zajímavý, můžete dát zákazníkovi samozřejmě nižší cenu, aby do projektu šel. Ale interně si v týmu nic nenalhávejte.
Neupřímnost ničí pracovní vztahy.</p>Robert Dreslerhttp://www.blogger.com/profile/16401744220939465418noreply@blogger.com3tag:blogger.com,1999:blog-3408745507091232422.post-12439423718837020842012-10-01T15:14:00.000+02:002012-10-01T15:14:51.961+02:00Společné vlastnictví kódu<p>
<b>... nejvyšší forma týmové spolupráce
</b>
</p>
<p>
<div class="separator" style="clear: both; text-align: center;">
<img height="98" width="100" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiiBsy72i1SEPRIiicP5fd1DgGjrQDmo3IuOo9EIBU-eGuKJbVb-fXH00ly1LKzKDqmqfsOshKCoRFEhnsGj-MjXankLx8u8f6Ircv4SB8Ovb0YD2pdX_3VxR8_FalnNKhELircwlTuUvU-/s200/Working_Together_Teamwork_and-team-building-exercises%255B1%255D.jpg"
style="border:none;box-shadow:none;vertical-align:bottom;horizontal-align:center;" /></div>
</p>
<p>
<i>
Franta je na dovolené, proto si musí zákazník počkat tři týdny na opravu komponenty.<br />
Vím, že je kód této třídy ve špatné kvalitě, ale není to můj problém. Obrať se na autora!<br />
Už teď se mi při pomyšlení na refaktoring Robertova kódu dělá špatně! Tohle po mně vážně nechtěj!<br />
Jsem specialista na UI a nebudu zasahovat Martinovi do kódování middleware.<br />
Ludva se otrávil methylalkoholem a oslepl. Bude trvat týdny, než to někdo převezme. <br />
</i>
</p>
<p>
Pokud se váš vývojový tým dostává do podobných situací, zřejmě by vám pomohlo praktikování <i>společného vlastnictví kódu</i> (Collective Code Ownership).
Jedná se o jednu z technik metodiky extrémního programování (XP). Jednoduše by se dalo CCO definovat takto:
</p>
<p>
<i>"Všichni sdílí zodpovědnost za kvalitu kódu. Každý může udělat změnu v jakékoli části kódu. Od všech se očekává, že odstraní problémy, na které v kódu narazí."</i>
</p>
<p>
Pojďme se podívat, jakou přidanou hodnotu nám společné vlastnictví přináší.
</p>
<h2>Vyšší kvalita kódu</h2>
<p>
V socialismu se kolektivní vlastnictví příliš neosvědčilo.
Ve výsledku všechno patřilo všem a nikomu a stav věcí podle toho vypadal. Vývojový tým je však specifická struktura, která při správném vedení
a správných charakterových vlastnostech jejich členů, dosahuje spoluprácí vyšší výkonnosti. Skupinová zodpovědnost vede k tomu, že vývojáři usilují společně o vysokou kvalitu kódu.
Špatný kód napsaný kolegou je i můj špatný kód. Kolega by měl pod závazkem společného kódu cítit větší zodpovědnost a snažit se o potřebnou kvalitu.
Já bych naopak měl na nekvalitní kód upozornit a nebo jej přímo zlepšit. Třeba refaktoringem nebo vylepšením návrhu.
</p>
<p>
Pokud je váš kód zveřejňován a běžně posuzován jinými lidmi, zvyšuje se vaše motivace ke kvalitnější práci. Profesionální vývoj software je o osvojení
správných návyků. Nad návyky nepřemýšlíte, děláte je automaticky. Pokud jste junior vývojář, bude pro vás práce v týmu s CCO obrovskou školou. Na druhou
stranu někteří senior vývojáři mohou mít problém s tím, že někdo jiný jim vidí do kódu a navíc si ho dovoluje měnit! Považují svůj kód za natolik intimní záležitost,
že si ji brání jako poklad. Někdy je to také z důvodu, že jejich kód je nečitelný, tedy špatný a sami to vědí.
</p>
<p>
Poznámka: Mezi atributy externí kvality kódu patří bezchybnost, použitelnost, efektivita, spolehlivost, integrita, přizpůsobivost, přesnost a robustnost.
Mezi atributy interní kvality kódu patří udržovatelnost, flexibilita, přenositelnost, znovupoužitelnost, čitelnost, testovatelnost, srozumitelnost.
</p>
<h2>Vzájemná zastupitelnost</h2>
<p>
Tradičním problémem vývojových týmů je koncentrace znalostí pouze u konkrétních lidí.
Autor komponenty je jediný, kdo zná její kód a pro ostatní se jedná o černou skříňku.
Někomu pocit nepostradatelnosti může dělat dobře, ale pro flexibilitu vývoje je to špatně. Dovolená, nemoc nebo jiná absence zablokuje práce na komponentě
na dlouhou dobu. Úplná ztráta člena týmu pak může způsobit katastrofu.
</p>
<p>
Společné vlastnictví kódu tyto problémy řeší poměrně efektivně. Dobrá znalost codebase je dovedností každého člena týmu. Oprava chyby, doplnění funkcionality
nebo jiný zásah do kódu někým jiným než autorem? Není problém. Ty máš čas, tak to prosím udělej.
</p>
<h2>Co vlastně potřebujeme?</h2>
<p>
Společné vlastnictví kódu nelze efektivně aplikovat bez dalších podpůrných technik XP. Jinak se výsledek může významně lišit od našeho očekávání.
</p>
<p>
Vývojáři si musejí rozumět. Jejich kód musí být vzájemně snadno pochopitelný. Je nutné zavést <i>jednotný kódovací styl</i> (Coding style). Měly by se ctít zásady
<i>čistého kódu</i> (Clean Code) a <i>jednoduchého návrhu</i> (Simple Design). Vysoká čitelnost kódu je zásadní požadavek na práci profesionálního vývojáře. V případě CCO
je jeho důležitost ještě umocněna.
</p>
<p>
Kvalita existujícího kódu je přírůstkově vylepšována postupným <i>refaktoringem</i> (Refactoring).
Refaktoring úzce souvisí s pokrytím kódu pomocí testů. XP aplikuje metodiku
<i>testy řízeného vývoje</i> (Test-Driven Development). Bez správného pokrytí kódu jednotkovými testy se nedá CCO použít. Vycházíme-li z definice CCO, kdy každý má
právo a povinnost kód vylepšit (refaktorovat) a rozšířit, je regresní funkce jednotkových testů nenahraditelná. Pokud by testy nad kódem nebyly, každý by se bál
do stávajícího kódu zasáhnout.
</p>
<p>
Další úrovní zajištění je technika <i>postupné integrace</i> (Continuous Integration). Po každém promítnutí změny v kódu do společného prostoru je proveden kontrolní
serverový integritní build, jehož součástí by mělo být i spuštění jednotkových testů. V případě zanesení problémů je autor změny ihned vyzván k opravě.
Touto technikou je zajištěna integrační validita kódu na týmovém serveru.
</p>
<p>
Tým by měl používat <i>verzovací systém</i> (Version Control) pro správu zdrojového kódu s podporou vícenásobného checkoutu. Při CCO dochází častěji k situaci, kdy více uživatelů
v jednom období edituje lokálně stejný objekt. Systém by měl mít kvalitní nástroj pro následné slučování změn. Doporučuje se u existujícího kódu dělat úpravy menšího rozsahu
a tím pádem častěji vracet změny na server.
</p>
<p>
Efektivní podpůrnou technikou je <i>párové programování</i> (Pair Programming). Programování ve dvojicích zlepšuje komunikaci, urychluje šíření znalostí v týmu, díky
online revizím návrhu a kódu zvyšuje výslednou kvalitu. Většina kombinací [nováček|pokročilý|expert]{2} je ve výsledku efektivní, kromě nováček + nováček - mentor.
Páry by se měly měnit a je nutné vytvořit unifikované programové prostředí u všech párovačů. Není nutno párovat po celou dobu práce.
</p>
<h2>Rizika</h2>
<p>
Nedostatečná znalost problematiky jednoho z členů týmu může způsobit problematický zásah do existujícího kódu. Jako pojistky máme jednotkové testy,
které by zároveň měly dokumentovat návrh příslušné části systému. V případě, že znalosti člena týmu jsou špatné, mohlo by zabrat nasazení párového programování.
</p>
<p>
Nikdo se nehlásí k zodpovědnosti za daný kód (No Code Ownership). Takového rizika se mohou obávat především projektoví manažeři. Všem zúčastněným musí
být zřejmé, že zodpovědnost za každou část leží na celém týmu. Postoje typu "Já mám svůj kód v pořádku a tento mě nezajímá" je potřeba eliminovat.
</p>
<p>
Nedodržení souvisejících agilních technik oslabí výhody CCO a možná jej úplně zabije. Je na zodpovědnosti vedoucího týmu,
aby zajistil vytvoření a provoz správně nastaveného agilního prostředí.
</p>
<h2>Alternativy</h2>
<p>
Pokud se codebase striktně rozdělí podle členů týmu a vzájemně si do kódu nezasahují, mluvíme o silném vlastnictví (Strong Code Ownership).
Méně striktní je slabé vlastnictví (Weak Code Ownership). Kód je stále rozdělen podle správců jednotlivých komponent, ale jiný člen týmu může
po svolení od správce kód změnit.
</p>
<h2>Závěrem</h2>
<p>
Pro malé a agilně řízené týmy se jeví CCO jako přirozené řešení požadavků na kvalitu a zastupitelnost.
U korporátních neagilně řízených týmů by se na propagátora CCO mohli dívat jako na Marťana, můžete to zkusit. :)
Pokud pro vás není agilita sprosté slovo, určitě stojí za to se nad dopady CCO zamyslet.
</p>
<p>
Rád bych článek doplnil o nějaké praktické postřehy, ale ve firmě se nám zatím nepodařilo vytvořit dostatečné prostředí pro provozování společného vlastnictví kódu.
Výhody jsou zřejmé a rádi bychom stávající slabé vlastnictví přetransformovali na společné. Pokud máte vlastní zkušenost, prosím o připojení komentáře. Děkuji.
</p>
<h2>Zdroje</h2>
<p>
<a href="http://jamesshore.com/Agile-Book/collective_code_ownership.html">The Art of Agile Development: Collective Code Ownership</a> - můžete si přečíst
odpovědi na otázky, které zřejmě vznese každý, kdo o přechodu na CCO uvažuje.
</p>Robert Dreslerhttp://www.blogger.com/profile/16401744220939465418noreply@blogger.com1tag:blogger.com,1999:blog-3408745507091232422.post-42856392569303748502012-08-24T21:47:00.001+02:002012-08-25T08:34:41.108+02:00Jednoho produktivního vývojáře prosím!<p>
<div class="separator" style="clear: both; text-align: center;">
<img border="0" width="150" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgaEOd0ftUESXacUZRiTvgA56vXB0mn3dUkQb93L75uXrcT8kxxJGl4ijsPL2z-k3Pf3loB8vt4KJPTbcrnsy8lmgDpIdHmG2cOeC3QUJ3pIiHu3OZEXI1-6pQNb5-1rehXF7XzN-rLNAOO/s200/dreamstime_xs_248739232%255B1%255D.jpg" style="border:none;box-shadow:none;vertical-align:bottom;horizontal-align:center;" /></div>
</p>
<p>
<i>
Jak velký je rozdíl mezi slabým, průměrným a vynikajícím vývojářem? Kolik průměrných vývojářů zastoupí jednoho excelentního?
O kolik člověkodnů dokončíme projekt rychleji přidáním dalšího vývojáře?
</i>
</p>
<p>
Odpovědi na tyto otázky samozřejmě nelze exaktně vyčíslit. Někdo by dokonce mohl říci, že v IT se nedá nic pořádně odhadovat a tak se o to ani nebude pokoušet.
Můžeme se ale na problém výkonnosti vývojářů podívat přes jejich produktivitu a posoudit efekt jednotlivých manažerských zásahů na rychlost práce vývojového týmu.
</p>
<h2>Produktivita vývojáře</h2>
<p>
Strohá definice říká, že produktivita vývojáře je (ekonomický) ukazatel mezi výsledkem (softwarový produkt) a časem potřebným k jeho dosažení. Podle této
definice bychom se měli snažit produkovat software za co nejkratší dobu. Samozřejmě s dodržením akceptačních kritérií na funkční
a nefunkční požadavky. Měli bychom také zajistit dostatečnou vniřní kvalitu systému, která nám u dlouhodobých projektů zjednoduší jejich údržbu a následný rozvoj.
</p>
<p>
Výslednou produktivitu vývojáře ovlivňuje velké množství faktorů. Patří mezi ně odborné znalosti, zkušenosti z jiných projektů, dovednosti v používání nástrojů, intuice v rozhodování, schopnost správného výběru z mnoha alternativ, soft skills, pracovní prostředí, vhodné nástroje a mnoho dalších.
</p>
<h2>Opravdu kvalitní vývojáři jsou mnohem produktivnější než ti průměrní</h2>
<p>
Někteří zkušení projektoví manažeři tvrdí, že vynikající vývojář je až o řády produktivnější než průměrný vývojář. Vzhledem k tomu,
že vývoj software je vysoce komplexní záležitost, dá se tomuto tvrzení věřit. Co se naprogramuje dnes, stane se základem pro zítra.
Pokud tedy pokládá základy určité části systému méně disponovaný vývojář, může být jeho práce nedostatečně kvalitní a ve výsledku neproduktivní.
Stavět na takto chatrných základech je pak pro ostatní velice neefektivní. Situace si někdy vynutí velký zásah nebo dokonce kompletní předělání,
samozřejmě s výrazným navýšením pracnosti.
</p>
<p>
Vývoj software prochází několika fázemi (specifikace požadavků, analýza, návrh, implementace, testování, nasazení do provozu, údržba).
Chyby a nerespektování požadavků v jednotlivých fázích mohou mít velké časové a ekonomické dopady. Výborný vývojář používá efektivně
postupy a nástroje, které chyby eliminují. Tím tráví méně času řešením následných defektů zanesených do systému v předchozích fázích.
</p>
<h2>Přidám lidi, zrychlím projekt</h2>
<p>
Tento mýtus IT managmentu je dost rozšířený. Pokud zapojíte další skladníky do nakládky kamionu, jistě se celá akce urychlí (pokud se nepoperou o ještěrku :)).
Ale vývoj software není pásová výroba. Tam takové pravidlo neplatí.
</p>
<p>
Přidáním vývojáře dojde z krátkodobého hlediska spíše ke zpomalení týmu. Stávající členové totiž musí věnovat určitý čas na zaškolení nováčků a
jejich uvedení do problematiky. Pokud navíc přidáte slabého vývojáře, jeho nekvalitní a pomalá práce může snížit efektivitu ostatních.
S navýšením počtu členů týmu také roste zátěž manažera v koordinací lidí. Množství komunikačních kanálů roste exponenciálně podle počtu lidí.
Podle vzorce n(n-1)/2 určíme, že např. pro tým 12 lidí, bude muset manažer udržovat 66 komunikačních vztahů.
</p>
<p>
Někdy je vhodnější slabého člena z týmu odebrat než se snažit přidat dalšího průměrného vývojáře.
Výborným vývojářům se uvolní ruce od zátěže s neproduktivním vývojářem a sami pak odvádějí lepší práci. V tomto případě tedy platí, že méně je více.
</p>
<h2>Jak tedy urychlit vývoj?</h2>
<p>
<ul>
<li>Určitě se soustřeďte na personální kvalitu Vašeho týmu. Věnujte více peněz na výběr excelentních členů.</li>
<li>Investujte do školení a dalších forem zvyšování produktivity. </li>
<li>Nespoléhejte jenom na průměrné vývojáře. Nemůžete na nich stavět projekt, který má být úspěšný. V IT neplatí, že průměrný tým odvede ve výsledku průměrnou práci. Výsledek může být mnohem problémovější.</li>
<li>Poskytněte vývojářům kvalitní nástroje, které zefektivní jejich práci.</li>
<li>Nezmatkujte a neurychlujte krátkodobě vývoj přidáváním dalších vývojářů. Hledejte důvody, proč je projekt v prodlení a odstraňujte překážky.</li>
<li>Zbavte se slabých vývojářů a nebudete je muset hlídat.</li>
</ul>
</p>
<h2>Zdroje</h2>
<p>
K napsání příspěvku mě inspirovala úvaha Neala Forda <a href="http://programmer.97things.oreilly.com/wiki/index.php/Developer_Productivity_Mean_vs._Median">Developer Productivity Mean vs. Median</a>.
</p>Robert Dreslerhttp://www.blogger.com/profile/16401744220939465418noreply@blogger.com0tag:blogger.com,1999:blog-3408745507091232422.post-17923516926757310592012-07-30T23:29:00.000+02:002012-07-31T15:16:11.952+02:00Tell, Don't Ask<p>
<b>... aneb snižujte závislosti mezi třídami</b>
</p>
<div class="separator" style="clear: both; text-align: center;">
<img border="0" height="60" width="60" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEheOJRqENKzuQ2lRboSwY6DhBIY-LSWW_tORnAhXOqvQvD3jiyCMFsXFoOtknnaO99O3NZM4orUY0oPUHy48oxF9ye7ntqmcTHXNYgoIPfwQOzw6pK0iXGndiUx2lEN5qDTDK9BOBMn2nJZ/s200/NoQuestions%255B1%255D.png"
style="border:none;box-shadow:none;vertical-align:bottom;horizontal-align:center;" /></div>
<p>Jedna z možných definic návrhového principu <b>Tell, Don't Ask</b> (TDA) zní takto:</p>
<p><i>"Každé rozhodování zcela závislé na vnitřním stavu objektu by mělo být prováděno uvnitř tohoto objektu."</i>
<p>Princip hovoří o tom, že bychom měli navrhovat třídy tak, aby se volající strana nemusela dotazovat na záležitosti týkající se vnitřního stavu volané třídy.</p>
<h2>Ukázka porušení TDA</h2>
<p>Mějme zjednodušený autobusový rezervační systém:</p>
<p>
<pre style="font-family: consolas"><span style="color: blue">class</span> <span style="color: #2b91af">Bus</span><br/>{<br/> <span style="color: blue">private</span> <span style="color: blue">int</span> numberOfSeats;<br/> <span style="color: blue">private</span> <span style="color: #2b91af">IList</span><<span style="color: #2b91af">Passenger</span>> passengers = <span style="color: blue">new</span> <span style="color: #2b91af">List</span><<span style="color: #2b91af">Passenger</span>>();<br/> <br/> <span style="color: blue">public</span> Bus(<span style="color: blue">int</span> numberOfSeats)<br/> {<br/> <span style="color: blue">this</span>.numberOfSeats = numberOfSeats;<br/> }<br/> <br/> <span style="color: blue">public</span> <span style="color: blue">bool</span> HasFreeSeat<br/> {<br/> <span style="color: blue">get</span><br/> {<br/> <span style="color: blue">return</span> numberOfSeats > passengers.Count;<br/> }<br/> }<br/> <br/> <span style="color: blue">public</span> <span style="color: blue">void</span> AddPassenger(<span style="color: #2b91af">Passenger</span> passenger)<br/> {<br/> passengers.Add(passenger);<br/> }<br/>}<br/> <br/><span style="color: blue">class</span> <span style="color: #2b91af">BusReservation</span><br/>{<br/> <span style="color: blue">public</span> <span style="color: blue">void</span> AddPassengerToBus(<span style="color: #2b91af">Bus</span> bus, <span style="color: #2b91af">Passenger</span> passenger)<br/> {<br/> <span style="color: blue">if</span> (bus.HasFreeSeat)<br/> {<br/> bus.AddPassenger(passenger);<br/> }<br/> }<br/>}</pre>
</p>
<p>
Proč je uvedené řešení problematické:
</p>
<p>
<ul>
<li>Základním principem OOP je zapouzdřenost interních dat objektu a jeho chování. Třída <code>Bus</code> však zbytečně zveřejňuje informaci o volných sedadlech
a nutí volající stranu, aby s touto informací pracovala a zohledňovala ji před voláním metody <code>AddPassenger</code>.</li>
<li>Třída <code>BusReservation</code> je závislá na třídě <code>Bus</code> na dvou místech. Dotazováním na vlastnost <code>HasFreeSeat</code> a voláním metody <code>AddPassenger</code>.
Každá nadbytečná závislost mezi třídami zvyšuje komplexitu návrhu a zhoršuje vlastnosti systému.</li>
<li>Třída <code>Bus</code> nutí volající stranu, aby měla znalost o tom, že před zavoláním <code>AddPassenger</code> si musí nejprve sama ověřit splnění kontraktů přidání cestujícího.
S tím souvisí i závislost na správném pořadí volání. Samostatné volání <code>HasFreeSeat</code> nedává smysl.</li>
<li>Co když se v budoucnu změní podmínky, za kterých je možné přidat cestujícího? Nyní je přidání závislé pouze na volném sedadle, ale nově může přibýt podmínka typu
"je autobus pojízdný". Pak bude nutné doplnit test na vlastnost <code>IsMobile</code> na všechna místa volání <code>AddPassenger</code>.</li>
<li>Každá nadbytečná závislost zvyšuje komplexitu jednotkových testů. Pokud chceme testovat třídu <code>BusReservation</code> v izolaci, musíme mockovat třídu <code>Bus</code>
(nebo lépe rozhraní). V našem problematickém případě musíte přidat chování mocku pro vlastnost <code>HasFreeSeats</code> a metodu <code>AddPassenger</code>.</li>
</ul>
</p>
<h2>Vhodnější řešení</h2>
<p>
Odstraníme závislost volající třídy na dotazování se na volné sedadlo. Veškeré testy na proveditelnost akce přidání cestujícího jsou zapouzdřeny uvnitř metody
<code>AddPassenger</code>. Pokud některá z podmínek není splněna, je vrácena výjimka, kterou zpracuje volající strana. Volající straně se situace zjednoduší.</p>
<p>
<pre style="font-family: consolas"><span style="color: blue">class</span> <span style="color: #2b91af">Bus</span><br/>{<br/> <span style="color: blue">private</span> <span style="color: blue">int</span> numberOfSeats;<br/> <span style="color: blue">private</span> <span style="color: #2b91af">IList</span><<span style="color: #2b91af">Passenger</span>> passengers = <span style="color: blue">new</span> <span style="color: #2b91af">List</span><<span style="color: #2b91af">Passenger</span>>();<br/> <br/> <span style="color: blue">public</span> Bus(<span style="color: blue">int</span> numberOfSeats)<br/> {<br/> <span style="color: blue">this</span>.numberOfSeats = numberOfSeats;<br/> }<br/> <br/> <span style="color: blue">private</span> <span style="color: blue">bool</span> HasFreeSeat<br/> {<br/> <span style="color: blue">get</span><br/> {<br/> <span style="color: blue">return</span> numberOfSeats > passengers.Count;<br/> }<br/> }<br/> <br/> <span style="color: blue">public</span> <span style="color: blue">void</span> AddPassenger(<span style="color: #2b91af">Passenger</span> passenger)<br/> {<br/> <span style="color: blue">bool</span> isFull = !HasFreeSeat;<br/> <br/> <span style="color: blue">if</span> (isFull)<br/> {<br/> <span style="color: blue">throw</span> <span style="color: blue">new</span> <span style="color: #2b91af">Exception</span>(<span style="color: #a31515">"Bus is full."</span>);<br/> }<br/> <br/> passengers.Add(passenger);<br/> }<br/>}<br/> <br/><span style="color: blue">class</span> <span style="color: #2b91af">BusReservation</span><br/>{<br/> <span style="color: blue">public</span> <span style="color: blue">void</span> AddPassengerToBus(<span style="color: #2b91af">Bus</span> bus, <span style="color: #2b91af">Passenger</span> passenger)<br/> {<br/> bus.AddPassenger(passenger);<br/> }<br/>}</pre>
</p>
<h2>Vezměte si na pomoc Adapter</h2>
<p>
Pokud využíváte rozhraní, které nemůžete měnit (komponenta třetí strany) a které porušuje TDA, můžete si pomoci návrhovým vzorem <a href="http://www.dofactory.com/Patterns/PatternAdapter.aspx">Adapter</a> (Wrapper).
Např. v jazyce C# je za příkazem <code>foreach</code> schován adaptér, který zjednodušuje práci se vším, co zveřejňuje metodu <code>IEnumerator GetEnumerator()</code>.
Z <code>IEnumerator</code> pak postupně volá metodu <code>bool MoveNext()</code> a dotazuje se na vlastnost <code>object Current { get; }</code>. Více na <a href="http://stackoverflow.com/a/398996">stackoverflow.com</a>.
</p>
<h2>Závěrem</h2>
<p>Tak jako většina principů a doporučení objektového návrhu, tak i TDA není možné bez rozmyslu aplikovat dogmaticky ve všech situacích.
Záleží na zodpovědnosti navrhované třídy, zda-li poskytuje <b>příkazy</b> (commands) k vykonání nějaké akce nebo <b>dotazy</b> (queries) vracející vnitřní stavy objektu.
V případě příkazů byste však měli o dodržování principu TDA usilovat.</p>Robert Dreslerhttp://www.blogger.com/profile/16401744220939465418noreply@blogger.com4tag:blogger.com,1999:blog-3408745507091232422.post-21577219763214339882012-07-09T23:06:00.001+02:002012-07-09T23:08:53.336+02:00Peníze až na čtvrtém místě<div class="separator" style="clear: both; text-align: center;"><img border="0" height="100" width="100" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhfYYYg6J1-1zx5g8nf8jxWr_0mI0vkOBwJaPdeeDdjoG4SMual4s9tPp-_HJdXk0O3Fqc2y76IWGjE-n-Ci5r1M3ZYJ6PFWB_NDvzyx_ZLpVX-6MA4FOWEwCsrddfQEBR7fX6VOyhNArE6/s200/bigstock_Self_Motivation_Golden_Dollar_2032755%255B1%255D.jpg" style="border:none;box-shadow:none;vertical-align:bottom;horizontal-align:center;" /></div>
<p>Richard Florida ve své knize <i>The Rise of the Creative Class</i> zveřejnil zajímavé výsledky výzkumu o motivování lidí.
Více jak 20 000 pracovníků z IT mělo z celkem 38 různých faktorů vybrat ty, které je nejvíce ovlivňují a motivují v jejich práci.
Top 10 vypadá takto:</p>
<p>
<ol>
<li>Náročnost úkolů a zodpovědnost</li>
<li>Flexibilita</li>
<li>Stabilní pracovní prostředí</li>
<li>Peníze</li>
<li>Profesní rozvoj</li>
<li>Uznání kolegů</li>
<li>Motivující spolupracovníci a nadřízení</li>
<li>Vzušující náplň práce</li>
<li>Firemní kultura</li>
<li>Umístění a komunita</li>
</ol>
</p>
<p>
Pokud na výsledky pohlížíte z perspektivy zaměstnance, snáze pochopíte, v jakém prostředí může vyniknout Váš kreativní potenciál.
Máte-li na výběr, hledejte firmu, která nabízí zajištění co nejvíce motivátorů ze seznamu. Pokud ve Vaší stávající firmě není splněna
většina věcí ze začátku seznamu, měli byste se vážně zamyslet, zda-li v takové firmě chcete nadále ztrácet svůj čas.</p>
<p>
Průzkum by měl být přínosný také pro zaměstnavatele a vedoucí týmů. Pokud chtějí z lidí dostat maximum a zajistit jejich spokojený pracovní život,
měli by realizovat opatření, která napomáhají motivovat. Nerespektování těchto faktů obvykle zabíjí inovaci, zvyšuje fluktaci lidí a v konečném důsledku
snižuje úspěšnost firmy.</p>
<p>Florida nám předkládá potvrzení faktu, že peníze nejsou dostatečným dlouhodobým motivátorem u kreativních lidí. V určité fázi pracovního vývoje totiž můžete zjistit,
že přestože vyděláváte slušný balík, nejste spokojeni. Dostali jste se zřejmě na úroveň, kdy základní potřeby včetně finančních jsou uspokojeny, ale
potřebujete navíc uspokojit Vaše seberealizační potřeby nejvyšší úrovně (viz. 4. a 5. patro
<a href="http://cs.wikipedia.org/wiki/Maslowova_pyramida">Maslowovy pyramidy potřeb</a>).</p>
<p>Pokud Vás zajímá problematika podpory kreativity v současné éře inovativní ekonomiky, můžete si přečíst knížku <a href="http://www.melvil.cz/kniha-nepostradatelni-linchpin">Nepostradatelní</a> od Jan Melvil publishing.
Seth Godin na mně působil zpočátku trochu jako otravný provokatér, ale s postupem času jsem na jeho hru přistoupil a začalo se mi to líbit. Doporučuji.</p>Robert Dreslerhttp://www.blogger.com/profile/16401744220939465418noreply@blogger.com0tag:blogger.com,1999:blog-3408745507091232422.post-23250265274600840602012-05-19T07:17:00.000+02:002012-05-23T09:23:42.864+02:00Produktivní rychlokodér<p><b>... aneb ovládněte základy Vašeho řemesla</b></p>
<div class="separator" style="clear: both; text-align: center;"><img border="0" height="66" width="200" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjgIooNWtAsHQUXmPekPH3kuPIvnpFvQpxUm05rMwCYo3pure841XRs27tbxh-N4Xl3kdpe7HSAIGWFanBrUVKwhh0sD-MXVMxYc031bjOG8kbvgclSa7o2iK_tYTDG6Yk_nSfBlb3j1q5e/s200/400px-Touch_typing.svg%255B1%255D.png" /></div>
<p><i>Je součástí Vaší profese vytváření programového kódu? Píšete kód produktivním způsobem? Znáte a používáte nástroje, které Vám pomáhají produktivitu zvyšovat?
Saháte často při psaní kódu na myš?</i></p>
<p>Stává se téměř denně, že objevím nějakou novou fintu, kterou se snažím využít pro zlepšení své produktivity.
Může se jednat o novou klávesovou zkratku, nový nástroj, novou techniku, zrychlení často se opakujícího postupu, apod.
Pokud chceme svoji práci dělat co nejlépe, je potřeba systematicky pracovat na zvyšování naší kodérské produktivity. </p>
<p>Tento příspěvek se týká aspektů rychlosti vytváření programového kódu. Rád bych shrnul elementární dovednosti, které jsou nutným základem pro práci kodéra.
Příklady v textu se týkají platformy Visual Studia, kterou používám. Předpokládám však, že pro jiná IDE existují ekvivalentní nástroje.</p>
<h2>Hbité kodérovy prsty</h2>
<p><i>Kolika prsty píšete a jak rychle? Díváte se při psaní na klávesnici? Děláte často chyby a musíte se při psaní vracet o odmazávat?</i></p>
<p>Někdo nepovažuje <b>rychlost psaní</b> u kodéra za příliš důležitou. Sami však tušíte, že je rozdíl mezi datlováním dvěma prsty a symfonií všech deseti.
Rychlost se uvádí v <a href="http://cs.wikipedia.org/wiki/%C3%9Ahoz">úhozech</a> (keystrokes) za minutu nebo v počtu napsaných slov za minutu (WPM).
Změřte si svou rychlost např. na <a href="http://10fastfingers.com/typing-test/english">http://10fastfingers.com</a>.
Průměr je mezi 50 a 70 wpm. Pokud se dostanete nad 100 wpm, patříte mezi 20% nejrychlejších psavců. Raději nebudu uvádět kolik jsem naměřil sobě. :)</p>
<p>A jak tuto dovednost zlepšovat? Zkuste se naučit <a href="http://cs.wikipedia.org/wiki/Hmatov%C3%A1_metoda_ovl%C3%A1d%C3%A1n%C3%AD_kl%C3%A1vesnice_deseti_prsty">hmatovou metodu</a>,
která využívá všech deseti prstů. Pořiďte si ergonomickou klávesnici, která Vám bude vyhovovat.</p>
<p>Můžete si také přečíst, co si o dovednostech pro psaní textu myslí respektovaný Jeff Atwood v příspěvku <a href="http://www.codinghorror.com/blog/2008/11/we-are-typists-first-programmers-second.html">We Are Typists First, Programmers Second</a>.</p>
<h2>Učte se klávesové zkratky a nesahejte na myš</h2>
<p>Důležitost konkrétní <b>klávesové zkratky</b> pochopíte v momentě, kdy se ji naučíte. Od tohoto okamžiku se bez ní neobejdete.
Zkratka většinou supluje akci, kterou můžete udělat myší nebo posloupností více klávesových akcí. Obě metody jsou obvykle pomalejší než zkratka (od toho je to zkratka :).
Základní sadu klávesových zkratek má vaše IDE, další dodají dodatečná rozšíření. Pro Visual Studio platí, že základ je sice ok, ale teprve s
rozšířením typu CodeRush nebo ReSharper povýšíte z akumulační vrtačky na pořádnou příklepovku! Investice do kvalitních rozšíření se určitě vyplatí.</p>
<p>Doporučuji vytisknout cheat sheety s přehledem klávesových zkratek Vašeho IDE a rozšíření. Zdroje pro
Visual Studio (<a href="http://www.microsoft.com/en-us/download/details.aspx?id=13189">Microsoft</a>,
<a href="http://www.dofactory.com/ShortCutKeys/ShortCutKeys.aspx">DoFactory</a>),
<a href="http://www.devexpress.com/Products/Visual_Studio_Add-in/Coding_Assistance/shortcut_sheets.xml?trk_event=search_ac&trk_pos=16&trk_model=open_graph_object&trk_len=5">CodeRush</a> a
<a href="http://www.jetbrains.com/resharper/webhelp/Reference__Keyboard_Shortcuts.html">ReSharper</a>.
Postup učení pak může být takový, že si nejprve přečtete referenční přehled zkratek, abyste dostali do podvědomí, co všechno se dá "zkracovat".
Pak se snažíte před každou požadovanou akcí vzpomenout si na příslušnou zkratku. Několikrát požádáte papír o nápovědu a podle konkurenceschopnosti
vaší střednědobé paměti si zkratku zapamatujete. Zkratek bývá velké množství a jsou strukturovány do menších oblastí. Zřejmě i zde platí Paretovo pravidlo, že 20% zkratek budete využívat v 80% případů.
Naučte se tedy alespoň těch 20%.</p>
<h2>Automatické doplňování a kontextový našeptávač</h2>
<p>Ve VS je k dispozici nástroj <b><a href="http://msdn.microsoft.com/en-us/library/hcw1s69b.aspx">IntelliSense</a></b>.
Podle aktuálního kontextu, části zadaného jména a s využitím reflexe, Vám například nabídne rychlé vložení příslušného jména identifikátoru.
Předpokládám, že není nikdo, kdo by nabízenou pomoc od IntelliSense odmítal. Ne každý však umí IntelliSense vyvolat explicitně (<kbd>Ctrl</kbd> + <kbd>J</kbd>),
zobrazit si informace o metodě a jejích parametrech (<kbd>Ctrl</kbd> + <kbd>Shift</kbd> + <kbd>Spacebar</kbd>), apod.</p>
<h2>Vkládání bloků kódu</h2>
<p>Psaní kódu není psaní beletrie, ale má charakter kompozice jednoduchých opakujících se bloků kódu do složitějších celků.
Nabízí se tedy s těmito bloky pracovat efektivněji. Ve většině IDE je k dispozici podpora <b>code snippetů</b>.
Jedná se o předpřipravené kusy kódu s možností definice parametrických částí. Vložení těchto kusů kódu
provedete zadáním zkratky snippetu a odesláním řídícího znaku (ve VS tabulátoru). Napište např. <code>foreach</code> a stiskněte tabulátor.
Editor v IDE Vám doplní celý blok příkazu foreach s možností změnit názvy parametrizovatelných částí.</p>
<p>V základu vašeho IDE je k dispozici množina předdefinovaných snippetů. Zajímavé jsou však i snippety, které si vytvoříte sami. Pokud používáte nějakou typickou
sekvenci nebo blok kódu, určitě si pro něj vytvořte snippet. VS nemá ideální podporu pro vytváření vlastních snippetů a proto musíte vzít zavděk některými externími editory.
Např. <a href="http://snippy.codeplex.com/">Snippy</a> nebo <a href="http://snippeteditor.codeplex.com/">Snippet Editor</a>.
Doporučuji vytvořit snippety pro Váš projekt a spravovat je centrálně v repository. Budou je mít k dispozici všichni členové týmu.</p>
<p>Rozšíření CodeRush nabízí aparát <b>šablon</b>. V daném kontextu je k dispozici zkratka, která odpovídá klíčovému slovu, názvu datového typu nebo
nějaké složitější sekvenci. Stačí pak zadat např. <code>t</code> a po stisku mezerníku bude doplněno <code>true</code>.
Šablony jsou inteligentní a jajich použití je variabilní a uživatelsky rozšiřitelné.</p>
<h2>Dogenerování chybějícího kódu</h2>
<p>Poměrně často používám klávesovou zkratku <kbd>Ctrl</kbd> + <kbd>.</kbd>, která podle aktuálního kontextu doplňuje chybějící kód.
Umí doplnit <code>using</code> pro relativně odkazovanou třídu, vygenerovat pole nebo vlastnost třídy, vytvořit kostru neexistující metody (při použití metody shora-dolů),
provést implementaci rozhraní, apod. Bez této funkce (klávesové zkratky) bych se už neobešel.</p>
<h2>Vylepšování kódu pomocí refaktorizace</h2>
<p>Znalost refaktorizačních technik by měla být v repertoáru každého kodéra. Mezi základní techniky patří přejmenování, vyčlenění kódu do samostatné metody,
práce s argumenty metody, apod. Další typy refaktorizací mohou přidat rozšíření. Refaktorizaci použijete v situaci, kdy chcete stávající kód vylepšit
(zlepšit čitelnost a udržovatelnost). Pěkné příklady jsou například na <a href="http://sourcemaking.com/refactoring">sourcemaking.com</a>.</p>
<h2>Generování kódu</h2>
<p>Ke generování větších a složitějších bloků kódu můžete využít podporu T4 šablony. Generovat se dá z logických DSL modelů, z databázových dotazů a dalších kolekcí.
Jedná se o efektivní a dobře použitelný nástroj. Můžete mrknout na <a href="http://www.hanselman.com/blog/T4TextTemplateTransformationToolkitCodeGenerationBestKeptVisualStudioSecret.aspx">ukázku</a>.</p>
<h2>Navigace v kódu</h2>
<p>Umět se rychle dostat na určité místo kódu je neméně důležité jako umět kód vytvářet. Čím je projekt rozsáhlejší, tím jsou nároky na navigaci v kódu vyšší.
Pokud však ovládáte klávesové zkratky pro přechod k deklaraci, na předchozí místo v kódu, do konkrétní třídy, apod. nebude pro Vás tato činnost problém.
Některé techniky, jako například Test Driven Development, vyžadují cyklické provádění stejné posloupnosti akcí. V těchto případech mohou být rozdíly v produktivitě
markantní.</p>
<p>Důležitá je i navigace mezi částmi IDE. Např. přechod do okna s chybami kompilace, do okna s testy, do Solution Exploreru, apod.
Na většinu akcí by opět měly být k dispozici klávesové zkratky. Jen se je naučit.</p>
<h2>Jak se dále zlepšovat?</h2>
<p>
<ul>
<li>Vyzkoušejte párové programování a pečlivě sledujte Vašeho spolukodéra. Snažte se pochytit jeho dobré návyky.</li>
<li>Sledujte blogy, které píší o používání Vašich nástrojů a zvyšování produktivity.</li>
<li>Pokud máte problém, snažte se jej vyřešit automatizací i za cenu (přiměřeně) vyšších startovních nákladů na naučení.</li>
<li>Účastněte se programátorských cvičení typu <a href="http://coderetreat.cz/">CodeRetreat</a>.</li>
<li>Trénujte. ;)</li>
</ul>
</p>Robert Dreslerhttp://www.blogger.com/profile/16401744220939465418noreply@blogger.com3tag:blogger.com,1999:blog-3408745507091232422.post-62096429540297286492012-04-05T18:09:00.000+02:002012-04-05T18:09:33.813+02:00Programová chyba jako test charakteru<div class="separator" style="clear: both; text-align: center;">
<img border="0" height="100" width="99" style="border:none;box-shadow:none;vertical-align:bottom;horizontal-align:center;" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjvjE9UMsCE1ge_7iI1ekwFjYB8ND3VALh6WTd-oiwmo8AXplGie8lA7iL8oXaW0uWGlPXnigrciIobdWspUJ4gzYEjqCjhHjDYCQhLwtgV07w-_BwmFoohqvZa3j5oTnSxTfxjvlQKf5_w/s200/emotions1%255B1%255D.jpg" /></div>
<p>Někdy je zajímavé sledovat, jak programátoři reagují na nahlášení chyby, za kterou jsou zodpovědní. Málo co odhalí
lidský charakter tak, jako chování v relativně krizové situaci. Pokusil jsem se s mírnou nadsázkou popsat
typologií programátorů právě podle jejich reakcí na chybu. Možná se poznáte nebo třeba někoho z vašich kolegů. :)</p>
<h2>Já přeci chyby nedělám</h2>
<p>Zastánce této techniky, pan Božský, se snaží za každou cenu zbavit zodpovědnosti za chybu.
Případné přiznání chyby by mu narušilo vlastní pocit idealismu, který chová vůči své osobě.</p>
<p><i>"Chyba sice nastala v mojí třídě, ale vůbec jsem netušil, že ji budeš používat takto!<br />
To je cílené chování aplikace dle specifikace."</i>
<p>Přestože se aplikace chová objektivně špatně a specifikace vůbec neexistuje.
Dost času ztrácíte tím, že musíte dotyčného přesvědčit o jeho zodpovědnosti za chybu.</p>
<h2>Hulk </h2>
<p>Nahlásit chybu takovému programátorovi se obvykle trochu bojíte. Víte, že jeho počáteční reakce je dost agresivní.
Zbledne, pak zezelená, natlakuje se, začne prskat a hledat nějaký cíl, na který by se mohla svalit část viny za vznik chyby.</p>
<p><i>"Sakra, zase to někdo pořádně neotestoval!<br />Přeci jsem upozorňoval, že úprava může způsobit problémy!<br />
No a co, že jsem to dal k otestování těsně před uzavřením iterace!"</i>
<p>Na hrubý pytel, hrubá záplata :)</p>
<h2>Hlavně nenápadně a zatloukat</h2>
<p>Programátor se doslechne o chybě, rychle ji opraví a tváří se jako by o žádné chybě ani nevěděl.</p>
<p><i>"Mně se chybu nedaří navodit. Prosím prověř (testere) chování v aktuální verzi.<br />Vidíš, že se to chová správně!"</i></p>
<p>Přiznání, že tam chyba opravdu byla, se od něho dobrovolně nedočkáte. Po urgencích se možná přizná,
ale pachuť neupřímnosti zůstává.</p>
<h2>Sebemrskačství</h2>
<p><i>"Hrozně mě ta chyba mrzí! To snad není možné! Jak se to mohlo stát?! Takový jsem si dával pozor!"</i></p>
<p>Každá chyba je pro něho stresovou záležitostí. Každé šlápnutí vedle ještě více sráží jeho již tak nízké sebevědomí.
Pošlete jej na kurs asertivního chování!</p>
<h2>Alibismus ukrytý v pseudosložitosti</h2>
<p>Zaplavit kolegy hromadou nadbytečných informací, které navodí dojem toho, že prostě chyba v tak komplikované situaci musela
zákonitě vzniknout.</p>
<p><i>"Databáze je taková a maková, nastavení bylo netypické, plán optimalizace nepředpokládatelný.
S tím jsem sice mohl počítat, ale těch možných stavů je tolik, bla bla bla ..."</i></p>
<p>Prostě to oprav a neztrácej svůj ani můj čas zbytečným vysvětlováním!</p>
<h2>Jsem z planety pokročilých uživatelů</h2>
<p><i>"Proč se tohle UI uživatelům nelíbí, vždyť je tam tolik funkcí a všechny jsou pěkně vidět naráz?!<br />
Spousta informací pěkně rozmístěná po velkém formuláři.<br />
Barvy jsou dostatečně výrazné, aby upozornily na důležité části UI.<br />
Proč by to nemohlo zobrazit vždy dialogovou zprávu o úspěšném ukončení zpracování."</i></p>
<p>Takový člověk podle sebe a svých subjektivních vjemů chybně předpokládá chování ostatních uživatelů.
Pokud nezná nebo nechápe základní pravidla uživatelské použitelnosti (UX), zkuste mu je vysvětlit.
Ale ať už nediskutuje a upraví to! </p>
<h2>A jaká by měla být správná reakce?</h2>
<p>Jedná se o velmi zjednodušený postup, ale můžete zkusit třeba:</p>
<ol>
<li>Zajistěte si kompletní informace o chybě. Potřebujete znát kontext spuštěné aplikace (zákazník, operační systém, typ prohlížeče, apod.),
postup navození chyby, popis co je vlastně chybou a jak by se měla aplikace správně chovat. Vše by mělo být součástí hlášení o chybě ve
vašem systému na sledování chyb.</li>
<li>Někdo by měl chybu klasifikovat. Určit její závažnost a přiřadit jí prioritu, která ovlivní rychlost její opravy.
Měl by také domyslet nápravná opatření, např. opravu dat v databázi, apod.</li>
<li>Chyba je směrovaná na vás. Objektivně rozhodněte, zda-li je problém opravdu na vaší straně nebo ji směrujte na příslušného správce části aplikace,
se kterou chyba souvisí. Zkuste omezit počet přehazování chyby mezi řešiteli. Ztrácíte čas váš i ostatních.</li>
<li>V rámci řešení můžete získat další informace o důsledcích chyby (výši škody). Zveřejněte tyto informace pro ostatní zainteresované kolegy.
Buďte transaparentní, upřímní a nic nezatloukejte. Zvýšíte tím efektivitu řešení problému.</li>
<li>Odstraňte systémově příčiny problému tak, aby se chyba neopakovala. Přijměte nápravná opatření na související chyby. Napište programový test,
který se bude provádět automaticky a upozorní na případné vrácení podobné chyby.</li>
<li>Informujte o vyřešení chyby. Sdělte právě tolik informací, kolik postižená strana potřebuje vědět. </li>
</ol>Robert Dreslerhttp://www.blogger.com/profile/16401744220939465418noreply@blogger.com0tag:blogger.com,1999:blog-3408745507091232422.post-9421096451075299182012-03-21T21:40:00.000+01:002012-03-21T21:40:13.502+01:00Automatické testování proti databázi<div class="separator" style="clear: both; text-align: center;">
<img border="0" height="100" width="100"
style="border:none;box-shadow:none;vertical-align:bottom;horizontal-align:center;" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEi6KMxmB3VyVSWt4FE_t2OcHnterp4WsUQBjISQ9nsI6mKrpug6MvnibXQTWvhAT4pedAJanmwZ-AgFrcr708XrYlo_9FSbkPhM4WpifdLu4fa8obovFyd2OtPX4nkfLnEKR7sfKmMLhD2A/s200/database.png" /></div>
<p>Proti databázi budete zřejmě spouštět testy pokrývající datovou vrstvu.
U vyšších vrstev aplikace, použijete testovací databázi v situacích, kdy není vhodné datovou vrstvu mockovat.
Testovací databáze se bude hodit v případě zátěžových a výkonnostních testů.
</p>
<h2>Dostupnost testovací databáze</h2>
<p>Testy potřebujete spouštět na pracovních stanicích vývojářů, na buildovacím serveru nebo na jiném počítači, který nemusí být nutně připojen k počítačové síti.
Je obvyklé, že databáze se zpřístupní v okamžiku spouštění testů a po jejich provedení se zahodí. </p>
<p>Není také vhodné, aby více běhových testovacích prostředí přistupovalo na stejnou instanci databáze. Mohly by se vzájemně ovlivňovat v operacích, které nejdou
schovat do transakce (např. DDL příkazy).</p>
<p>Z uvedených důvodů se používají lokální databáze. V odůvodněných případech můžete použít i serverovou instanci databáze, ale toto řešení přináší
jistá omezení plynoucí ze společného přístupu více testovacích klientů.</p>
<h2>Rychlost vytvoření lokální databáze</h2>
<p>Jeden z důležitých požadavků kladených na testy je jejich rychlost provádění. A databázové testy patří mezi ty nejpomalejší. Pokud používáte lokální databázi,
musíte počítat s časovými režijemi na vytvoření instance databáze.</p>
<p>Nejrychleji startují paměťové (in-memory) databáze (např. SQLite) a databáze pracující nad datovými soubory. Pokud je vaše datová vrstva nezávislá na konkrétním
typu databáze, můžete pro účely testů použít některou z rychlých variant, která neodpovídá produkční databázi. Např. u zákazníků běží vaše aplikace na MS SQL Serveru
a na Oracle, ale testujete proti SQLite.</p>
<h2>Jak to funguje u nás</h2>
<p>V naší firmě jsme zvolili testovací databázi stejnou jako produkční a to MS SQL Server. Každý počítač, na kterém chceme spouštět testy, má instalován plnotučný MS SQL Server
nebo alespoň MS SQL Server Express (na vývojářských stanicích). Při této variantě je nutné databázi obnovit (příkaz restore) z lokálního .bak souboru. Naše databáze
má více jak 1000 tabulek a její obnovení trvá do 10 sekund. Optimalizací je to, že databázi obnovujeme pouze jednou, na začátku spouštění sady testů.</p>
<p>Soubor s databází je vytvářen ze serverové databázové instance, ke které je omezený přístup. Jsou na ní spouštěny pouze schválené změnové skripty a přímo na ní se netestuje.
Soubor je uložen v systému pro správu zdrojových kódů a je synchronizován spolu se zdrojovými produkčními kódy a testy na počítač, kde se testy spouští.</p>
<p>Vývoj a spouštění testů probíhá nad více vývojovými větvemi. Pro každou větev je k dispozici kompatibilní databázový soubor s příslušnou strukturou.</p>
<h2>Testovací data</h2>
<p>Aby bylo možné validovat výsledek spuštění každého testu, musí být splněny vstupní podmínky. V případě testů proti databázi musí být k dispozici taková testovací
data, která předpokládá test. Ideální situací je prázdná databáze před testem. Všechna data jsou pak v inicializaci testu do databáze vložena skriptem.
Složitost databázových skriptů se liší podle testovaného problému a složitosti vazeb do podřízených tabulek.</p>
<p>Vyhněte se přípravě testovacích dat pomocí programových tříd. Může se stát, že test selže ve fázi právě této přípravy testovacích dat. Tím se celý test znehodnotí
a chybně indikuje problém, který je zřejmě jinde než v testované části kódu. Navíc zbytečně zvyšujete složitost kódu testů.</p>
<p>Někdy může být výhodné mít v databázi část dat předvyplněných. Jedná se o data, která mají referenční charakter (jsou stejná na všech instalacích) nebo o data,
která využívá většina testů - testovací aplikační uživatelé, testovací osoby, apod. Taková data musí být neměnná a testy s nimi musí počítat.</p>
<p>SQL skripty generující testovací data ukládejte do repository. Jeden skript může být použit pro celou sadu testů. Dokonce si dovedu představit, že skript,
který generuje např. testovací objednávky, bude použit v testech datové vrstvy objednávek i funkcionality WCF služby pro práci s objednávkami.</p>
<h2>Užitečné tipy</h2>
<p>Uzavřete provádění celého testu do transakce, která vždy skončí příkazem rollback. Pro promítnutí změn do databáze použijte příslušnou funkci vašeho
perzistentního frameworku. Např. pro (N)Hibernate je to funkce Flush() databázové relace.</p>
<p>Databázový uživatel, pod kterým spouštíte testy, by měl mít stejná oprávnění jako v produkčním prostředí. Vyhněte se uživatelům s DBA právy a uživateli,
který je vlastníkem databázových struktur. Pod takovými uživateli může test projít, ale v produkci dojde k chybě.</p>
<p>Pokud se chcete vyhnout časově náročné obnově databáze před každým testem, můžete si pomoci "úklidem" databáze. Před nebo po každém testu spustíte skript,
který smaže všechna data. V případě, že se vám daří provádět testy v transakci s rollbackem, nebude zřejmě úklid nutný.</p>
<h2>Závěrem</h2>
<p>Vyberte si vhodnou strategii, která bude vyhovovat vašim potřebám. Efektivní vytváření a spouštění testů zvýší vaši produktivitu práce
a vnese potřebnou jistotu do udržovatelnosti aplikace.</p>Robert Dreslerhttp://www.blogger.com/profile/16401744220939465418noreply@blogger.com5tag:blogger.com,1999:blog-3408745507091232422.post-88436438353918052922012-02-26T18:29:00.002+01:002012-02-27T06:27:06.399+01:00Techniky pro prevenci softwarových chyb<p><b>... aneb chyby se začnou bát vás!</b></p>
<div class="separator" style="clear: both; text-align: center;">
<img border="0" height="100" width="100"
style="border:none;box-shadow:none;vertical-align:bottom;horizontal-align:center;"
src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjb-ESKEnHxnibhmZZ9Cm66X_SkRfgHcqQnxnNkkmyQEcvh8Z6vF3XjcjyjnYmv2Sc53oskN6Q4adwFc7n2vED2IivHomMspfSibXS_7uSznIkGpox23YZ-36cuoYcW19s4wL-OEOt_uJcD/s200/bug.jpg" />
</div>
<p>Chyba, defekt, štěnice, brouk, bug, fail, fault, mistake. Tato slova nám nezní moc libozvučně. Ve své práci vynakládáme nemalé úsilí na jejich
deratizaci. V tomto průřezovém článku jsem se zaměřil na několik preventivních technik. Zdravotní pojišťovny ví, že prevence je levnější než léčba.
Stejně tak si i zkušení vývojáři uvědomují, že čím dříve se chybu podaří diagnostikovat, tím bude její odstranění levnější. Legrace končí, pokud se chyba
dostane až do provozního prostředí.</p>
<p>Chyby na sebe berou mnoho podob. Může se jednat o pád aplikace na neošetřenou chybu některé z komponent, sémantickou nefunkčnost aplikace (chybný výpočet, nesprávná data) nebo nesplnění
nefunkčního požadavku na systém - pomalost, porušení zabezpečení, neškálovatelnost, apod. Chyby mají různou závažnost a některé dokáží způsobit hodně velkou škodu.
Na míře chybovosti je závislé vnímání vaší aplikace uživateli. Je to výrazný faktor úspěšnosti celého vašeho snažení.</p>
<h2>Pište čistý kód</h2>
<p>Krysy žijí v kanálech a švábi v místech, kde je nepořádek a neuklízí se. Softwarové chyby to mají podobně. Více se objevují v kódu, který nedodržuje metodiku
"čistého kódu". Jaký kód je čistý? Kód, který je čitelný, přehledný, dodržuje kódovací standardy, je správně strukturovaný, používají se v něm vhodné názvy,
má správné úrovně abstrakcí v metodách, apod. K technikám čistého kódu se možná dopracujete praxí nebo rychlejším způsobem, přečtením výborné knihy
<a href="http://knihy.cpress.cz/cisty-kod.html">Čistý kód</a> od Roberta C. Martina.</p>
<p>Čistý kód podporuje efektivnější ladění. Pokud např. dodržujete pravidlo, že každá metoda má právě jeden výstupní bod (příkaz return), je snadnější rozmístit ladící body.
Pokud správně strukturujete kód třídy na menší metody a nemícháte více úrovní abstrakce do jedné metody, navigace je rychlejší a případné problémové místo najdete snáze.</p>
<p>Důsledkem aplikace pravidel čistého kódu je především dobrá čitelnost kódu, která snižuje riziko "ukrytí" zákeřných programových chyb už v prvotní fázi psaní kódu.</p>
<h2>Dobrý objektový návrh</h2>
<p>Chybný objektový návrh dokáže hodně zavařit a čím později si chyby uvědomíte, tím více práce si přiděláte. Dobře navržený systém respektuje pravidla návrhové
metodologie SOLID a dalších dobrých návrhových praktik. Rozsáhlejší systémy, které nerespektují dobrý návrh jsou problematicky udržovatelné a vysoce rizikové
při jakémkoliv pozdějším zásahu do kódu. Říkáme, že jsou křehké. Zanesení chyby je vysoce pravděpodobné.</p>
<p>Neobjevujte kolo a naučte se využívat návrhové vzory. Buďte si jistí, že problém, který řešíte, už měly zřejmě stovky vývojářů před vámi. A návrhový vzor je efektivním
řešením tohoto typu problému. Jsou popsány desítky vzorů pro vznik objektů, pro zachycení struktury mezi objekty, pro řízení chování, pro implementaci jednotlivých
vrstev aplikací (datová, obchodní logika, prezentační, ...) a další.</p>
<p>Díky dobrému návrhu zoptimalizujete i další preventivní techniky popsané v tomto článku. Například bez Inversion of Control a programování proti rozhraní (ISP)
byste psali problematicky jednotkové a integrační testy.</p>
<p>Naučte se i antivzory (antipatterns), špatné techniky návrhu. Jejich znalost vás již dopředu bude varovat před chybnými kroky, které by vás jinak stály vyšší
chybovost, čas a prostředky.</p>
<h2>Refaktorizace kódu</h2>
<p>Rekaftorizace kódu je změna struktury kódu, která nemá vliv na jeho celkovou funkčnost. Znalost refaktorizačních technik patří mezi základní dovednosti
vývojáře. Příkladem refaktorizačních technik je přejmenování (proměnné, metody, třídy), vyjmutí části kódu do samostatné metody nebo třídy, změna pořadí
argumentů metody, apod. Nezbytností je, aby vaše IDE podporovalo refaktorizační techniky. Nebojte se refaktorovat vždy, když budete mít pocit, že se kód zlepší.</p>
<p>S využitím refaktorizace dosáhnete čistého kódu a dobrého návrhu. Snížíte složitost částí kódu. Platí pravidlo, že co je složité, je náchylné k vyšší chybovosti.
Dobrý vývojář dokáže i složitý problém implementovat přehledně a "jednoduše".</p>
<p>Hezký popis refaktorizačních technik je k dispozici na serveru <a href="http://sourcemaking.com/">SourceMaking</a>.</p>
<h2>Revize kódu (Code Review)</h2>
<p>Promluvili jste si někdy o svém kódu s kolegou? Bavili jste se, proč jste použili zrovna takovou implementaci? Uvědomili jste si při tom, že by problém šlo
vyřešit lépe nebo jste dokonce objevili chybu? Výborně! Pak jste použili techniku revize kódu. Když se na váš kód podívá někdo jiný,
je to téměř vždy ke prospěchu věci. </p>
<p>Kdy provádět revizi kódu? Ideální by bylo během nebo těsně po vlastní implementaci. Revize kódu je jedním ze základních aspektů párového programování
(Pair Programming). Dvojice společně vyvíjí kód a revize probíhá neustále. Pokud neaplikujete párového programování, můžete nastavit povinnou revizi kódu
při umisťování změn na server. Revizi můžete také provádět v rámci celého vývojového týmu na pracovních poradách.</p>
<p>Jak je revize kódu efektivní? Záleží na úrovni zkušeností vývojáře a "revizora". U začínajících vývojářů budou revize častější a revizorem by měl být zkušený
pracovník. Při revizi kódu vytvořeného zkušeným vývojářem nemusí být objeveno mnoho chyb, ale celý proces může posloužit k tomu,
že posluchačům budou předány zkušenosti a praktické rady.
Technik revizí kódu je více a liší se svojí formálností, obsazením revizního týmu a způsobem evidence nalezených defektů.</p>
<p>Revize kódu má však i svá rizika. V posuzování práce někoho jiného musíte být opatrní, abyste dotyčnému neublížili před ostatními. Chybně provedená veřejná revize
může způsobit konflikty. Měli byste vždy vývojářům, jejichž práce bude revidována, vysvětlit účel a přínosy pro něj i ostatní.</p>
<h2>Statická analýza kódu</h2>
<p>Analýza kódu, která je prováděna bez nutnosti spouštění programu. Jedná se o soubor preventivních technik, které mají odhalit defekty a problémová místa ve vašem systému.
Jak se problémová místa poznají? Například podle složitosti. Jak již bylo uvedeno výše, u složitě kódované části aplikace je pravděpodobnější, že vývojář
zanesl nebo přehlédl chybu.</p>
<p>Problémová místa vám pomáhají určit softwarové metriky orientované na kód a na návrh tříd. Uvedu pár příkladů:</p>
<ul>
<li><a href="http://en.wikipedia.org/wiki/Cyclomatic_complexity">Cyclomatic Complexity</a> vyjadřuje složitost části programu (např. metody) co do množství
větvení a cyklů. Tyto programové konstrukce zvyšují počet možných cest provádění programu. Vysoké číslo indikuje komplikovaně napsané složité metody,
které je problematické pokrývat testy. Řešením je metodu rozbít do více menších metod.</li>
<li><a href="http://en.wikipedia.org/wiki/Source_lines_of_code">Line Count</a> vyjadřuje množství řádků kódu v metodách. Dlouhé metody jsou nepřehledné a
dělají zřejmě více než jednu věc (pro danou úroveň abstrakce). Použitelnost takových metod je problematická, stejně jako pokrytí testy. Řešením je opět
refaktorizace do více metod.</li>
<li>Objektové metriky jako Weighted Method Count (celková složitost metod ve třídě), Depth of Inheritance Tree (počet předků třídy) a
Coupling Between Objects (provázanost mezi objekty) mohou indikovat problémy v objektovém návrhu.</li>
</ul>
<p>Údaje získáné z metrik, by měl vyhodnocovat vedoucí vývojář. Nástroje pro statickou analýzu jsou u komerčních IDE k dispozici ve vyšších edicích.
Pokud máte k dispozici nástroje, které metriky zobrazují přímo v kódu, naučte se je vyhodnocovat a vaši práci podle nich přizpůsobovat již během vlastní implementace.</p>
<p>Mezi techniky statické analýzy patří také validace kódu podle pravidel definovaných pro zdrojový kód. Tato technika zvýší přehlednost a čitelnost kódu.
Každý vývojový tým by si měl na začátku projektu zadefinovat kódovací standardy a zvolit nástroj, který bude na dodržování dohlížet. Jak lze využít
StyleCop si můžete přečíst v příspěvku <a href="http://www.robertdresler.cz/2011/09/jak-psat-lepsi-kod-s-vyuzitim-stylecopu.html">Jak psát lepší kód s využitím StyleCopu</a>.
</p>
<h2>Volba technologií</h2>
<p>Správnost volby technologií může mít na chybovost zásadní vliv. Rozsáhlejší projekt využívá velké množství technologií a nástrojů. Relační databázový systém,
vývojové prostředí, programovací a značkovací jazyky, validační frameworky, perzistentní framework, základ pro služby, prezentační frameworky a komponenty,
apod. Vybírejte technologie prověřené a odzkoušené (pozor na poslední releasy), které se dobře používají a mají perspektivu (abyste si je nemuseli vyvíjet v budoucnu sami :).
Rozhraní dobrých komponent je snadno použitelné, intuitivní a dobře zdokumentované. Důležitá je také testovatelnost.</p>
<h2>Automatizované testování</h2>
<p>Testování je technika dynamické analýzy kódu. Psaní testů by podle metodologie Test-Driven Development (TDD) mělo předcházet vlastní implementaci.
Zkuste si tento přístup zažít a uvidíte, že se vám zalíbí. A pokud ne, vězte, že testy stejně musíte napsat. Jinak se pro vás stane prvotní
vývoj a především pozdější zásahy do produkčního kódu noční můrou. Testy jsou indikátory chybových stavů.
Vývoj aplikací bez pokrytí testy provozují pouze hazardéři ;)</p>
<p>První typ testů, který napíšete, budou jednotkové testy (unit test). Základní logika jednotkového testu je jednoduchá. Voláte metodu instance testované třídy s určitými vstupy
a validujete výstupy. Pokud výstupy neodpovídají předpokladům, test selže a je nutno hledat chybu v implementaci. Lze prohlásit, že vyšší pokrytí testy
lépe pojistí váš kód. Ale je také nutno dodat, že testy se nesmí psát jen z formality, ale musí být správně cílené na problémové situace. O špatných technikách
psaní jednotkových testů si můžete přečíst v příspěvku <a href="http://www.robertdresler.cz/2012/02/jak-nepsat-jednotkove-testy.html">Jak nepsat jednotkové testy</a>.
</p>
<p>Pokud je test napsaný tak, že "vidí" do implementace, mluvíme o white-box testování. Pokud je testovaný kód pro test černou skříňkou, hovoříme o black-box
testování. Oba přístupy mají své opodstatnění. Pomocí "bílého" testování snáze pokryjete všechny cesty provádění. "Černé" testování zase zosobňuje
naivní přístup klientské strany, který může přinést nečekané způsoby volání.</p>
<p>Vyšší formou testů jsou integrační a systémové testy. Validují interakci více objektů a funkcionalitu větších celků. Pamatujte, že požadavky na kvalitu kódu
testů jsou stejně přísná jako na vlastní testovaný (produkční) kód. Kód testů budete udržovat stejně dlouho jako produkční kód. Zjednodušeně
shrnuto, testy by měly běžet krátkou dobu, na libovolném "kompatibilním" počítači, měly by po sobě uklidit a neměly by být na sobě vzájemně závislé.</p>
<p>Snažte se co nejvíce testů zautomatizovat, určitě se vám práce vyplatí. Bez automatizace nejsou některé typy testů vůbec proveditelné. Těžko se shání
několik stovek uživatelů na zátěžové testy, kteří by v jednom čase začali používat a zatěžovat vaši aplikaci :)</p>
<p>Zautomatizovat se dá i interakce s uživatelským rozhraním vaší aplikace. Volba nástrojů závisí na technologii prezentační vrstvy.</p>
<h2>Ruční testování</h2>
<p>Jedná se o pracnější formu validace funkcionality vaší aplikace, která má však stále svoje opodstatnění. Šikovný tester je vynalézavější než vaše automatizované testy
a objeví situace a scénáře, které jste nepředpokládali. Ještě vynalézavější jsou však uživatelé, proto se také uvolňují nefinální beta verze :)</p>
<h2>Automatizace buildů</h2>
<p>Vytvořte a nakonfigurujte buildovací server pro týmový vývoj. Po každém vrácení změn na server spouštějte build průběžné integrace (Continuous Integration), který
pohlídá, aby vrácená změna nerozbila integritu projektu. Vývojář získá okamžitou zpětnou vazbu, že jeho změna může zablokovat práci celého týmu.</p>
<p>Užitečné jsou i buildy pro zajištění kvality. Jsou spouštěny v pravidelných cyklech, například každou noc a jejich úkolem je provádět statickou i dynamickou
analýzu kódu. Provádějí se validace kódu, vyhodnocují se metriky, spouští testy. Výsledky se následně vyhodnocují a sjednávají se nápravná opatření.</p>
<p>Výhodou automatického buildování je i rychlé vytváření průběžných testovacích verzí a jejich nasazení do testovacího prostředí.</p>
<h2>Prototypování</h2>
<p>Někdy je obtížné již v ranných fázích vývoje přesně specifikovat způsob realizace cílových požadavků na systém.
Víme sice, co chceme udělat, ale nejsme si jisti, jak bude vypadat například uživatelské rozhraní naší aplikace.
Prototyp je funkčně zjednodušený základ (předobraz, demoverze) vyvíjeného systému.
Měl by vzniknout relativně rychle a slouží k průběžné revizi požadavků.
Prototyp můžete předvést investorovi a získat zpětnou vazbu. Prototyp je vyvíjen v cyklech. V každém cyklu jsou zapracovány získané připomínky.</p>
<p>Pokud používáte prototypování správně, můžete získat efektivní nástroj pro řízení a směrování projektu. Vyhnete se chybám, které by byly jinak objeveny
až později a jejich řešení by bylo nákladné. Pro vývojáře je někdy tvorba prototypu neoblíbenou činností. Může se totiž stát, že celý prototyp se zahodí
jako nevhodné řešení a začne se vytvářen nový. Pořád to však méně bolí než složitě předělávat systém v pozdní fázi implementace.</p>
<h2>Revize výstupů v předimplementačních fázích</h2>
<p>Většina vývojových metodik rozděluje vývojový cyklus na fáze specifikace požadavků, analýza, návrh, implementace, testování, nasazení a údržba. V každé fázi
vznikne určitý výstup. Například v první fázi specifikace požadavků vytvoříte požadavky na systém. Pokud jsou sestaveny chybně a zjistíte to až v okamžiku předávání software
zákazníkovi, vyvstává velký problém. Příslušná část aplikace se musí předělat a rozsah víceprací může být značný. Stejně tak chyby v analýze nebo návrhu
vás mohou přijít hodně draho.</p>
<p>Proto je vhodné podobně jako revidujete implementační kód, revidovat co nejdříve všechny předimplementační výstupy. Taková revize má svůj formalismus a pokud
ji uděláte kvalitně, můžete objevit již v ranné fázi závažné chyby. Pokud máte malý vývojový tým, požádejte kolegu, aby si po vás dokumenty s požadavky, analýzou
a návrhem přečetl.</p>
<h2>Motivace lidí</h2>
<p>Některé z výše uvedených technik selhávají, pokud je používá člen týmu s nedostatečnou motivací pro dosahování kvality. Revize se dají odbýt, testy se dají napsat
jen aby se dosáhlo vyššího pokrytí, při psaní kódu lze ošálit statickou analýzu neúčelnou kompatibilitou s validačními pravidly.</p>
<p>Členové vašeho týmu musí být motivováni finančně i nefinančně, aby pro ně bylo přirozené a prioritní zajišťovat vysokou kvalitu svojí práce.</p>Robert Dreslerhttp://www.blogger.com/profile/16401744220939465418noreply@blogger.com0tag:blogger.com,1999:blog-3408745507091232422.post-1288983210848060962012-02-12T20:48:00.002+01:002012-02-12T23:19:16.887+01:00Jak nepsat jednotkové testy<h2>... aneb pozor na lháře, křiklouna a místního hrdinu</h2>
<div class="separator" style="clear: both; text-align: center;">
<img border="0" height="86" width="111" style="border:none;box-shadow:none;vertical-align:bottom;horizontal-align:center;" src="http://us.cdn4.123rf.com/168nwm/grgroup/grgroup1107/grgroup110700130/10032966-black-red-and-green-pedestrian-ligt-isolated-over-white-background.jpg" /></div>
<p>Uvádím seznam nejfrekventovanějších antivzorů (špatných technik) pro psaní jednotkových testů. Vyvarujte se jich a Vaše testy budou v dobré kondici ;-)</p>
<ul>
<li>
<p>
<b>Lhář</b> (The Liar). Jednotkový test, který prochází pro každý testovací případ. Optimismus nás však přejde, pokud se podíváme blíže na implementaci testu a zjistíme,
že ve skutečnosti požadovanou vlastnost netestuje.
</p>
</li>
<li>
<p>
<b>Nadměrná příprava</b> (Excessive Setup). Test, který potřebuje rozsáhlou přípravu ještě před samotným spuštěním testovaného kódu. Stovky řádků a velké množství
objektů, které test vyžaduje, způsobí, že je obtížné ověřit testovanou funkcionalitu. Test může selhat z mnoha jiných příčin, než z vlastní chyby v testovaném kódu.
</p>
</li>
<li>
<p>
<b>Obr</b> (The Giant). Jednotkový test, který pokrývá velké množství testovacích případů a je v rozsahu stovek až tisíců řádků. Přestože validně testuje testovaný kód, jedná
se zřejmě o jednotkový test nad božským objektem (God object). Tedy chybný návrh třídy, která v sobě slučuje více zodpovědností.
</p>
</li>
<li>
<p>
<b>Imitátorna</b> (The Mockery). Používání mock objektů je v mnoha případech dobré a šikovné. V některých případech však mohou vývojáři ztratit kontrolu sami nad sebou
a nadměrným používáním mock, fake a stub objektů potlačit vlastní testovanou funkcionalitu. Dochází pak spíše k testování dat, které
vracejí jednotlivé mock objekty. Definice mock objektů je navíc velmi křehká a může být snadno rozbita a chybně způsobí selhání testu.
To je samo o sobě proti principům TDD. Příliš mnoho závislostí a komplikované vazby na další třídy může indikovat testování božského objektu.
V takovém případě by měla být testovaná třída refaktorována nebo by mělo být jedno volání nahrazeno sekvencí více volání metod s menším rozsahem funkcionality.
Každé dílčí volání by pak mohlo být otestováno samostatně a není nutné znovu testovat celou sekvenci jako celek.
</p>
</li>
<li>
<p>
<b>Inspektor</b> (The Inspector). Inspektor je jednotkový test, který ví příliš mnoho o vnitřní struktuře testovaného kódu. Je napsán na míru z důvodu 100% pokrytí kódu.
V případě, že je testovaný kód refaktorován a přestože se jeho validita nemění, tzn. měl by procházet, začne test neprocházet. To vynutí současnou změnu i v jednotkovém testu.
</p>
</li>
<li>
<p>
<b>Velkorysé zbytky</b> (Generous Leftovers). Jeden jednotkový test vytvoří data, která jsou někde persistována (uchována). Jiný test tato data využívá pro svoje
vlastní (původnímu testu neznámé) účely. Pokud je takový "test-generátor" spuštěn později nebo pouze částečně, dochází chybně k selhání v testu,
který je na něm závislý.
</p>
</li>
<li>
<p>
<b>Místní hrdina</b> (The Local Hero). Test je napsaný tak, že obsahuje závislosti na prostředí, ve kterém byl vyvinut.
V případě, že je spuštěn v těchto podmínkách, pak v pořádku prochází. Pokud se však test spustí v jiném prostředí, selže.
</p>
</li>
<li>
<p>
<b>Hnidopich</b> (The Nitpicker). Test, který prověřuje kompletní výstup, přestože významná je pouze část vrácené informace.
Pokud se změní nevýznamová část vrácené informace, začne test chybně selhávat. Takové testy jsou typické při testování webových aplikací.
</p>
</li>
<li>
<p>
<b>Tajemný lovec</b> (The Secret Catcher). Na první pohled takový test vypadá, že nic netestuje, neboť nemá žádné asserty. Ovšem v tomto případě platí rčení, že
"ďábel je ukryt v detailech". Test předpokládá, že v případě selhání vyvolá testovaný kód výjimku, kterou zachytí a zpracuje testovací framework.
Řešením by mohlo být odchycení výjimky do proměnné určitého typu a porovnání na null hodnotu. Nebo můžete použít atribut ExpectedException.
</p>
</li>
<li>
<p>
<b>Ulejvák</b> (The Dodger). Jednotkový test, který testuje několik méně podstatných aspektů testovaného kódu a vyhýbá se otestování chování zásadního.
Obvykle z důvodu vyšší složitosti takového otestování.
</p>
</li>
<li>
<p>
<b>Křikloun</b> (The Loudmouth). Jednotkový test nebo sada testovacích případů, které posílají na konzoli velké množství testovacích, ladících nebo protokolovacích zpráv,
i v případě, že testy procházejí.
Jedná se obvykle o pozůstatky ručního ladění. Tyto nevýznamné zprávy znepřehledňují výsledký protokol o výsledku spuštěných testů.
</p>
</li>
<li>
<p>
<b>Nenasytný lovec</b> (The Greedy Catcher). Jednotkový test, který zachytí výjimku a "polkne" ji včetně trasování zásobníku. Tuto výjimku někdy nahradí informačně
méně hodnotnou zprávou. Někdy dokonce chybu pouze zaloguje a test nechá projít.
<li>
<p>
<b>Řadič</b> (The Sequencer). Jednotkový test, jehož procházení je závisle na určitém pořadí assertů, u kterých by na pořadí záležet nemělo.
</p>
</li>
<li>
<p>
<b>Skrytá závislost</b> (Hidden Dependency). Hodně podobný "Místnímu hrdinovi". Test přepokládá, že před jeho spuštěním jsou připravena data, na kterých je závislý.
Pokud tomu tak není, test selže. Vývojář obdrží omezenou informaci o problému a je nucen projít velké množství kódu a zjistit problém se závislými daty.
Například starší .dll knihovny mohou být závislé na ini souboru, který řídí jejich chování.
Je obvykle složité dopátrat se vlastní příčiny selhání testu a této skryté závisloti.
</p>
</li>
<li>
<p>
<b>Výčet</b> (The Enumerator). Jednotkový test s testovacími případy, které se jmenují podobně. Např. TestMethod1(), TestMethod2(), ...
V tomto případě není možné z názvů testovacích případů určit jejich význam. V případě selhání je vývojář nucen procházet přímo zdrojový kód testu
a snažit se pochopit jeho význam.
</p>
</li>
<li>
<p>
<b>Cizinec</b> (The Stranger). Testovací případ, který nepatří do jednotkového testu.
Ve skutečnosti testuje jiný typ objektu, který je využíván a vrácen testovaným objektem.
</p>
</li>
<li>
<p>
<b>Kazatel operačního systému</b> (The Operating System Evangelist). Jednotkový test, který se opírá o specifické prostředí nebo vlastnosti operačního systému.
Příkladem může být assert v testovacím případě, který ověřuje sekvenci znaků pro nový řádek a předpokládá Windows konvenci. Takový test selže při spuštní na Linuxu.
</p>
</li>
<li>
<p>
<b>Úspěch zaručen</b> (Success Against All Odds). Test, který byl napsán nejdříve tak, aby prošel, místo aby selhal.
Naneštěstí pak takový testovací případ prochází i v situacích, kdy by měl selhat.
</p>
</li>
<li>
<p>
<b>Jízda zadarmo</b> (The Free Ride). Namísto vytvoření nové metody testovacího případu pro otestování další vlastnosti nebo funkcionality,
se přidá pouze nový assert k již existujícím.
</p>
</li>
<li>
<p>
<b>Jedinečný</b> (The One). Kombinace několika vzorů, zejména "Jízdy zadarmo" a "Obra". Test obsahuje jeden testovací případ, který testuje celou sadu funkcionalit
testovaného objektu. Obvyklým ukazatelem je to, že testovací metoda se jmenuje stejně jako jednotkový test.
</p>
</li>
<li>
<p>
<b>Vykukující kocour</b> (The Peeping Tom). Test, který skrze sdílené zdroje vidí na výsledná data jiných testů. Na základě těchto dat může test selhat,
přestože testovaný systém je pro testovací případ validní. Toto se běžně stávalo ve FitNesse, kde se používaly statické členské proměnné pro
uchování kolekcí, které nebyly korektně vyčištěny po proběhnutí testu. Tento problém se objevoval neočekávaně při některých bězích testů. Vzor známý také
jako "Nezvaní hosté" (The Uninvited Guests).
</p>
</li>
<li>
<p>
<b>Pomalé dloubnutí</b> (The Slow Poke). Jednotkový test, který běží neúnosně pomalu. Když jej vývojář spustí, může si zajít do koupelny nebo zakouřit.
V nejhorším případě jej může spustit na konci šichty před odchodem domů.
</p>
</li>
<li>
<p>
<b>Štastná cesta</b> (Happy Path). Test probíhá pouze po hladké, bezproblémové cestě. Netestuje hraniční hodnoty a výjimky.
</p>
</li>
<li>
<p>
<b>Podřadní občané</b> (Second Class Citizens). Testovací kód není tak dobře refaktorovaný jako testovaný kód, obsahuje duplicity a je špatně udržovatelný.
</p>
</li>
<li>
<p>
<b>Spoutaní řetězem</b> (Chain Gang). Dvojice testů, které musí být spuštěné v určitém pořadí. Například jeden test nastaví globální stav systému
(globální proměnná, databázová data) a druhý test je na tomto stavu závislý. Např. u databázových testů se může stát, že pokud není provádění
uzavřeno ve chráněném bloku a test selže, není po testu korektně uklizeno.
</p>
</li>
<li>
<p>
<b>Bezejmenný test</b> (The Test With No Name). Test, který byl vytvořen, aby reprodukoval nalezenou chybu a jeho autor nepovažoval za důležité
vymyslet mu významové jméno. Namísto posílení (rozšíření) existujícího testu, je vytvořen nový test s názvem TestProChybu123. Po dvou letech, kdy tento test
začne selhávat, musíte do systému pro sledování chyb a hledáte Chybu123, abyste pochopili účel tohoto testu.
</p>
</li>
<li>
<p>
<b>Spáč</b> (The Sleeper). Test, který selže v určitou dobu nebo po určitém datu. Jedná se často o nekorektní kontrolu hraničních hodnot při testování kódu,
který pracuje s objekty typu Date nebo Calendar. Problémový může být také běh o půlnoci. Chyba je na straně kódu testu.
</p>
</li>
</ul>
<h2>Informační zdroje</h2>
<p>Článek jsem sestavil ze dvou níže uvedených zdrojů a dokořenil jej vlastními vsuvkami. Může se stát, že se mi nepodařilo trefit ideální
český ekvivalent pro název některého antivzoru. Navrhněte lepší, rád upravím.</p>
<ul>
<li><a href="http://blog.james-carr.org/2006/11/03/tdd-anti-patterns/">TDD Anti-Patterns</a> na blogu Jamese Carra</li>
<li><a href="http://stackoverflow.com/questions/333682/tdd-anti-patterns-catalogue">TDD Anti-patterns catalogue</a> na stackoverflow.com</li>
</ul>Robert Dreslerhttp://www.blogger.com/profile/16401744220939465418noreply@blogger.com3tag:blogger.com,1999:blog-3408745507091232422.post-88678719560638312992012-02-07T20:15:00.001+01:002012-02-20T18:07:45.922+01:00Pár fíglů od Steva Jobse ...<p>
<div align="center">
<img border="0" height="75" width="66" style="border:none;box-shadow:none;vertical-align:bottom;horizontal-align:center;" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEi_nYJnLoFDlpUkcsiLyT0JnG0c7oiKmpP8K-dUc8x2zDd5LDoTkMGyC46QW6qNuAdy7Y3-sFntnznmJZawcn3EKGRMpzirhH9pJA-JJ7MzrJ2pcrWhl0DcmyicT13I3a8Ff55seZpvr_Qy/s200/jobs.png" /></div>
</p>
<h2> ... aneb Jak vybudovat firmu podobnou Apple</h2>
<p>
Je potřeba na začátek zdůraznit, že potřebujete garáž! Vážně, garáž je pro začínající projekty hodně důležitá. Bez ní to budete mít opravdu těžké ;)
Jo a taky potřebujete někoho podobného Stevu Jobsovi! Troufáte si někdo?
Možná by Vám mohlo zvednout šanci na úspěch, pokud byste od mala vyrůstali v Sillicon Valley a potkávali zapálené inženýry v Palo Alto.
Pokud jste náhodou adoptovaní, lépe se Vám bude hledat motivace dokázat světu, že původní rodiče udělali chybu, když se Vás vzdali.
No tak, nebuďte tak upjatí a zkuste nějaký halucinogen, abyste se trochu odvázali a dokázali dohlédnout do budoucnosti dál než ostatní ...</p>
<p>Přátelé, musím k Vám být upřímný. Každému to nevyjde. Přesněji, skoro nikomu to nevyjde. Bohužel. Nedá se nic dělat!
Pokud Vás však zajímá, jak se vlastně Stevu Jobsovi povedlo vybudovat aktuální technologickou firmu číslo jedna,
mohl by Vás tento článek zajímat. Pokud budete pozorní a přemýšliví, určitě se dozvíte něco, co sami s výhodou použijete.</p>
<h2>Obklopte se schopnými lidmi</h2>
<p><cite>"Například Woz byl člověk asi tak padesátkrát lepší než průměrný inženýr. Ten mohl pořádat mítinky ve své hlavě. Mac tým byl pokus sestavit
tým ze samých takových lidí, z áčkových hráčů. Lidi říkají, že to spolu nemůžou vydržet, že nebudou schopni spolupracovat, nesnesou se.
Ale já zjistil, že áčkoví hráči nemají problém pracovat s jinými áčkovými hráči, ale nedovedou pracovat s hráči céčkovými."</cite></p>
<p>Pro Jobse bylo osudové setkání se Stevem Wozniakem. Kromě školních legrácek a ptákovin sestrojili "modrou krabičku", kterou byli
schopni ovládat miliardovou infrastrukturu telekomunikačního obra AT&T a volat zadarmo po celém světě. Wozniak je také označován za posledního
člověka, který dokázal sám sestrojit celý počítač (Apple I). Samozřejmě v garáži!</p>
<p>Jobs dokázal do svojí firmy nalákat významné manažery a designéry ze slavných firem jako byly Xerox, Intel, Hewlett-Packard, Motorola, Pepsi, apod.
Pečlivě vybíral lidi i do nižších technických pozic. Proslulé jsou jeho přijímací pohovory, během kterých dostával zájemce do prekérních situací
a sledoval, jak si s ní poradí. Jen si představte sami sebe, pokud by se Vás někdo na přijímacím pohovoru zeptal
"V kolika letech jsi přišel o panictví?" nebo "Bral jsi LSD?".</p>
<p>Vybíral špičkové lidi, kteří nebyli příliš upjatí a dokázali si prosadit svůj názor.
Jak sám říká, chtěl se vyhnout "explozi mamlasů" neboli zamoření společnosti průměrnými zaměstnanci.</p>
<h2>Soustřeďte se na inovaci</h2>
<p><cite>"Mám svoji teorii o tom, proč došlo k úpadku ve společnostech jako je IBM nebo Microsoft. Ty společnosti odváděly skvělou práci,
inovovaly a získaly v určité oblasti monopol nebo skoro monopol a posléze se pro ně kvalita produktů stala méně důležitou.
Společnosti si začaly vážit dobrých obchodníků, protože to jsou ti, kteří mají moc rozhodovat o tržbách, ne inženýři a designéři."</cite></p>
<p>Apple je dnes považována za nejvíce inovativní firmu. Jobs si může právem připisovat zásluhy v oblastech, ve kterých jeho produkty způsobily revoluci.
Macintosh byl první počítač určený pro domácnosti s grafickým uživatelským rozhraním, Pixarovské animáky nastartovaly éru digitální kinematografie,
iPod změnil způsob, jakým uživatelé začali konzumovat multimediální obsah, iTunes Store vzkřísil zkomírající hudební průmysl, iPhone byl průkopníkem
v dotykových chytrých telefonech, App Store umožnil prodávat malým vývojářům aplikace pro miliony uživatelů, iPad nabídl platformu pro digitální deníky,
časopisy, knihy a video. A mnoho dalších.</p>
<p>Jobs věřil, že dlouhodobě budovat firmu lze pouze v případě, že se bude investovat do inovací. Pro firmu Apple se inovace stala prioritou a součástí
celofiremní kultury. Jobs nutil lidi kolem sebe "Myslet jinak". Součástí pravidelných porad byly dlouhé diskuze na téma budoucnosti produktů. </p>
<h2>Spoléhejte na intuici</h2>
<p><cite>"Naším úkolem je číst to, co ještě nebylo napsáno."</cite></p>
<p>Musíte se pokusit pohlédnout do budoucnosti, abyste dokázali přijít s novátorským produktem. Jobs se nespoléhal na marketingové průzkumy. Tušil, že
jeho geniální schopnosti spočívají v tom, že dokáže odhadnout, co bude za několik let hitem. Tento hit pak jednoduše vytvořil. Byl jako stopař, který zavětří odkud
vítr vane, chytí stopu a už ji nepustí.</p>
<p>Dobrá intuice se projevila i při jeho působení ve firmě Pixar. Už to vypadalo, že oddělení animovaných filmů Walta Disneyho nemůže pořádně vydělávat.
V těžkých letech investoval velké peníze do krátkých filmů. Celé jeho snažení vyústilo ve vytvoření Příběhu hraček - prvního celovečerního animáku,
který vydělal na tu dobu astronomických 362 miliónů $. Další filmy studia Pixar pak obchodní zisk ještě znásobily.</p>
<h2>Vytvořte jednoduchý, ale dokonalý design</h2>
<p><cite>"Náš pokrok spočívá v eliminaci, v odstraňování nadbytečného."</cite></p>
<p>Design je jedním z nejvýraznější znaků produktů Apple. Jobs byl ovlivněn duchovním učením Zenu, které zvýrazňovalo jednoduchost. Dokázal
zjednodušování dovést až na maximální hranici. Výrobky zjednodušoval tím, že odstraňoval tlačítka, software zjednodušoval tím, že eliminoval funkce
a rozhraní zase eliminací možností. Astronom Jan Kepler již dříve prohlásil, že příroda miluje jednoduchost a jednotu.
Jobs dokázal, že podobně to mají i uživatelé jeho výrobků.</p>
<p>Jobs dokázal propojit všechna vývojová oddělení, designéry i inženýry v jeden integrovaný fungující celek. V Apple se nejdříve
navrhl design, např. počítačová skříň ve tvaru zenové krychle, a podle něho se pak musela přizpůsobit technika. Je jasné, že nejvíc nadávali technici,
co že to zase ti designéři vymysleli. Jako jeden chudák inženýr, jehož úkolem bylo
vyvinout myš, která by pohybovala kurzorem plynule do všech směrů. Když se vyjádřil, že něco takového nejde, druhý den už v Applu nepracoval.</p>
<p>Jobs byl designem posedlý a stávalo se, že prototyp výrobku byl mnohokrát přepracováván. Nechtěl dělat kompromisy i za cenu toho, že se oddálil termín
uvedení do prodeje. Jako u iPhonu, jehož design byl po devíti měsících vývoje kompletně přepracován. V těžkých dobách firmy Apple se stal právě design zachráncem firmy.
Na trhu s počítači, který byl zaplaven levnými šedými krabicemi (rozuměj počítači) firem Dell, Compaq a H-P, si dokázal Apple udržet dostatečný cílový segment tak,
aby přežil.</p>
<p>Už jste si někdy rozbalovali něco od Apple?</p>
<h2>Integrujte hardware, software a služby</h2>
<p><cite>"Lidé nám platí za to, že pro ně integrujeme věci, protože sami nemají čas to řešit. Chcete-li vytvářet skvělé produkty, musíte integrovat,
propojovat hardware se softwarem a správou obsahu. Chcete-li proniknout na nové území, tak to musíte udělat sám. Chcete-li, aby Vaše produkty
byly otevřené jinému software či hardware, musíte se přinejmenším částečně vzdát své vize."</cite></p>
<p>Bill Gates svůj operační systém Windows prodal velké spoustě výrobců hardware a tím dosáhl toho, že prakticky ovládl trh s osobními počítači. Věřil, že v
otevřenosti je budoucnost. Steve Jobs naopak podporoval princip uzavřeného systému. Díky své touze po dokonalosti nechtěl cizím firmám prodat licenci
na svůj operační systém, aby byl provozován na levném a nekvalitním hardware. Tím se jeho počítače typu Macintosh staly nekompatibilní se zbytkem (Windows) světa.</p>
<p>Jobs se však nenechal odradit od své vize dokonale odladěného systému od jedné společnosti. Postupně vylepšoval všechny aspekty produktů a dokázal
nabídnout inovativní technologie a služby, kvůli kterým uživatelé rádi na jeho platformu (do jeho zahrádky) přešli. O správnosti vize svědčí i obchodní
vývoj Microsoftu a Apple. V roce 2000 měl Apple pouze dvacetinovou tržní hodnotu oproti Microsoftu, v roce 2010 se obě firmy srovnaly a v roce 2011 již byl
Apple o 70% hodnotnější firmou než Microsoft.</p>
<p>Za Jobsův mistrovský kousek je považováno vytvoření iTunes Store - obchodu s digitální hudbou. Podařilo se mu přesvědčit největší hudební
vydavatelství a hudební hvězdy, aby začaly svoji hudbu prodávat uživatelům platformy iPod. V té době panovala skepse, že lidé nebudou mít o takovou
placenou službu zájem. Realita však překonala všechna očekávání. Miliontá skladba byla prodána po šesti dnech od zprovoznění služby,
10 miliard skladeb bylo staženo již za sedm let provozu, tedy v roce 2010.</p>
<p>To co udělal Microsoft v 80-tých letech na poli osobních počítačů, to udělala firma Google s operačním systémem mobilních zařízení. Vyvinula Android,
jehož licenci prodala mnoha výrobcům chytrých telefonů. Vlna Android zařízení zaplavila svět. Objevil se levný systém dostupný pro široké masy.
Tato zařízení však mají v mnoha případech problémy s kompatibilitou. Je to daň za velké množství permutací verzí Androidu, modelů telefonů a aplikací.</p>
<p>Nakonec přeci jenom Jobs vpustil externí vývojáře do svého systému. V rámci obchodu s aplikacemi App Store umožnil prodávat aplikace nezávislých vývojářů
i zavedených firem. Stanovil však přísnou posuzovací proceduru, kterou musí každá aplikace projít. Chtěl se vyvarovat tomu, aby se platforma iOS zaneřádila
viry a nekvalitním obsahem, který by degradoval uživatelský dojem z celého systému. Cítil morální zodpovědnost za obsah jeho služeb a proto do AppStore
nikdy nepustil pornografii a bránil se i politickým materiálům.</p>
<h2>Zaměřte se na priority</h2>
<p><cite>"Rozhodnutí, co nedělat, je stejně důležité, jako rozhodnutí, co dělat."</cite></p>
<p>Když se Jobs nadchl pro nějaký výrobek, dokázal odfiltrovat nepodstatné problémy od těch podstatných. To mu umožnilo soustředit se na řešení těch
problémů, které byly pro úspěch rozhodující. Když Jobse vyštípali z Apple a pak jej zase přemluvili, aby se vrátil, vyráběl Apple velké množství různě
nekvalitních výrobků. Tržby klesaly a firma se pohybovala ve spirále smrti. První co Jobs udělal, byla revize výrobní produktové řady.
Sestavil čtyři kvadranty (Zákaznický a Profesionální) x (Desktop a Přenosný) a v každém kvadrantu ponechal pouze jeden produkt. Stmelil rozklížené
vývojové týmy a soustředil energii do vývoje těchto čtyř produktů. Dalším krokem bylo zrušení smlouvy s Hewlett-Packard a opuštění trhu s tiskárnami v roce 1997.</p>
<p>Důkazem správnosti této strategie je aktuálně vysoká prodejnost mobilních telefonů iPhone.
V současnosti je Apple největším výrobcem chytrých telefonů na světě, v podstatě s jedním vícegeneračním modelem. Podíl iPhone na zisku v segmentu chytrých mobilů je kolem 73%.</p>
<h2>Musíte umět zákazníky zpracovat</h2>
<p><cite>"Je důležité přesvědčit lidi o naší velikosti tím, že na ně uděláme pozoruhodný dojem, zvlášť při představení nového produktu."</cite></p>
<p>Uvádění nových produktů byla Jobsova silná parketa. Pečlivě připravený scénář a schopnost vygradovat atmosféru způsobovala téměř davové šílenství.
Dokázal také zapůsobit na vlivné reportéry prestižních magazínů, kteří za získání exkluzivity udělali Jobsovi pořádnou reklamu a správně zahřáli
nedočkavé uživatele.</p>
<p>Jobs spoléhal na sílu médií a investoval do reklamy obrovské sumy. Na každé reklamní kampani se aktivně spolupodílel a projevoval i zde svoji
touhu po perfekcionismu. Díky tomu mohli vytvořit reklamní spot na uvedení Macintoshe, který se vysílal během finále Super Bowlu - v nejdrahším
reklamním čase. Reklama s běžící kladivářkou pak byla jedním magazínem vyhlášena za nejlepší reklamní spot všech dob.
Ve svých reklamách si také Jobs drze troufnul spojit svoje produkty s největšími osobnostmi lidských dějin (Einstein, Gándhí, Picasso).</p>
<p>Při prezentaci svých produktů se zaměřoval na svůj obchodní cíl - na uživatele a na jejich kreativitu a zkušenost s produktem.
Na této myšlence byla vybudována síť kamenných obchodů Apple Stores. Jobs věřil, že obchod je nejmocnější fyzickou prezentací značky.
Každý z obchodů Apple Store je architektonické umělecké dílo, navržené podle Jobsových představ o minimalistickém designu tvořeném obvykle
skleněnými prvky.</p>
<h2>Musíte být upřímní ke svým kolegům (podřízeným)</h2>
<p><cite>"To je moje práce říkat na rovinu, když je něco na hovno, a ne to lakovat na růžovo."</cite></p>
<p>Pokud chcete stvořit něco fenomenálního, musíte po sobě i po ostatních vyžadovat maximální nasazení. Jobs dokázal lidi ve svém okolí namotivovat tak,
že překonávali svoje limity. Byl na ně zároveň velice tvrdý. Pod jeho vedením panovala nulová tolerance k nevýkonnosti. Fénování zaměstnanců patřilo
k běžným komunikačním technikám. U Jobse nefungoval filtr mezi mozkem a jazykem, který by zjemňoval ostré výpady proti kolegům. Když se však s odstupem
času zeptáte členů vývojového týmu Mac na spolupráci s Jobsem, dostanete odpověď, která vás může překvapit. Období spolupráce s Jobsem pro ně bylo
nejúžasnější etapou jejich profesního života.</p>
<p>Zdvořilí a vlídní vůdcové, kteří mají starost, aby se někoho nedotkli, většinou nedovedou tak účinně prosazovat změny.</p>
<h2>Pár vět na závěr</h2>
<p>Život Steva Jobse je samozřejmě plný chybných rozhodnutí a špatných investic. Nezdary zažívá mnoho lidí, kteří se rozhodnou
riskovat a vzít zodpovědnost do vlastních rukou. Je to normální. Ve výsledku však Jobs obstál takovým způsobem,
že vytáhl garážovou firmu do čela smečky technologických gigantů.</p>
<p>Myšlenky a citace uváděné v tomto článku pocházejí ze životopisné knihy <a href="http://www.kosmas.cz/knihy/163937/steve-jobs/">Steve Jobs</a> od Waltera Isaacsona.
Musím přiznat, že kniha na mě udělala velký dojem a donutila mě přemýšlet nad některými věcmi v nových souvislostech. Téměř 700 stran je nabitých zajímavostmi
z doby, kdy se rodily velké věci. Z doby, kdy proti sobě stáli dva velikáni počítačového věku narození v roce 1955,
oba bez dokončeného vysokoškolského studia - (otevřený) Bill Gates a (uzavřený) Steve Jobs.</p>
<p>Pokud máte čas, určitě si ji přečtěte, ať už jste nebo nejste fanouškem Jobse. Nebo už jste ji četli? Líbila se Vám?</p>
<p>Budu rád, pokud zanecháte komentář. Povzbudíte tím autora do dalšího psaní ;-) Nebo možná odradíte ;-)</p>Robert Dreslerhttp://www.blogger.com/profile/16401744220939465418noreply@blogger.com2