Antipatterny, smradlavý kód a Peterův princip v IT

facepalm 80

U předchozího článku se už v titulku objevilo slovo „antipattern“. Jak samotný název napovídá, jde o určitý protipól návrhových vzorů, „patternů“, ovšem tentokrát v opačném smyslu, tedy „jak to nedělat“. Pojďme si taková „antidoporučení“ projít – a nezapomeňme se přepnout do módu „nadsázka povolena“.

Peterův princip říká, že v hierarchické organizaci jsou lidé povyšováni tak dlouho, až se dostanou na pozici, na kterou už nestačí. Je to logický důsledek snahy povyšovat lidi, kteří se na svém místě osvědčili – jednoho dne jsou povýšeni do funkce, kterou už nezvládnou, a tam se jejich postup zastaví.

Generalizace tohoto principu říká, že cokoli, co funguje, bude používáno pro stále složitější a odtažitější úkoly, až to bude nasazeno někde, kde to už fungovat nebude. Každý z nás jistě dokáže vyjmenovat několik takových příkladů z oboru software a IT vůbec. Nástroje, původně napsané pro určitou konkrétní oblast, se ukázaly životaschopnými – a za chvíli je vývojáři ohýbali pro použití v oblastech, kde víc práce zabralo samotné ohnutí oblíbeného nástroje než použití jiného, vhodnějšího.

Softwarový Peterův princip má význam lehce odlišný. Popisuje vývoj softwarového projektu, který se pomalu stává složitějším a složitějším, až sami vývojáři přestanou rozumět tomu, na čem vlastně pracují, a projekt ještě chvíli jede setrvačností, dokud s rámusem nepadne. Následně je označen štítkem EPIC FAIL a starší kolegové jím straší ty služebně mladší.

Příčiny takového selhání mohou být tři (a většinou chodí ruku v ruce). První příčinou mohou být nezkušení vývojáři. Druhou příčinou pak vývojáři sice zkušení, ale nekompetentní. Definici „nekompetentního vývojáře“ nabízí Steve McConnell v knize Code Complete. Podle něho jsou nejlepší vývojáři ti, kteří pochopili, že je důležitější komunikovat s lidmi než se strojem. A nemusí to být jen třeba zákazníci nebo uživatelé – je potřeba komunikovat i s lidmi, co se o kód budou starat po vás. McConnell říká, že nekompetentní programátor upřednostňuje pokročilé a složité konstrukce či málo známé vlastnosti programovacích jazyků („programování na hraně“) před čitelností kódu. Kód psaný takovými programátory zvyšuje složitost celého projektu (i když mnozí z nich považují právě takové složité konstrukce za znak opravdového machra, co fakt do toho jazyka vidí).

Třetí příčinou selhání podle Peterova principu je ztráta koncepční jednoty. O tomto problému jsme si už na Zdrojáku říkali v článcích o projektovém řízení – ve chvíli, kdy začnou vývojáři podléhat nadšení z toho, co všechno by do projektu ještě mohli přidat, a nesoustředí se na základní funkčnost, je celý projekt na nejlepší cestě do pekel. Proto je potřeba, aby projekt řídil jeden člověk (nebo malý tým), který právě tyhle tendence udrží na uzdě a dokáže vývoj směřovat k určitému cíli. V projektech bez silného vedení a jasně dané koncepce se míchají otázky návrhu s otázkami implementace, a jejich řešení bývá ponecháno na uvážení programátorů. V případě, že mají programátoři v těchto oblastech přílišnou volnost, začnou přidávat nové funkce a zkoušet nové postupy a přepisovat už napsaný kód – a celý projekt se pak sype jak domek z karet.

Smradlavý kód

Vývojář s mnohaletou zkušeností dokáže kouknout na cizí kód a – aniž by ho podrobněji studoval – říct: S tím budou problémy. Jak to pozná? Většinou intuitivně. Špatný kód, se kterým budou problémy, totiž zapáchá (Code Smell). Co si pod takovým smrdutým kódem představit?

Nejčastější „smradlavé konstrukce“ jsou takové, o nichž každý programátor s alespoň základním teoretickým vzděláním ví, že je dělat nemá (ale v praxi pak vznikají „nějak samy“). Například duplikovaný kód – stejný nebo velmi podobný kód na různých místech. V OOP to jsou třeba příliš velké třídy, třídy s velkým množstvím funkcí, dlouhé metody, nebo naopak třídy příliš krátké, příliš „líné“ (lazy class, freeloader). Zapáchající kód představuje třeba třída, která přepisuje svého předka takovým způsobem, že ji lze za potomka považovat už jen stěží (viz Liskov substitution principle a související Circle-ellipse problem). Zapáchá i třída, jejíž správné fungování závisí na konkrétní implementaci jiné třídy (inappropriate intimacy) nebo taková, která zneužívá metody jiné třídy.

Zapáchající kód vznikne i přílišným lpěním na dogmatech – například použitím složitého návrhového vzoru tam, kde by stačilo jednoduché a přímočaré řešení. Problém mohou signalizovat i literály (konstantní řetězce či čísla) roztroušené po celém kódu, nebo používání složitých jmenných konvencí pro odlišení případů, které měly být odlišené samotnou architekturou.

Kód, v němž se takové příznaky vyskytují, zkrátka čpí na sto honů, a i když je možné, že bude teď a tady fungovat a bude svou funkci plnit, je velmi pravděpodobné, že s ním budou problémy při další údržbě, třeba při nutnosti přidat nebo pozměnit nějaké jeho funkce. V takovém případě je téměř jisté, že se něco rozbije

Antipatterny – „návrhové horrory“

Na rozdíl od návrhových vzorů, které nabízejí modelová řešení pro konkrétní situace a je dobré se jimi řídit (resp. ve standardní situaci použít standardizovaný vzor), jsou antipatterny spíš návrhové horrory. Jsou to často používaná (či „často vznikající“) řešení, která jsou možná funkční, ale z principu špatná. Popisují nejčastější kategorie vývojářských „nočních můr“. Pojďme si některé z nich představit.

Obrácení abstrakce (Abstraction inversion)

Obrácená abstrakce popisuje situaci, kdy kód sice dělá něco, co uživatel požaduje, ale autor tyto funkce nezpřístupní ostatním. Výsledkem je, že programátor musí tutéž funkci, která už je uvnitř implementovaná, napsat znovu, místo toho, aby ji prostě využil – nemá totiž jak. 

Hrouda bláta (Big ball of mud)

Už samotný název tohoto antipatternu říká, jak vypadá takový kód. Je to kód, v němž není rozpoznatelná struktura; slepenec tříd, metod, rozhraní, to všechno s nejasnými vazbami a souvislostmi. Čeština má pro takový kód rčení „prase aby se v tom vyznalo“.

Databáze jako komunikační rozhraní (Database-as-IPC)

Někdy není zbytí a prostředky, co máme k dispozici, jsou tak omezené (představme si např. sdílený LAMP hosting), že je potřeba řešit komunikaci mezi procesy pomocí databáze, v níž si nasimulujeme frontu zpráv. Což ale neznamená, že to je správné řešení. Správné řešení je použít vhodný IPC nástroj.

Pozlacení (Gold plating)

I tento antipattern jsme si už představovali v článcích o principu „good enough“. Každý projekt se dostane do bodu, za nímž už se nevyplatí vynakládat další prostředky na vývoj funkcí, protože jejich přínos je nižší než ty vynaložené prostředky. Takové perfekcionalistické „vyvíjení za hranicí rentability“ lze přirovnat k pozlacování kuchyňského nože – je to zbytečné, nepřináší to žádné zásadní vylepšení ani novou funkci a výsledek je jen dražší.

Efekt vnitřní platformy (Inner-platform effect)

Program někdy nabízí takové možnosti přizpůsobení, rozšíření, doplnění, upravení a nastavení, že se stává sám vývojářskou platformou. Jako příklad lze použít známý bonmot: „EMACS je skvělý operační systém, kterému chybí jen použitelný textový editor“.

Nafouknuté rozhraní (Interface bloat)

Navrhněte rozhraní tak mocné a schopné, že bude extrémně složité ho implementovat.

BaseBean

Tento antipattern popisuje situaci, kdy potřebnou funkci z pomocné třídy dědíme, místo toho, abychom ji na tuto třídu delegovali.

Kruhová závislost (Circular dependency)

Mějme třídu A, která je závislá na třídách B a C. Třída C je závislá na třídě D, která je závislá na třídách B a E, a třída E je závislá na třídě A. Nebo třídu P, která závisí na třídě Q, která závisí na třídě P. V extrémním případě pak „rekurze: viz rekurze“.

Božský objekt (God object)

Už jsme na něj narazili výš, v části o zapáchajícím kódu. Božský objekt vznikne sloučením velkého množství (leckdy nesouvisejících) funkcí do jednoho místa.

Objektové orgie (Object orgy)

Stav, kdy vývojář rezignuje na zapouzdření objektů a všichni tak mají neomezený přístup ke všem vnitřním hodnotám a metodám.

Poltergeist

Poltergeist je mysticky vznikající a zase mizící objekt s krátkou životností. Typicky vznikne, zavolá nějakou funkci, a zase zmizí. Často bývá plodem programátorova předjímání, že tam někde bude někdy v budoucnu něco složitějšího, a ono tam nakonec nic složitějšího není, ale zbytečný mezikrok tam straší dál.

Sequential coupling

Třída, která vyžaduje, aby její metody byly volány v přesně daném pořadí (a to nikoli z logiky věci, ale kvůli implementaci).

Problém joja (Yo-yo problem)

Tento problém je patrný v situaci, kdy se programátor snaží pochopit závislosti tříd a dívá se na jejich graf. Když mu pohled létá nahoru a dolů, jako kdyby sledoval jojo, je to příznak, že struktura trpí tímto antipatternem (nebo že dokumentaci tvořil sadista, co chce ostatním znepříjemnit pochopení problému). Často se vyskytuje při extrémním „rozdrobení“ struktury na malé kousky, které jsou pospojovány zcela zběsilým způsobem.

Akce na dálku (Action at a distance)

Nečekaná interakce mezi velmi vzdálenými částmi systému. Třeba systém, kde si TCP/IP stack volá pro výpočet čísla sekvence ovladač tiskárny. 

Slepá víra (Blind faith)

Slepou vírou se proviní každý, kdo:

  • spoléhá na to, že chybu opravil správně,
  • spoléhá na to, že funkce vrátí správnou hodnotu,

aniž by si to otestoval. Bude potrestán prapodivnými chybami, které se náhodně projevují a nelze je vystopovat.

Kotva (Boat anchor)

Po delším vývoji najdete v systému části kódu, které už nikdo nepoužívá, ale přesto tam jsou. To jsou právě takové kotvy.

Kargokultické programování (Cargo cult programming)

Programátoři, vyznávající kargo kult, se projevují tím, že mechanicky používají vzory a postupy, aniž by opravdu chápali, proč je používají. A týká se to nejen programátorů…

Skrývání chyb (Error hiding)

Někteří vývojáři vyznávají princip „chyba je selhání vývojáře“. Někdy takový princip vyznává vedoucí týmu. Logickým protihmatem je tedy všechny výjimky odchytit, nevypsat nic a tvářit se, že chyby nejsou. A po pravdě řečeno – vypsat chybové hlášení „Došlo k chybě, ouha“ je v zásadě totéž jako nevypsat nic.

Loop-switch sequence

Představte si, že máte v kódu vykonat určitou posloupnost činností. Pokud chcete využít tento antipattern, udělejte si smyčku FOR s proměnnou, řekněme, i, do těla smyčky dejte switch podle této proměnné a pro každou hodnotu nadefinujte jednu činnost. Úspěch zaručen!

Magická čísla (Magic numbers)

a = n ^ 0.15915494309189533576888376337251  – prosím? Nechť zvedne ruku každý, kdo na první pohled pochopil, že to číslo je 1/(2*PI)… Pokud už nějaké takové číslo potřebujete, vložte ho jako pojmenovanou konstantu a vysvětlete význam.

Copy and paste programming

Programování metodou copy-paste porušuje hned několik zásad správného programování. Zamyslete se, jestli by nešlo nahradit zkopírovaný (a pozměněný) kód nějakým obecným řešením.

Zlaté kladivo (Golden hammer) a stříbrná kulka (Silver Bullet)

Oblíbený postup, u něhož věříme, že je vždy použitelný, je takové zlaté kladivo. Oblíbený postup, u kterého věříme, že vyřeší všechny možné problémy, je stříbrná kulka. Obojí je většinou iluze.

Faktor nepravděpodobnosti (Improbability factor)

V systému je známá, i když vzácná chyba, ale místo toho, abychom s ní počítali a ošetřili ji v kódu, tak se spoléháme na to, že zrovna u nás nenastane. Proč si přidělávat práci, že?

Programování metodou pokus-omyl (Programming by permutation, „programming by accident“)

Cyklus změna – test – změna – test…, aniž bychom věděli, co máme změnit a proč, ale spíš naslepo střílíme a čekáme, že to jednou začne fungovat.

Vynalézání kola (Reinventing the wheel)

Existuje přijatelné a odpovídající obecné řešení problému, ale my si přesto zvolíme cestu psaní vlastního kódu s bonusovou možností nasekat stejné chyby, jaké udělali tvůrci toho řešení, a přidat i pár nových.

Vynalézání hranatého kola (Reinventing the square wheel)

Existuje přijatelné a odpovídající obecné řešení problému, ale my si přesto zvolíme řešení na míru, které bude mnohem horší.

Projektové antipatterny

Pochod smrti (Death march)

Všichni vědí, že projekt skončí katastroficky, ale skrývají skutečný stav věcí, aby se vyhnuli zastavení a zrušení celého projektu. Někdy se to podaří utajovat a celý projekt uměle udržovat při životě až do chvíle, kdy přijde Den D. Jiná definice pochodu smrti říká, že jde o situaci, kdy jsou vývojáři nuceni pracovat přesčas a o víkendech, i když je každému jasné, že termín dokončení je naprosto nesmyslný a nelze to stihnout, ani kdyby měl den 36 hodin.

Groupthink

Termín z psychologie, popisuje situaci, kdy se skupina lidí uzavře před pohledem zvenčí a navzájem se ujišťují, že jejich pohled na věc či zvolený postup je správný. Též „nemoc výborů“ a „problém komisí“.

Analysis paralysis

Tak dlouho se vypracovávají analýzy, zprávy, rozbory a posudky, až už není potřeba nic programovat. Důsledným analyzováním všeho a neustálým svoláváním porad lze zaměstnat hned několik týmů na dlouhé měsíce, během nichž budou všichni pracovat, aniž by vytvořili cokoli funkčního.

Navrženo komisí (Design by committee)

Návrh potřebuje jednotnou vizi. V situaci, kdy do návrhu mluví každý a každý považuje svůj pohled za stejně důležitý jako pohled ostatních, vznikne nekoncepční zmetek.

Komise rozhodla (Escalation of commitment)

…a pak se ukáže, že její rozhodnutí je špatné. Ovšem nikdo ho už není schopen odvolat, a tak se dál pokračuje špatným směrem.

Morální hazard (Moral hazard)

Popis tohoto antipatternu je všeříkající: o věcech rozhoduje člověk, který nikdy nepocítí následky svého rozhodnutí. 

Houbový management (Mushroom management)

Zaměstnanci jsou v prostředí připomínajícím pěstírnu hub: udržováni v temnotě, obklopeni hnojem, a jakmile vystrčí hlavu, tak jsou odříznuti a odstraněni. Tato obrazná definice popisuje situaci, kdy management cosi rozhoduje, ale zaměstnanci nedostávají pořádné instrukce, pokyny si často protiřečí, všechno je tajné, nikdo do ničeho pořádně nemůže mluvit, nikdo neví, kdo o věcech vlastně rozhoduje…

A mnohé další…

Antipatternů je mnohem víc, vybrali jsme jen některé z nich. Zájemci najdou víc v literatuře. Nezbývá než popřát všem takovou práci, kde nebudou muset žádný z nich používat.

Tento text čerpá z popisů antipatternů na Wikipedii, a vychází proto pod licencí CC-BY-SA.

Začal programovat v roce 1984 s programovatelnou kalkulačkou. Pokračoval k BASICu, assembleru Z80, Forthu, Pascalu, Céčku, dalším assemblerům, před časem v PHP a teď by rád neprogramoval a radši se věnoval starým počítačům.

Věděli jste, že nám můžete zasílat zprávičky? (Jen pro přihlášené.)

Komentáře: 93

Přehled komentářů

Blaazen Antipatternofobie
Ondřej Mirtes Re: Antipatternofobie
kraken Poltergeist
jehovista Re: Poltergeist
Hans Re: Poltergeist
X Re: Poltergeist
belzebub opisovani wikipedie
biq Re: opisovani wikipedie
belzebub Re: opisovani wikipedie
Ivan Nový Re: opisovani wikipedie
boban Re: opisovani wikipedie
kronta Re: opisovani wikipedie
koudy Re: opisovani wikipedie
??? Re: opisovani wikipedie
uf Re: opisovani wikipedie
Radek Re: opisovani wikipedie
wellczech Re: opisovani wikipedie
pht Re: opisovani wikipedie
tdvorak Re: opisovani wikipedie
snehuliak je to opisovanie
cpt. Rumpill Re: je to opisovanie
JScore Loop-switch sequence
Fandik Hacker Re: Loop-switch sequence
JScore Re: Loop-switch sequence
mmad Re: Loop-switch sequence
phr Re: Loop-switch sequence
Jirka Re: Loop-switch sequence
maryo Re: Antipatterny, smradlavý kód a Peterův princip v IT
Vebloud Re: Antipatterny, smradlavý kód a Peterův princip v IT
Branik Re: Antipatterny, smradlavý kód a Peterův princip v IT
Michal Augustýn Re: Antipatterny, smradlavý kód a Peterův princip v IT
Infragile Re: Antipatterny, smradlavý kód a Peterův princip v IT
Inkvizitor Code Complete jsem nečetl,
Martin Malý Re: Code Complete jsem nečetl,
Opravdový odborník :-) Re: Code Complete jsem nečetl,
Inkvizitor Díky za odpověď
Aichi Re: Code Complete jsem nečetl,
Martin Malý Re: Code Complete jsem nečetl,
Martin Soušek bohužel programátorem se člověk rodí - to se nenaučíte
Branik Re: bohužel programátorem se člověk rodí - to se nenaučíte
. Re: bohužel programátorem se člověk rodí - to se nenaučíte
ahmul Morální hazard
asdasd Re: Morální hazard
Ondřej Mirtes Další antipatterny
Opravdový odborník :-) Re: Další antipatterny
blizz Re: Další antipatterny
asdasd Re: Další antipatterny
Aleš Roubíček Re: Další antipatterny
Radek Miček Re: Další antipatterny
Aleš Roubíček Re: Další antipatterny
asdasd Re: Další antipatterny
Aleš Roubíček Re: Další antipatterny
asdasd Re: Další antipatterny
Michal Augustýn Re: Další antipatterny
František Kučera Re: Další antipatterny
ondra.novacisko.cz Re: Další antipatterny
Aleš Roubíček Re: Další antipatterny
Michal Augustýn Re: Další antipatterny
ondra.novacisko.cz Re: Další antipatterny
Michal Augustýn Re: Další antipatterny
ondra.novacisko.cz Re: Další antipatterny
Michal Augustýn Re: Další antipatterny
ondra.novacisko.cz Re: Další antipatterny
Aleš Roubíček Re: Další antipatterny
xxx Re: Další antipatterny
Aleš Roubíček Re: Další antipatterny
Branik Re: Další antipatterny
phr Re: Další antipatterny
Tonda Re: Další antipatterny
Ondřej Mirtes Re: Další antipatterny
jos Re: Další antipatterny
Nox Re: Další antipatterny
vonRibbentrop heje
Michal Wiglasz Re: heje
Sten Re: heje
utx Příklad: GTK+
ondra.novacisko.cz Re: Příklad: GTK+
Ondřej Mirtes Re: Příklad: GTK+
ondra.novacisko.cz Re: Příklad: GTK+
Ondřej Mirtes Re: Příklad: GTK+
ondra.novacisko.cz Re: Příklad: GTK+
uf Re: Příklad: GTK+
ondra.novacisko.cz Re: Příklad: GTK+
František Kučera Re: Příklad: GTK+
uf Re: Příklad: GTK+
Aminux EMACS
Sten Re: EMACS
verajo Hezky clanek!
rooobertek Super článok
carlo.kokoth Původně jsem chtěl komentovat ...
100% Lenin Re: Původně jsem chtěl komentovat ...
100% Lenin Re: Původně jsem chtěl komentovat ...
veselej Naprosto sedí
Zdroj: https://www.zdrojak.cz/?p=3509