Category Archives: Agile

Nasazujeme a testujeme (mikro)služby

Pokud dostanete chybu v testu vyšší úrovně, nemáte jenom chybu v testovaném kódu. Také vám někde chybí unit test.
Martin Fowler

Včera jsem se vrátil z GeeConu. Jelikož jsem neuvěřitelně vzdělaný, sečtělý a šikovný, tak mě tam zas tolik věcí nezaujalo. Dostala mě ale prezentace Sama Newmana o testování a nasazování mikroslužeb. Dozvěděl jsem se tam řešení problému, s kterým si nevíme rady.

Máme totiž platformu rozdělenou na služby, které jsou ve správě jednotlivých týmů. To má spoustu výhod. Každý si hraje na svém písečku, může si rozhodnout v jakém jazyce to bude psát, jak to bude testovat, jak často chce nasazovat a spoustu dalších věcí. Tím, že jsme platformu rozdělili na služby, se nám ohromně usnadnila práce. Každý máme svoji hromádku, o kterou se staráme a za kterou neseme zodpovědnost. Od té doby, co jsem se takto rozdělili, jsme se ohromně zlepšili ve vývoji, testování i nasazování jednotlivých služeb. Každá služba má totiž specifické požadavky a najednou nám odpadla většina pokusů najít dokonalé univerzální řešení. Víc experimentujeme a každý tým si najde co mu vyhovuje.

Problém ale je, že jednotlivé služby pořád tvoří jednu platformu a zákazníkovi je jedno, že moje část je skvěle otestovaná a funguje, když platforma nefunguje jako celek. Jednotlivé týmy se starají o svoje služby, ale docela nám drhne nasazování a testování, když se jednotlivé služby dají dohromady. Například je složité rozhodnout jaké kombinace služeb testovat, když má každá služba jiný cyklus nasazování. Dopředu moc nevíte jaké verze jednotlivých služeb se potkají na produkci. Co když neškodná změna jedné služby, rozbije něco ve druhé službě? Existuje několik evidentních řešení, které bohužel nezabírají.

Integrační testy

Ideálním řešením jsou integrační testy, které automaticky otestují celou platformu, všechny případy užití a všechny možné kombinace služeb. Před každou změnou se tyto testy spustí, a když projdou, tak je všechno v pořádku a můžeme nasazovat. Jak už jsem řekl, toto řešení je ideální, což bohužel znamená, že v reálném světě moc nefunguje. Abych mohl spustit integrační testy, tak musím všechno nasadit, pospojovat a pak spustit testy, které klikají skrz UI. To za prvé dost dlouho trvá a za druhé je tam tolik věcí, které se můžou rozbít, že testy někdy víc padají, než procházejí. Co dělat když testy neprojdou? Který tým se na to má podívat? Kdo určí co se rozbilo? Sam Newman sice říkal, že když integrační testy neprocházejí, tak je to dobře. Pravděpodobně to poukazuje na křehkost našeho testování. Ale zestabilnění integračního testování je příliš velké sousto, kterému se sice asi nevyhneme, ale bude to dost dlouho trvat. Do GeeConu jsem věřil, že to jde, že je to jediná správná cesta, že se jen málo snažíme. Ale asi jsem byl příliš velký idealista.

Navíc mi nedošla jedna zásadní věc. Protože jsou integrační testy pracné, pomalé a křehké, je dobré je používat jen na věci, které se jinak otestovat nedají. Třeba na otestování toho, že nám celý systém funguje. Spousta věcí se dá ale otestovat jinak, jednodušeji.

Nasazovat najednou

Druhá možnost je nasazovat najednou. Udělat release okna a dopředu vědět co kdo bude kdy nasazovat. Můžeme se tvářit, že nemáme služby ale jeden celek, který můžeme najednou otestovat a nasadit. V teorii to zní dobře, ale předpokládá to, že nikdo neudělá chybu. Že nikdo na poslední chvíli nezjistí, že mu něco nefunguje nebo že na něco zapomněl. Co pak? Odložit i release ostatních služeb? Následující release pak bude ještě větší, a tím se zvětší i pravděpodobnost, že se něco rozbije. Takže se release zas odloží a tak dál. To je cesta do pekel.

Kontrakt mezi službami

Když se nám nedaří testovat to celé najednou, co takhle dobře otestovat jednotlivé služby a pevně stanovit kontrakt mezi nimi? Něco podobného navrhoval kdysi kolega, že prý nemusíme tak intenzivně testovat celou platformu, stačí když dobře zdokumentujeme API. Tenkrát jsme mu to rozmluvili. Právem. Dokumentace je obvykle neúplná, nepřesná a zastaralá, ta by nám kvalitu nezajistila. Nedošlo nám ale, že jsme byli jen kousíček o řešení. Co takhle přísnější kontrakt? Co když tým spravující jednu službu uzavře kontrakt s týmem spravujícím druhou službu o tom jak ji budou používat. A místo toho, aby si na to plácli, tak na to napíší testy. Říká se tomu Consumer-Driven Contract.

Jednoduše se napíší testy, které říkají, my vás budeme volat takto a vy nám budete odpovídat takto. Když se přihodí toto, tak nám vrátíte tamto. Pokud někdo změní službu, spustí testy, které hlídají její kontrakt. Když projdou, je velká šance, že se nic nerozbilo. Díky testům kontraktu budeme mít otestovanou spolupráci mezi službami, díky ostatním testům služby samotné. Místo velkých megatestů, které to pokryjí najednou od hlavy až k patě, pokryjeme systém menšími, překrývajícími se testy. Navíc budeme mít i zdokumentovaný kontrakt mezi službami, což není nikdy na škodu.

Není to samozřejmě dokonalé, pořád tam budou věci, na které zapomeneme. Pořád budeme potřebovat integrační testy, ale nebude jich potřeba tolik. Stačí jich pár, které ale na oplátku můžeme pouštět třeba i na produkci.


Sam Neward toho radil víc, ale consumer-driven contracts mě zaujaly nejvíce. Abych vás neochudil o zbytek, tady je celá prezentace a toto jsou hlavní rady:

Buďte si vědomi vaší pyramidy testů. Vyvažujte ji.Pyramida testů říká v zásadě to, že byste měli mít hromadu unit testů, spoustu komponentových testů a míň integračních testů. Čím větší daný test je, tím míň jich chcete mít. Je to relativní číslo, neříká, že máte kašlat na integrační testy. Říká jen, že pokud máte víc integračních testů než unit testů, tak je něco špatně.

Rozumějte rovnováze mezi testováním a rychlou nápravou – Máte omezené množství zdrojů, je dobré najít rovnováhu mezi tím, jak umíte testovat a mezi tím jak rychle umíte odhalit a napravit chyby na produkci. Možná je výhodnější mít méně dokonalé testy, ale lepší monitoring a rychlejší releasy. Všimněte si, že je to o rovnováze, rozhodně neříká ať kašlete na testy.

Nasazujte jednu věc po druhé – V daném okamžiku nasazujte jenom jednu službu. Budete mít snazší rollback a diagnostiku chyb.

Zvažte consumer-driven contracts – o tom je celý tento zápisek.

Prozkoumejte nasazovaní založené na imagích, abyste zmenšili rozdíly mezi testovacími prostředími – místo toho, abychom měli jeden image s operačním systémem a všechno ostatní na něj instalovali, je údajně lepší vyrobit image s celou naší službou a ten image pak prohnat celým testovacím potrubím až po produkci. Vyžaduje to mít jednu službu per image, ale díky Dockeru to prý jde udělat lacině.

Autonomie, vlastnictví, agilita

Chcete aby byl váš tým agilní? Je to jednoduché. Musíte mu dát autonomii, z ní může vzejít pocit vlastnictví a teprve pak se může začít objevovat agilita. Pro mě je totiž Agile v první řadě neustálý proces učení se a zlepšování. Nikdo není dokonalý, takže je potřeba se neustále ohlížet, zjišťovat co funguje a co ne a na základě toho se učit. Proto máme iterace a na konci každé z nich retrospektivu. Tento pravidelný rytmus rituálů zajišťuje, aby se na učení nezapomnělo.

Ale je nutné si uvědomit, že rituály jsou k ničemu, pokud nemá tým pocit, že může něco změnit. Pokud si nevezme problémy za své, tak můžete udělat třeba tisíc retrospektiv a bude vám to k ničemu. Pro to, aby měl tým pocit vlastnictví, musí mít nad svou prací kontrolu, musí být autonomní. Musí mít prostor a zdroje, aby mohl měnit věci které nefungují, musí vidět že opravdu může něco zlepšit.

Pokud tým nemá autonomii, tak nemá důvod se snažit. Proč taky, vždyť o všem důležitém rozhoduje někdo jiný. V podobné situaci jsme byli před rokem, dvěma. Pokoušeli jsme se o Kanban. Šoupali jsme kartičkami po tabuli a nevím co ještě, ale pořád jsme měli moc rozpracovaných věcí (Work In Progress). Kanban je při tom na sledování množství rozpracovaných věcí postaven. Pokud je jich moc, tak je to příznak problému. Tým si toho všimne, zjistí co drhne, opraví to a jede dál.

Ale v našem pojetí to vypadalo následovně: „Proč děláš na třech věcech najednou?“ „Tady čekám na předávku kvalitě a tady na operations.“ „A proč to nepopoženeš?“ „Copak jsem jejich manažer?“ Zpětně je evidentní, že problém byl v nedostatečné autonomii týmů. V každodenní práci byly moc odkázány na ostatní, nebyly samostatné a jejich členové necítili vlastnictví. Proč by měli popohánět lidi z jiného oddělení? Proč by se měli snažit o zlepšení? Vždyť je to problém někoho jiného.

Pomohlo až to, co píší v každé knížce o Agile – dali jsme operations, kvalitu a vývojáře do společného týmu a najednou to není problém někoho jiného, najednou se to dá řešit, najednou se týmy snaží zlepšovat. Navíc nám už nikdo shora nepřikazuje zlepšovat tu a tu metriku, najednou se týmy snaží zlepšovat samy. Ano, není to procházka růžovou zahradou, jde to pomalu, drhne to, ale hýbe se to.

Nicméně jak říká Henrik Kniberg, Agile is Fragile. Je velmi snadné to rozbít. Nám se to částečně povedlo u releasů. Máme složitou platformu takže i releasy jsou složité. Některé týmy si to vyřešily po svém a nasazují samostatně. Jinými slovy, cítily problém, který přesahoval jejich možnosti, tak si odtrhly část platformy pod svoji kontrolu a zbytek neřešily. V rozdělování platformy měly navíc velkou podporu vedení, takže se to některým týmům povedlo.

Problém s releasy se tím ale nevyřešil. Některé týmy to mají s odtrháváním složitější, mnoho částí navíc zůstalo v zemi nikoho. Třeba společné testovací prostředí, to nikdo nechce, ale každý ho může rozbít. Zkrátka a dobře, problém s releasy se sice výrazně zlepšil, ale pořád se nám občas na produkci dostane něco, co by se tam dostávat nemělo.

Protože se to stávalo opakovaně, tak se naše vedení rozhodlo s tím něco udělat. Sešli se páni direktoři a rozhodli, že releasovat se bude tak a tak. Na tom také není nic špatného, dělají svoji práci. Viděli problém, tak se rozhodli ho řešit. Jenom jim nedošlo, že tím berou týmům část jejich autonomie. Teď už nejsou releasy záležitostí týmů, teď už jsou záležitostí directorů. Že se nová funkcionalita dostala na produkci pozdě? Ptejte se directorů. Že nevíme co, kdy a kde testovat? Ptejte se directorů. Je hrozně snadné k takovému přístupu sklouznout. Představte si, že vám někdo začne mluvit do věci, s kterou si beztak nevíte moc rady. Je hrozně snadné rozhodit rukama a tvářit se, že to tím pádem není váš problém. Znám pár lidí, kteří dokáží těmto pocitům vzdorovat, ale například mě to fakt nejde. Pokud mám pocit, že nad něčím nemám kontrolu, tak se nedokážu přinutit to řešit.

Hrozně rád bych tady napsal co s tím, bohužel to ale nevím. Na jedné straně vidím, že pokud týmy mají opravdovou autonomii, tak to funguje mnohem lépe. Čím víc si toho můžou řešit samy, tím lépe. Na druhou stranu ale nevím, jak řešit věci, které se dotýkají víc týmů nebo celé firmy. V chytrých knihách píší, že je potřeba určit společný cíl, který si lidé vezmou za svůj. Pak už jen údajně stačí jim dát prostor a oni vás k němu dostanou. Hmm.

Poslouchejme

Nemůžete posunout konverzaci pozitivnějším směrem, pokud se váš partner necítí vyslyšen a pochopen.
Douglas Stone

Musím se k něčemu přiznat. Myslel jsem si, že hlavním cílem komunikace je přenos myšlenek z jedné hlavy do druhé. Že když mi někdo něco vysvětluje, tak je jeho hlavním cílem předat mi nějakou myšlenku a mým úkolem je snažit se mu v tom pomoci. V okamžiku, kdy mi tu myšlenku předal, tak mu to musím dát najevo, ujistit se, že jsem to pochopil správně, prohlásit téma za ukončené a přesunout se dál.

Zní to rozumně, plně to odpovídá modelu racionálního člověka a přesto je to naprosto špatně. Ve spoustě situací vám druhý člověk nechce předat informaci, ale chce se jednoduše vypovídat.

Proč to vůbec píšu? Protože je to důležité a hrozně s tím bojuji. Nedávno se mi stalo, že jsem zastavil kolegu po první větě, protože jsem věděl, že to co mi říká, už dávno neplatí. Chyba. Myslel jsem si, že nám tím ušetřím čas, ale nestalo se. Byl rozhozený a následná diskuze byla k ničemu.

Co s tím? Je potřeba poslouchat. Ano, i když vám někdo říká něco co už dávno víte, i tak musíte poslouchat. Ne jenom čekat až ten druhý domluví, inteligentně u toho pokyvovat hlavou a přitom přemýšlet co budu říkat já, až se uráčí vyžbleptnout. Je potřeba ho opravdu naplno poslouchat. Nejen že nám opravdu může říci něco co nevíme. Ale i kdybychom přesně věděli, co nám chce sdělit, tak dokud nebudeme poslouchat my jeho, tak nebude poslouchat on nás. Dostaneme se do situace, kdy budeme vést sériový monolog. Každý si bude mlít to svoje, aniž bychom se navzájem poslouchali.

Abych ocitoval odbornou literaturu: „Důvod proč vás ten druhý neposlouchá není to, že je tvrdohlavý, je to proto, že se necítí být vyslyšen. Jinými slovy, neposlouchá vás ze stejného důvodu proč neposloucháte vy jeho. Myslí si o vás, že jste pomalí a tvrdohlaví. Takže se opakuje, hledá nové cesty jak vám to vysvětlit, zvyšuje hlas a tak dále.“ Nepřipomíná vám to vaší poslední složitou schůzi? Mně jo.

Netvrdím, že poslouchání je jednoduché. Už pár měsíců se to snažím naučit a pořád se mi to nedaří. Ano, umím se naučit parafrázovat, klást doplňující otázky a podobné finty. V tom to ale není. Ten pravý trik je v tom opravdu vnímat co ten druhý říká. Je to hrozná fuška, ale začíná mi docházet, že jinak to nejde.