Zamyšlení nad procesy
Poslední CzPodcast a následná diskuse na Twitteru mě vedla k nápadu popsat, jak fungujeme u nás ve Forrestu. Twitter je na hlubší myšlenky prostě moc omezený. Jsem si vědom toho, že to je risk, protože tohle je oblast citlivá a každý na ní má svůj názor. Nemám(e) patent na rozum a klidně si rád na Twitteru vyslechnu vaše komentáře. V článku spíš chci zmínit body / praktiky, které nám dávají smysl a považujeme je za funkční. Přes to všechno - chyby se stávají, a nic z toho, co tu budu psát nám nezaručuje bezchybné, bezproblémové a jedině ziskové projekty.
Jsem si vědom toho, že řada věcí může fungovat jen při splnění určitých předpokladů. Nemyslím si, že by tyhle postupy šly naroubovat na společnosti o stovkách programátorů. Stejně tak musí být jiné postupy i v týmech, kde je hodně nezkušených programátorů.
Analýza a tvorba zadání
Kamil Zmeškal v tweetu naznačoval diskusi ohledně vstupů pro programátora, tak začnu analýzou a začátkem práce na funkčním celku.
V maximální možné míře se snažíme, aby analýzu dělal člověk, který bude následně vývoj řídit a sám realizovat. Moje historická zkušenost s analytiky je špatná, vidím je jen jako další kolečko v soukolí, kde dochází ke ztrátě informací důležitých pro projekt. Přímý kontakt realizátora se zadavatelem vidím jako klíčový. UML používáme zřídka - pokud, tak activity diagramy pro popis workflow, component diagramy pro high level popis architektury. Technická analýza je typicky strukturovaný dokument, který následně přetavíme v akceptační scénáře a realizační issue.
Objahoba architektury
Párové programování používáme velmi zřídka (obvykle pouze na klíčových místech systému, nebo pokud probíhá nějaké zaučování služebně mladšího kolegy), co si však hlídáme je tvorba architektury v párech. Pokud to dva (a více) lidí spolu přímo netvoří, tak vždy se snažím, aby proběhla revize analýzy druhýma očima a ideálně následně na společné schůzce proběhla “oponentura”. Při ní se druhé oči snaží najít slabá místa a nedostatečně srozumitelné či rozebrané části systému s cílem zajistit porozumnění řešeného problému na maximální možnou míru. Stejně tak se oba snaží najít pro a proti argumenty navrhované architektury a hledat alternativy a porovnávat je s původním návrhem.
Tuhle praktiku osobně považuji za klíčovou, snažím se, aby ji lidi z mého týmu nepodceňovali a sám chodím za ostatními, aby mi revizi mé práce také prováděli. Argumentace proč to dělat je následující:
- chyby v analýze a architektuře jsou ve všech dalších fázích projektu obrovsky drahé
- druhé oči, i když nebyly na jednáních se zákazníkem, přinášejí cenný nezatížený a nezávislý pohled na věc (je potřeba, aby k diskusi přistupovali s pokorou a vědomím, že jim kus kontextu, který má tvůrce návrhu, může chybět)
- jiný člověk má jinou sadu zkušeností ze svých projektů, složení zkušeností každého z nás je unikátní
- rubber duck efekt, už jen, když musí tvůrce návrhu svůj návrh představit často odkryje mezery a nejasnosti v něm
V podstatě celá argumentace je shodná jako u párového programování, jen to má v úvodních fázích daleko větší “hodnotu”.
Grafika, dráty
Našimi předskokany u klienta jsou obvykle naši specialisti na webový marketing a UX. V jejich rukách vzniká tzv. koncept, který řeší co a jak bude systém dělat z uživatelského pohledu. Klíčové části systému jsou rozpracovány do drátěného modelu nebo přímo i do grafiky. Tohle vidím také jako velmi klíčovou věc, protože většina zákazníků potřebuje fyzicky vidět, jak bude web/aplikace vypadat a pak si dokáží jakž takž představit, jak se s tím bude pracovat (i tak se leccos na poslední chvíli před spuštěním předělává). Tihle kluci a holky dokáží s klientem najít řeč daleko lépe než my s analytickým myšlením.
My se do projektu zapojujeme obvykle později, ale než je celá funkční specifikace upečená, musí být mezi technickou částí a klientsky zaměřeným konceptem shoda na realizovatelnosti.
Vývojářské praktiky
Tady zkusím zmínit věci, které se nám osvědčily ve vývoji.
Merge requests
Merge requesty (či pull requesty) používáme pouze v těchto případech:
- kód kontribuuje nováček, u kterého je pravděpodobnost, že v kódu mohou být věci neoptimálně
- kód kontribuuje klidně i zkušený člověk, který ale nemá dostatečný kontakt s projektem (a jeho kontextem)
- když si to sám kontributor vyžádá (já to také často dělám, když si nejsem jist, jestli jsem odhalil všechny vazby a možné komplikace)
Pro revizní komentáře používáme buď možnosti v GitLabu nebo přímo v IDE doplníme na daná místa TODO komentáře s vysvětlením / požadavkem.
Revizím kódu se snažíme dávat prioritu, aby autor měl pořád problém / kód / komplikace v živé paměti.
Testy
Ukřižujte mě, ale netlačíme TDD. Je mi jasné, že tady si nabíhám na hrot - ale v diskusích ohledně testování je mi prostě bližší exploratory coding. Obvykle napíšu nahrubo nějakou funkční část (kombinace datové a byznys vrstvy) a když se mi zdá, že je to životaschopná cesta, začínám proti tomu psát testy, kdy se snažím vyladit API, aby bylo pochopitelně použitelné a zároveň si na něm ověřím různé scénáře použití a hraničních případů. Osvědčilo se mi, že když dotáhnu pokrytí testy někam k 70%, tak se tomu kódu dá už docela věřit (jsem si vědom toho, jak ošemetná metrika pokrytí kódu testy je).
Testy na view vrstvě typicky nepíšeme pro žádné zákaznické implementace - ekonomicky nám to prostě nikdy nedávalo smysl. End to end testy nad WebDriverem píšeme pouze na produktovou část řešení (tj. na UI, které je shodné pro většinu našich zákazníků) a to pouze v částech, o kterých víme, že jsou časem prověřená a že v nich už velké změny nebudou.
Performance testy nemáme zatím do pipeliny zapojené vůbec, děláme je ad-hoc a je to špatně. V tomhle směru bych chtěl v letošním roce udělat nějaký pokrok.
Pravidla pro TODO
V kódu používáme tyto konvence (IntelliJ má skvělou podporu pro hlídání a navigaci v TODO poznámkách):
- TODO JNO … klasická poznámka, že je v daném místě potřeba něco dořešit, TODO je vždy adresné a je za ním trojpísmenná zkratka řešitele (máme nepsané pravidlo, že neadresné TODO nesmí vzniknout)
- TBD #číslo issue … odkaz v kódu, že dané místo je řešené dočasně a čekají ho změny spojené s issue, která je již zapsaná v issue trackeru a zaplánovaná k řešení
- DOCME JNO … těmito poznámkami označujeme místa, která nejsou dostatečně zdokumentovaná nebo umožňují různý výklad, těmito komentáři se navzájem úkolujeme, abychom postupně vytvořili dokumentaci, které všichni v týmu rozumí
Před zamergováním větve do hlavní vývojové větve nesmí v kódu zbýt žádné TODO ani DOCME. Finální kontrolu provádíme před každým releasem (ano nemáme to zatím zautomatizované).
Standupy / statusy
Naše týmy se hodně samoorganizují. Některé provozují SCRUM, jiné se ale, podobně jako my, shodli, že denní statusy nám nepřinášejí dostatečnou hodnotu a máme pouze týdenní synchronizační schůzky, které trvají něco okolo jedné hodiny. Na nich se snažíme být co nejvíce fyzicky pospolu. Pravda je, že náš tým je bez výjimky tvořen seniorními lidmi, kteří mají hodně odprogramováno a po tom, co si dohodneme další postup na této synchronizační schůzce, tak každý ví, co dál. Samozřejmě, že v průběhu týdne máme pár konzultačních ad-hoc rozhovorů dle potřeby už jen v částech týmu.
Osobně tlačím, aby všechny živé projekty měly statusovou schůzku alespoň 1x týdně. Mám historicky špatnou zkušenost z projektů, kde se toto podcenilo a projekťák vsázel třeba jen na one-to-one rozhovory s konkrétními členy týmu. Typicky se v těchto případech ztratil týmový kontext a častokrát vznikaly situace “mrtvého úhlu” - tj. vznikla problémová místa, kde si různí lidé mysleli, že to řeší “někdo jiný” a ve výsledku se ukázalo, že je nikdo neřešil. Problémy byly i v soudržnosti týmu a návaznostech, protože projekťák nemůže některé věci prostě domyslet a je potřeba, aby si to vyříkali lidi, kteří projekt dělají.
Checklisty
Když se podívám na co všechno je třeba myslet, tak prostě nevěřím v přelud full-stack developera. Ne v dnešní době. Jsem rád, že máme specialisty na konkrétní oblasti, ve kterých bych si nikdy nedokázal udržet přehled i kdybych byl sebeinteligentnější - den má pořád jen 24 hodin.
I tak nikdo z nás neudrží všechny informace v hlavě a tak si udržujeme checklisty, podle kterých provádíme finální testy před spuštěním, po spuštění, návody na upgrady, nasazení konkrétního modulu, platebních bran atd. atd. Checklisty se jednoznačně osvědčily a dokud nemáme fajfku u checklistu tak nespouštíme.
Přímý přístup na produkci
V podstatě každý vývojář v týmu má přístup na produkční servery, všichni máme přímý přístup k logům a telemetrii v Zabbixu. Na instalace máme pipeliny v CI, ale pro průzkum případných problémů je často přístup na produkci důležitý. Restart serveru, instalaci updatu dokáže a může provést kdokoliv z nás.
Hlavní dohled nad systémy mají naši kluci z Operations, ale v případě problémů nás velmi rychle kontaktují - respektive o problémech, my vývojáři, víme obvykle stejně rychle jako oni díky aktivnímu reportingu chyb z produkce. Problémy na produkci si řeší každý tým sám a osobně to považuji za hodně důležitý “samoočišťující” mechanismus. Je to jeden z důležitých impulsů pro defenzivní programování.
V tomhle ohledu tedy jednoznačně prosazujeme důvěru a odpovědnost.
Svoboda
Myslím, že v tomhle ohledu jsme ušli v posledních 10 letech největší kus cesty. Týmy mají svobodu určit si jak budou konkrétní věci řešit, jaké knihovny k tomu použijí, jak si nastaví způsob práce s Gitem, issue trackerem, schůzkami a dalšími věcmi. Nikdo jim do toho nemluví do doby, než by se ukázalo, že to nefunguje.
Jednotlivci mají obrovskou volnost v tom, jak si nastaví práci z domu - máme tu lidi, kteří jedou 99% remote, plno lidí dojede do kanceláře jen na jeden den v týdnu. Jedinou podmínkou je to, že to nesmí nikoho omezovat. Služebně mladší kolegové jsou logicky v kancelářích víc, stejně tak i jejich “mentor” - protože to je potřeba. V začátcích projektu, kdy je potřeba více osobního kontaktu, jsou lidi v kancelářích víc. V období, kdy je vše jasné a je pouze třeba “to naprogramovat”, tak zase víc dělají z domu. Měřítkem jsou jen termíny, budget a kvalita (ale i když to někde zaskřípe, nezažil jsem nedůvěru vůči práci z domu).
Zažili jsme i hodně “přestupů” mezi týmy, kdy si prostě lidi chtěli vyzkoušet nějakou jinou specializaci nebo přechody na částečné úvazky a zase zpět. Skoro na všem se dá prostě dohodnout.
Kvalita týmu
Je klíčová a je to zároveň největším problémem. Nedokážu si představit, že bychom fungovali stejně, kdyby byl poměr juniorních lidí proti seniorním nějak výrazně větší než je. Hodně těžíme z toho, že plno lidí je ve Forrestu už dlouho a jsou mezi sebou sehraní a taky vědí, co od sebe navzájem očekávat. Najímat lidi se zkušenostmi je těžké a drahé, přesto se nám to často vyplatilo. Jsem si vědom toho, že je potřeba vychovávat nové generace vývojářů, ale osobně se přikláním při přijímacích pohovorech pouze k lidem, kteří mají už něco odprogramováno a mají zájem se rozvíjet dál, nebo opravdu chytrým a nadšeným juniorům.
Výchova nového člověka je běh na dlouhou trať a obrovská investice ani ne tak z pohledu přímých nákladů na jeho mzdu nebo vybavení, ale z pohledu času ostatních seniorních lidí v týmu. Dříve jsme nováčkům dávali zkraje “vzdělávací projekty” do šuplíku a drželi je po nějakou dobu ve “skleníku”, ale postupně jsme od toho ustoupili a čím dál dříve je házíme rovnou do vody, aby ukázali, co v nich je. Buď to zvládnou nebo ne. Samozřejmě se snažíme z naší strany dát maximální podporu, ale ten člověk sám musí ukázat, že se s problémy chce a dokáže vypořádat.