čtvrtek 27. února 2014

Go není další Jenkins a je to dobře

ThoughtWorks oznámili uvolnění platformy Go jako open source. Go realizuje myšlenky, které ThoughtWorks dlouhodobě razí tj. Continuous Integration a především Continuous Delivery. Samotné Go je zajímavé z několika úhlů pohledu. Přestože existuje celá řada CI serverů, s uceleným konceptem realizace Continuous Delivery zatím nikdo nepřišel až do představení Go - kolega to trefně nazval post Jenkinsovou érou. Go je postavený podle myšlenek a zkušeností, které popsali pánové Jez Humble a David Farley v knize Continuous Delivery: Reliable Software Releases through Build, Test, and Deployment Automation.

One size fits all vs. Lego

Jenkins se stal v mnoha firmách páteří Continuous Integration infrastruktury neboť nabízí velmi dobrou rozšiřitelnost. Existuje celá řada rozšíření, pomocí kterých můžete nad Jenkinsem vystavět prakticky jakýkoliv proces v oblasti testování a nasazení. Jenkins a jeho rozšíření představují Lego skládačku, ze které si postavíte cokoliv. Když vám náhodou nějaká funkcionalita chybí, můžete si jí naprogramovat. Díky Lego konceptu dostanete kostičky, které si musíte sestavit dohromady, aby dávaly dohromady požadovanou funkcionalitu. Bohužel neexistují v uvozovkách Lego stavebnice, které by obsahovaly jenom otestovanou sadu realizující konkrétní use case například Continuous Delivery. Lego koncept umožňuje teoreticky postavit cokoliv, ale prakticky, a to jsme si v GoodData vyzkoušeli mnohokrát, to je velmi nákladné a velmi křehké.

Náklady na skládání kostiček nesete nejenom na úrovni vývoje a testování výsledného řešení, ale i jeho udržování. Při vývoji si musíte nejdříve najít pluginy, pomocí kterých by šel váš scénář realizovat, zjistit jestli by spolu nějak mohly spolupracovat a potom je umě pospojovat dohromady. Prakticky jakýkoliv upgrade Jenkinse a nebo jednoho z jeho rozšíření může vést k tomu, že se celé řešení rozsype jako domeček z karet. Nezanedbatelnou roli hraje doménová znalost problému např. Continuous Delivery. Pokud nevíte co máte postavit, těžko to postavíte.

Doménová znalost Continuous Delivery a realizace jeho základních konceptů přímo v jádru systému je podle mého obrovskou výhodou Go oproti Jenkinsu. Go nabízí rozšiřitelnost, díky které můžete systém přizpůsobit vašim potřebám. Go mi dává smysl v tom, že se nesnaží profilovat jako další Continuous Integration server, ale jako realizace Continuous Delivery infrastraktury. Go nebude zcela určitě Jenkins killer, stále tu budou společnosti, které budou využívat jeho Lego vlastností v oblasti testovací infrastruktury a Continuous Integration.

Kdybych měl dnes znovu začít na vývoji platformy, kterou se v GoodData snažíme realizovat Continuous Integration/Delivery viz Evoluce Continuos Integration infrastruktury v GoodData, určitě bych jí začal stavět právě nad Go. Ušetřilo by nám to spoustu programování a práce s ohýbáním a laděním Jenkinse (pipeliny, propagování artefaktů, vizualizace a mohl bych pokračovat dál). S Go nemám žádné zkušenosti a možná se tahle implementace dlouhodobě neprosadí, ale koncept je krok správným směrem. Mimochodem dejte mi vědět pokud by vás práce s Go zajímala.

středa 26. února 2014

Příběh jednoho selhání, katarze a poučení v agile vývoji

Tohle je příběh jednoho selhání, katraze a poučení našeho týmu při doručování re-brandované login a registrační stránky. Mohl bych ho volně zařadit do série, říkat že dělám agile vývoj je rozdíl oproti tomu dělat agile opravdu, ale neudělám to, protože na tomhle selhání jsme se hodně naučili a přijali pár opatření, které náš tým posunuly. Moje poznatky v tomhle článku pochází z poznámek, které jsem si stačil udělat během retrospektivy. Skoro bych řekl, že se v tomhle příběhu zrcadlí několik ukázkových problémů, a proto o něm píšu. Na tomhle selhání se všechny zainteresované složky podílely přibližně stejnou měrou a protože proběhla retrospektiva, kde jsme bez emocí pojmenovaly všechny problémy a příjmuli opatření k jejich odstranění, můžu zde o nich psát aniž by se to někoho dotklo.


Dobrý úmysl dláždí cestu do pekel

Původně jsme chtěli jenom udělat re-branding login a registrační stránky do GoodData. Designer navrhl vizuální stránky a jeden vývojář měl zmapovat flows, pomocí kterých se může uživatel dostat na login a registrační stránku. Přestože si řeknete, že login a registrační stránka je jenom jedna, existují různé kontexty, ve kterých login stránka vystupuje. Namátkou , embedované módy, potvrzení registrace ,Single Sign On a jeho selhání, vypršení autentizační session atd. Od začátku jsme se nechtěli pouštět do předělání logiky těchto flows. Nakonec nás stála tahle sranda dva měsíce práce, nevrhla na nás úplně nejlepší světlo u vyššího managementu a trochu narušila vztahy s Product Management (zkráceně PM). Zpětně viděno, nasekali jsme několik ukázkových chyb, které v dobré víře vycházely z našeho přesvědčení, že zvolený přístup je správný.


Dělejte jenom to co musíte, ani o chlup více

Když někomu řeknete, že se pustíte do re-designu něčeho, dělejte skutečně re-design a nic dalšího. My jsme se v rámci re-designu pustili do upgradu na novější verzi knihovny Ember.js, přepisu kódu na tuto technologii, budování a ladění infrastruktury pro automatické testy v prohlížeči. Jinými slovy jsme se v rámci re-designu, to jest v chápání normálního smrtelníka maximálně změny CSS a HTML kódu, pustili do splácení technologického dluhu. To nás stálo plno času, který jsme nemohli trávit na vlastní funkcionalitě. Mixování funkcionality a splácení technologického dluhu je nebezpečné v tom, že se velmi těžko odhaduje jeho pracnost a dochází k vazbě mezi doručením funkcionality a umáznutím dluhu. Navíc se to dost špatně komunikuje - "no víte, už by to dávno bylo, ale musíme tady ještě pošolíchat testovací framework, abychom mohli otestovat X. No a ještě musíme něco udělat se stabilitou těch testů, protože teď ty testy vlastně nemají vypovídající hodnotu. A kdy to bude? To se dá těžko odhadnout...". Proto jsme zavedli pravidlo: splácení technologického dluhu děláme separátně od vývoje funkcionality a nespojujeme jej dohromady s vývojem nových vlastností.


Rozděl, ale i doručuj po částech

Celou práci jsme si rozdělili na několik logických kroků, podle kterých jsme chtěli postupovat. Doručení a předání bylo plánované, jako celek ovšem! Díky tomu jsme měli reálnou zpětnou vazbu až úplně na konci vývoje tj. po několika sprintech. Ze zpětné vazby vyplynulo, že je potřeba předělat například validaci, protože nevyhovovala use case. To docela pocuchalo nervový aparát celého týmu. Celá story byla zpožděná, čili všichni cítili tlak na její doručení, a hlavně všichni už byli přesvědčeni, že jsou v cíli a místo toho následovalo další kolečko vývoje.

Mám pocit, že týmy obvykle plánují práci způsobem, že výsledek je vidět až úplně na konci. Představte si, že máte silnici po které chcete nechat projet auto a v jednom pruhu leží balvan. Tým tedy naplánuje nejdříve odstranění balvanu a potom nechá projet auto. Pokud se vám ovšem nepodaří ten balvan odvalit, ohrozíte tím to hlavní, průjezd toho auta. Opačný přístup je nechat to auto projet v protisměru - přestože jenom dočasně. To je podlě mě správný přístup. Zavedli jsme proto pravidlo sprintu: doručit vždy něco, co si může zákazník osahat - minimální produkt (doručit minimální viditelnou změny pro zákazníka).


Můj zákazník můj pán

Dalším problémem představovalo předání, kdy nebyl přesně známý zákazník dané funkcionality. Docházelo k ping pongu mezi PM a týmem. Z jedné části PM znělo: ano jdeme, a z druhé části: nejsme spokojeni, je potřeba ještě upravit to a to. Docela dost to vyostřilo vztahy, protože vývojáři nevěděli, kdo je ten hlavní s kým komunikovat změny. Velký vliv mělo předání celé funkcionality v PM oddělení, a k problémům by zřejmě nedošlo, kdyby byl od začátku do konce za danou věc odpovědný jeden člověk z PM. Zavedli jsme proto pravidlo: během plánování sprintu se všichni shodneme na tom, kdo je zákazník - pro koho pracujeme.

< h3>Jedno prostředí

Vlastní předvádění zákazníkovi nám komplikoval fakt, že různé části měli vývojáři ve svých větvích. Demo a verifikace probíhala vždy na lokální verzi na stavu code base, kterou měl vývojář k dispozici. Při vlastním předvádění si zákazník nemohl vyzkoušet funkčnost jako celek. Pokud se někdo objevila chyba, nebylo zřejmé, jestli je to aktuální problém a nebo to je již v jiné větvi u jiného vývojáře vyřešené. Pro zákazníka je klíčové, aby měl jedno referenční prostředí, na kterém dochází k předání a kontrole odvedené práce. Zavedli jsme proto pravidlo: na akceptačním prostředí se dohodneme během plánování. Komplikovaný merge a chyby, které se projevily až po zamergování do hlavní vývojové větve, byly násobené změnami v infrastruktuře viz upgrade Ember.js. Asi by nám pomohl mainline development (integrační problémy jsou viditelné ihned), ale na to by bylo potřeba vyřešit procesní věci spojené s plněním Service Organization Controls 2.


Neznámé neznámo

Docela dost času jsme strávili analýzou existujícího kódu, abychom zjistili stavy, při kterých dochází k přechodu na login a registrační stránku. Vznikly flows, které nám měly pomoci pochopit, kam je potřeba šáhnout, protože jsme nejenom re-brandovali, ale přepisovali inkriminované části na novou technologii a psali nové testy. Ne že by nám flows nepomohly, ale to co přinesly neodpovídalo investovaným nákladům. Neodhalily například krajní případy, ze kterých na nás během manuálního testování vypadlo větší množství chyb. Analýza nám určitě pomohlo pochopit, co všechno budeme muset otestovat, ale z pohledu odhadu pracnosti byl její přínos zanedbatelný. Shodli jsme se na tom, že mnohem více by nám pomohl opačný přístup - začít z jedné vody na čisto s minimálním produktem případně s variantou v podobě funkčního prototypu, který je rychlejší a poukáže na problémy stejně dobře. I prototyp totiž můžete někomu ukázat a nechat ho ošahat. Analýza jsou slova a slova jsou vítr jak věděl Jon Snow a sním všichni čtenáři pentalogie Píseň Ohně a Ledu. Prototyp lépe pomáhá odhalit problémy, které by vás během analýzy nemusely napadnout - neznámé neznámo, nevím že existuje proto jej ani nemůžu analyzovat.



Strategie

Žádný plán nepřežije první dotek s nepřítelem, jak pravil von Moltke, to ale neznamená, že by neměla existovat strategie, jak řešit situace se kterými ze začátku nepočítám. Ve chvíli kdy se objevily nějaké problémy, neexistoval postup jak se z nich vymotat. Strategie může být: "dodávám malé kousky, které na několikadenní bázi ukazuji zákazníkovi. Změny přijímáme operativně na základě trvalé zpětné vazby ze strany zákazníka. Pokud se najde problém, který nedokážeme vyřešit z časových důvodů nebo je to velká změna do zadání, vyřešíme to během dalšího sprintu jako navazující úkol." My jsme žádnou strategii neměli, protože celý úkol byl pojatý jako monolit na všech úrovních - plánování, vývoj, testování, předání atd. Strategie, a teď myslím strategie vývoje té vlastnosti, by nás mohla donutit snažit se ten monolit rozsekat již při plánování.


Závěr

Když to shrnu do pár základních pravidel, na kterých jsme se shodli na základě retrospektivy.

  • Doručujeme něco viditelného co si může zákazník ošahat v každém sprintu
  • Během plánování zná celý vývojový tým, kdo je zákazníkem resp. kdo hraje jeho roli
  • Při plánování určujeme strategii vývoje tj. teď uděláme X a další sprint Y
  • Neděláme detailní plán, protože stejně nepřežije první dotek s realitou
  • Při plánování se zákazníkem dohodneme na akceptačním prostředí
  • Nemícháme infrastrukturu do vývoje nových vlastností