14. dubna 2016

Nesouvislé rozjímání programátorovo II


Dejte někomu program a frustrujete ho na den. Naučte ho programovat a frustrujete ho na celý život. – David Leinweber


V r. 2012 jsem shrnul pár postřehů o softwarovém vývoji a zároveň slíbil, že se nedopustím pokračování. Protože sliby se mají porušovat a protože se mi nashromáždilo několik dalších poznámek, o něž se chci podělit, zde je další dávka.

Architektura


Dali byste si do svého CV “Junior SW Architect”? Přijali byste takového člověka do firmy? Asi sotva. Slovo Architekt evokuje někoho seriózního, někoho staršího. A je to odůvodněný požadavek – architekt má (měl by mít) v první řadě zkušenosti s nejméně několika komplexními projekty. Měl by mít vizi, přehled o celku, měl by umět konzervativně tlumit naivní nadšení juniorních vývojářů na jedné straně a naopak argumentovat ve prospěch zdánlivě nerozumných rozhodnutí, pokud jsou dlouhodobě užitečná. Pokud slyší „získáme tím to a to“, měl by vždy dodat „a tímto za to zaplatíme“. Měl by… jistě umíte pokračovat.

Pokud se jen trochu orientujete v zásadách moderního vývoje software, nemohl vám uniknout rezervovaný názor agilních věrozvěstů na softwarovou architekturu a částečně i určitý despekt k SW architektům jako takovým. Je to odůvodněné – tato nedůvěra pramení z doby, kdy se plánovalo stylem waterfall. Architekt býval mudrc v bílém plášti, který vše na základě zadání vyprojektoval v průběhu jediného geniálního tvůrčího aktu, předal vývojářům nějaký plán (v dávné minulosti štos vývojových diagramů, dnes nejspíš nějaká UML schemata), nemyslící poslušní vývojáři plán uchopili a realizovali, nemyslící poslušní testeři otestovali, a pak se to nasadilo.
Dnes jsme dál. Základním předpokladem agile je, že jakákoliv změna musí zůstat levná po dobu celého vývoje (tedy po dobu života projektu, vč. fáze údržby). O architektuře se nemluví, vzniká jaksi za pochodu. Architektura není něco, co můžete naúčtovat zákazníkovi, architektura není feature. Není to něco, co by si product management objednal, tak proč bychom to vůbec měli řešit? V předchozím postu jsem toto téma jen nadhodil: Důvěra v projekt vzniká agilními iteracemi. Že je tato inkrementální cesta "mnoha sprinty k cíli" často pomalejší než trasa pro poctivé maratonce, pak nakonec nikoho nezajímá.
Ano, určitě dnes nepotřebujete mudrce v bílém plášti. Nepotřebujete knížecí rady někoho z venku. A zvláště nepotřebujete architekta, jenž se odmítá dotknout zdrojového kódu a nechce se ušpinit konkrétními problémy, tzv. „implementačními detaily“ všedních dní.

To ale neznamená, že nepotřebujete člověka, jenž má architektonické cítění. Někoho, kdo má zkušenostmi vypěstovaný cit pro rovnováhu mezi krátkodobými a dlouhodobými cíli, mezi celkem a detailem. Musí to být někdo uvnitř týmu se znalostmi o projektu, ale i s dobrým přehledem o nových technologiích. V ideálním případě je to člověk, jenž stojí u zrodu projektu a má představu o jeho organickém růstu. Je to mediátor, jenž se na každý technický spor dokáže podívat z pohledu obou stran konfliktu a dovede nezaujatě posoudit pro a proti každého řešení. Také je kompetentní, co se týče technologického dluhu. Dává pozor, aby tento příliš nenarostl a neprodražoval změny, naopak si uvědomuje, že rychlý postup občas vyžaduje jeho krátkodobý nárůst (pilotní experimenty). Umí včas naplánovat fázi refaktorování a rozpustit technologické úkoly v rámci normální agilní iterace, aby okolí nenabylo dojmu, že se příliš snížila velocita projektu. Protože kvůli tajm tu market jsme přešli na skram, ale proč to nakódili tak zabagovaný, že to musej teď furt jen fixovat?
Jistě vás napadne, že zatímco instantních manažerů s agilními certifikáty je všude plno, jejich protihráč – architekt-programátor-superhrdina – se nedá sehnat, a pokud ano, nedá se zaplatit.

Pravidla


Co když si ale roli architekta rozdělí několik členů týmu? Co když je architektonické rozhodnutí záměrně konsensuální?
Zkuste s touto představou chvíli pracovat: Architektura není dílo jednotlivce, jde o kolektivní proces. Místo ustavení jediného osvíceného diktátora zodpovědného za dlouhodobou technickou strategii posílíte svědomí všech vývojářů tak, aby ke špatným rozhodnutím pokud možno nedocházelo. Myslíte, že je to nemožné? Dejte dvěma programátorům stejné zadání a jako odpověd získáte šest navzájem odlišných způsobů, jak ho lze implementovat. Tak jak by mohlo docházet ke shodě v architektuře?
Trik je v tom, že sice při vývoji software skoro vždy existuje více cest, jak dosáhnout jednoho cíle, vývojáři se ale dokážou snadno shodnout v jejich hodnocení („když použiji tuto knihovnu, znamená to...“, „když přejdeme na toto API, musíme řešit...“, atd.). Důležité je, aby za zásadnější rozhodnutí (např. o závislosti na konkrétní technologii třetí strany) nebyl zodpovědný jediný člověk. Aby nedocházelo k prosazení individuální vůle na úkor skřípání zubů ostatních. Samozřejmě, že čím více lidí se podílí na rozhodovacích procesech, tím je větší riziko paralýzy analýzou. Rozhodnutí prodiskutované v okruhu několika zainteresovaných je ale vždy žádoucí a v dobrém týmu je tento postup zpravidla efektivní.

S rostoucím počtem členů týmu začne být zjevné, že některá rozhodnutí mají obecnou platnost. Není třeba stále opakovat malé debaty, pokud existuje pozitivní zkušenost s důsledky jejich závěrů. Začne vznikat sada zvyků (best practices), ať už v psané nebo neformální podobě. Tato sada mívá většinou povahu detailních pokynů z agilní praxe – např. jednotný způsob formátování kódu (coding standards), pravidla revize kódu (peer review), automatizace, atd.
Často ale tímto postupem organicky vznikají i vysokoúrovňová pravidla s dopady na architekturu řešení. Zde je nutné zdůraznit jednu důležitou věc: Architektonické pravidlo není – na rozdíl od agilních dogmat – nějaké jedno pevné schema, spíš jde o návod k tvorbě schemat, mají-li být životaschopná. Nejde tedy o stav, ale o proces. Architektura je tak flexibilní, což se cení, protože schopnost konat rychlé změny je jedním ze základních principů.

Když se časem ukáže, že se nějaký postup přežil, mělo by být samozřejmé ho po dohodě revidovat. Podobně, jako nikomu nepřijde divné mazat řádky nepotřebného kódu, mělo by být snané zrušit rozhodnutí, když se ukáže, že už nevyhovuje novým podmínkám.
Pravidla musí být jednoduchá, aby fungovala a nesmí jich nikdy být mnoho. Jejich jednoduchost a nízký počet dovolí, aby byla snadno bez velkého přemýšlení dodržována. Komplikované a od reality odtržené zásady jsou běžně obcházeny, realita je vždy složitější než znění sebedelšího zákona. Libovolný proces je snadno dodržován, pokud tvůrčímu člověku pomáhá a zbytečně ho neomezuje.

Na architekturu a agilní pravidla se můžeme dívat jako na jakési metaprogramování programátorů. Pokud dobrý programátor produkuje dobrý software, pak dobrá architektura a rozumné zásady produkují dobré programátory. Abych nebyl špatně pochopen – nejde o technokratický styl řízení lidí, ono „produkovat programátory“ znamená především je naučit, jak se co nejlépe mohou sami zorganizovat v rámci týmu, aby si navzájem nepřekáželi. A protože vývojáři jsou většinou otevřeni novému, vnímají tyto procesy jako novou zajímavou společenskou hru, jejíž pravidla si musí osvojit a mohou se zároveň spolupodílet na jejich tvorbě.
Důležité je stále mít na paměti, že příliš byrokracie brzdí, zvlášť v malých týmech. Programátor se chce plně soustředit na svůj problém, cokoliv mimo něj ho zdržuje. A obrovskou brzdou je pocit nesouladu, pocit zbytečné nebo rutinní práce, nedůvěra v cíl snažení. Konsensus v zásadních otázkách naopak vnímá vývojář jako něco přirozeného.

Elegance


Tím se dostávám k poslední oblasti, osobnosti a emocím programátora. Mohlo by se zdát, že v dnešním SW vývoji emoce nemají své místo. Vývojář jako disciplinovaný profesionál má zdánlivě činit objektivní kroky od dobrého zadání k dokonalé implementaci. Domnívám se, že tomu tak ale není a že individuální preference a intuice programátora se do výsledného software promítají na každém kroku, téměř na každém řádku zdrojového kódu. Jsme odlišní v tom, jaké programovací jazyky upřednostňujeme, lišíme se v tom, co považujeme za jednoduché a co naopak za složité, jinak důvěřujeme novým postupům a technologiím, máme odlišnou potřebu psát komentáře, neshodujeme se často v tom, co znamená dostatečné pokrytí testy, atd.
Věcí, které může osobnost a zkušenosti vývojáře ovlivnit, je příliš mnoho na to, aby se dalo od emocí a intuicí snadno abstrahovat.

Opět zde platí, že přestože se dva programátoři jen málokdy shodnou v tom, jaký kód je dobrý, často se shodují v názoru na to, že nějaký kód je špatný. Znakem špatného kódu je jeho nepřehlednost, nekonzistence, množství podmínek, příliš mnoho varovných komentářů (beware, fixme, ugly…). Špatné řešení jednoduše vzbuzuje pocit, že zdrojový kód je obtížně udržovatelný a přerostl autorovi přes hlavu, že se v něm dopustí chyby každý, kdo se pokusí o jeho úpravu. Pocit, že nejlepší by bylo to celé přepsat.

Technologický dluh je v podstatě hromadění ošklivého. Vzniká plíživě – jsou to denodenní malá rozhodnutí, nevinně vypadající kompromisy, nánosy prachu rostoucí ve zdrojovém kódu, které se v nejméně vhodnou chvíli jako lavina utrhnou a zavalí všechny zúčastněné. Aby zůstal dluh pod kontrolou, je nutné čas od času uklízet, zjednodušovat kód, zpřehledňovat a opravovat drobné defekty. Pokud se z této činnosti stane dlouhodobý návyk, dovoluje to projektu růst organickou cestou, od jednoduchého ke složitějšímu, při udržení konstantní kvality. Pořádek (čistota kódu) umožňuje lepší spolupráci.
Když se naopak stane nepořádek normou, všichni se naučí tolerovat malé nedostatky, ignorovat varování, vypínat automatické testy. Kvalita software postupně upadá, takže je časem snadné přehlédnout nějakou fatální chybu.

Dalším těžko sdělitelným pocitem je elegance kódu. Co je a co není elegantní, je značně subjektivní záležitost. Např. ve volbě programovacích jazyků panuje mezi programátory téměř dokonalá neshoda: Ruby mi připadá v mnoha ohledech elegantnější a ergonomičtější než Python, přestože jsou oba jazyky podobné. Naučil jsem se ale respektovat, že je mnoho lidí s opačným názorem, o čemž vypovídá nezpochybnitelné vítězství Pythonu ve světě strojového učení. Ve vlastním kódu se snažím nevynalézat kolo a rád se opřu o cizí řešení, na druhou stranu rozumím tomu, když si kolega napíše vlastní implementaci něčeho velmi základního, jen proto, aby se vyhnul závislosti na nové knihovně, atd.

V programování platí, podobně jako v jiných lidských činnostech, že vkus a soudnost roste se zkušeností. Nerodíme se se schopností poznat dobrou hudbu od špatné, jsme vychováváni k tomu poznat kvalitu od škváry tím, jak posloucháme. Podobně se z nás gurmán nestane, dokud neochutnáme opravdu dobrá jídla.
Cit pro eleganci a jednoduchost řešení tak najdete snáze u zkušeného vývojáře než u začátečníka. Opačně to ale neplatí – i zkušený programátor může odbýt návrh rozhraní, nemá-li čas nebo je mu to jedno.

Dobrá, jak se tedy snadno stanete vnímavým k estetické stránce software?
Nejde to snadno, ale stojí to za tu námahu: Čtěte cizí zdrojový kód, snažte se pochopit složitější systémy. Proč je API navrženo právě takto a ne jinak, jak jsou části odděleny a jak propojeny, jak vypadají úspěšné refaktorizace, atd. Uvažujte nad komunikačními protokoly, datovými strukturami, relačními schematy. Snažte se vidět, jak se systém vyvíjí v čase – sledujte, které jeho části se mění pomalu a které rychle. Co je jednoduchá změna a jak vypadá drahá oprava. Proč a kde se schovávají chyby. Kde je užitečné optimalizovat a kde je to naopak škodlivé. Přečtěte si o tom nějaké chytré texty a buďte kritičtí.
A nejen to. Čtěte dobré knihy nejen o SW, foťte nebo kreslete, cestujte a naslouchejte, poslouchejte nebo provozujte muziku, obdivujte krásné věci, přemýšlejte o symetrii, o řádu světa, o eleganci.

A Captain Obvious by ještě dodal: Pokud se chcete stát dobrým softwarovým architektem, především velmi programujte!