Nahoru
 

Defenzivní programování

Při programování se musí počítat s velkým množstvím situací, které mohou za běhu kódu nastat. Může se jednat o špatně zadaný vstup od uživatele, nepředpokládaná velikost souboru nebo různé další nepříznivé okolnosti. Perfektní aplikace se vypořádá se vším a správně. Samozřejmě naprosto dokonalý program vytvořit nelze. Jde se mu ale přiblížit pomocí defenzivního programování.

Myšlenku defenzivního programování si lze představit na jednoduchém příkladu řidiče auta. Dovolím si tento příklad nazvat defenzivní řízení. Je to takový způsob řízení, při kterém nevěříte ostatním řidičům a nikdy si nejste jistí, co udělají. Až některý z nich udělá chybu, vy na ni okamžitě zareagujete a nebudete zraněni. Berete za sebe zodpovědnost i kdybyste za případnou srážku nemohli. Při defenzivním programování přejímají roli ostatních řidičů data, která přišla z jiných procedur, např. vám má dorazit číslo mezi 0 a 100, ale po nové aktualizaci aplikace přijde 101.

Asserty

Prvním krokem k defenzivnějšímu kódu jsou tzv. asserty (z anglického Asserstions). Jde o kód používaný během vývoje, který má za úkol kontrolovat sám sebe za běhu. Testují tedy aplikaci automaticky (více o automatickém testování se dozvíte v článku Automatické testování softwaru, neboli kód, co kontroluje kód). Jejich hlavním přínosem je zbavení se nepříjemných chyb způsobených modifikací nějaké části programu, kdy po aktualizaci nesedí některá data.

Splněné testy
Obrázek č. 1: Asserty jsou skvělým způsobem, jak zjistit, že nové aktualizace programu nerozbily předešlý kód

Jako příklad bych uvedl část kódu, která má za úkol šifrovat text. Po prvním vyzkoušení se zdá být vše v pořádku, a tak to pustíte do světa. Časem se ale přijde na to, že je potřeba šifrování udělat bezpečnější. Otevřete tedy část programu obstarávající šifrování a zabezpečíte ho. Tím se však změní způsob, jakým se nešifrovaný text změní v zašifrovaný. V kódu jsme však udělali chybu a některé speciální příklady se nepřekládají správně, jako předtím. Díky sebekontrolovacímu kódu jsme na to byli upozorněni. Pokud bychom neměli automaticky otestovanou funkčnost rozpoznávání šifrovaných a nešifrovaných textů, mohli bychom nefunkční aplikaci s klidem předat a na chybu by přišli až sami uživatelé.

Asserty by se měli používat pro speciální situace. Špatný uživatelský vstup a podobné běžné chyby je lepší zpracovat jinak.

Zpracování chyb

Zpracováním chyb (anglicky Error-Handling) rozumíme zachycení neočekávané události a následnou rozumnou reakci aplikace. Uživatel místo čísla zadá text. Program by si to měl sám uvědomit a zobrazit například chybovou hlášku „Prosím zadejte číslo“.

Špatný vstup od uživatele
Obrázek č. 2: Špatný vstup od uživatele lze zpracovat takto.

V závislosti na okolnostech se aplikace při chybě může zachovat různě. Zadáním špatného vstupu se zobrazí chybová hláška. Pokud aplikace zachytává každou desetinu sekundy teplotu a současné měření bylo mimo rozsah, může použít předchozí naměřenou hodnotu. V jiném případě lze chybu zaznamenat do souboru (logu) a nechat program běžet dál. Možností, jak zpracovat události, pro které kód není stavěný, je spoustu.

Vždy zpracujte chybu tak, aby byla vzhledem k uživateli co možná nejpřívětivější.

Oproti assertům, které jsou čistě pro vývojáře, musíte při zpracování chyb uvažovat nad tím, jak se bude uživateli aplikace ovládat. S tím souvisí pojmy robustnost a korektnost.

Robustnost vs. Korektnost

O aplikaci řekneme, že je robustní, pokud se za každou cenu snaží udržet běh programu, nehledě na špatná data, které do něj pošleme. Na druhé straně korektní kód nikdy nevrátí nepřesný výsledek, ale raději se zastaví a zobrazí chybovou hlášku.

Nelze říci, jestli je lepší robustní nebo korektní program, protože to vždy záleží na konkrétní situaci. Pokud se při běhu hry špatně načte barva pixelu na moři, použije se robustní postup, kde lze použít barvu posledního načteného pixelu, protože očekáváme, že moře bude velké. Naopak u aplikace pro kosmickou raketu, která počítá úhel, ve kterém má letět, aby doletěla na požadované místo, se použije korektní postup. Určitě nechceme místo na Mars poslat naší milovanou raketu někam pryč do vesmíru.

V některých aplikacích lze použít tzv. barikádu. Ta funguje stejně jako například průchod na operační sál v nemocnici. Všechno, co projde dveřmi musí být sterilizováno, jinak to zůstane venku. V programu to znamená, že si například vytvoříme nějakou validační proceduru, která nám zajistí správnost všech dat.

Defenzivní programování je bezpochyby skvělá věc. Má ovšem jeden paradox. Při vývoji programu chcete, aby případná chyba byla hned vidět a vy ji tím pádem mohli opravit. Jenže v ostrém nasazení vám jde o přívětivé zachování aplikace vzhledem k uživateli. S tímto paradoxem se musí každý vypořádat po svém v závislosti na tom, jaké technologie používá pro vývoj. V C++ lze například použít zabudovaný preprocesor, který při kompilaci může vynechat některé části kódu.

Pokud chcete programovat funkční aplikace, ve kterých není moc chyb, fungují správně a uživatelé je rádi používají, tak určitě využijte defenzivní programování. Vyhnete se velkému množství bugů a jakmile si zvyknete na nový styl psaní kódu, přijde vám to naprosto přirozené.