Ošetřování nereálných stavů

Školení, která pořádám

Řekněme, že máme připravit kód pro výpis seznamu rubrik. Není nic jednoduššího:

<?php
echo "<ul>\n";
$result = mysql_query("SELECT * FROM rubriky ORDER BY nazev");
while ($row = mysql_fetch_assoc($result)) {
    echo "<li><a href='rubrika.php?id=$row[id]'>" . htmlspecialchars($row["nazev"]) . "</a></li>\n";
}
mysql_free_result($result);
echo "</ul>\n";
?>

Co když ale žádné rubriky existovat nebudou? Neměli bychom kód upravit následujícím způsobem?

<?php
$result = mysql_query("SELECT * FROM rubriky ORDER BY nazev");
if (!mysql_num_rows($result)) {
    echo "<p>Žádné rubriky.</p>\n";
} else {
    echo "<ul>\n";
    while ($row = mysql_fetch_assoc($result)) {
        echo "<li><a href='rubrika.php?id=$row[id]'>" . htmlspecialchars($row["nazev"]) . "</a></li>\n";
    }
    echo "</ul>\n";
}
mysql_free_result($result);
?>

Toto řešení vypadá na první pohled jako správné – řeší oba stavy, ke kterým může dojít (dále by mohlo být řešeno ošetření chyb). Pokud je ale z návrhu aplikace jasné, že nějaké rubriky budou vždy existovat (jedná se např. o uzavřený systém, pro který už máme k dispozici data), zdá se mi lepší původní řešení – je kratší, přehlednější a nakonec i nepatrně rychlejší.

I když by první varianta mohla vyprodukovat nevalidní HTML kód a tím způsobit chybu, tak si můžeme být jistí, že k tomu nikdy nedojde, a v kódu tento nereálný stav neřešit.

Jakub Vrána, Dobře míněné rady, 19.12.2007, diskuse: 12 (nové: 0)

Diskuse

ikona Marty:

Poznámka ze života: Nikdy však nedůvěřujte zákazníkovi, který tvrdí, že se něco nemůže(!) stát. Zákazník povětšinou totiž není programátor..

ikona karf:

Aneb praxí mnohokrát ověřený "Murphyho" zákon zvaný "tahle situace NIKDY nenastane".

ikona Dzoukr:

Nebo-li "Já vím, že jsem vám to zapomněl říct, ale vzpomněl jsem si na takovou maličkost..." :)))

Jarda:

Vždy jedu podobně jako v druhé variantě. Ono je i při ladění příjemnější, když to vypíše "Žádné rubriky" než nic. :o)

Luke:

Osobne si myslim ze kazdu chybu by programator mal osetrit, ci odchytit.. a nespoliehat sa na to, ze nikdy nenastane..

Nashai:

2 Luke:
Osobně si myslím, že programátor by měl spoléhat na to, že každá chyba alespoň jednou nastane. Bo pak si ušetří hafo problémů.

Martin:

Myslím si, že tohle téma v rubrice "Dobře míněné rady" nemá co dělat. Rada má být takové, aby platila pořád a mohl se podle ní slepě orientovat každý blbec. Rada může být třeba toto: slovo "neboli" se píše vždy dohromady, nikdy jako "nebo-li".
Oproti tomu ošetřování chyb vždy závisí na konkrétním případu a je potřeba zapojit vlastní invenci a zkušenost a zvolit nejlepší možnost. V předložených příkladech vidím problém v tom, že z prvního padá nevalidní kód. Nevalidní kód by nikdy z aplikace neměl jít.
Druhý příklad je problematický tím, že vypisuje chybovou hlášku. Chybová hláška tohoto typu je většinou nesmysl. Uživatel musí být odstíněn od technických detailů. Když nejsou k dispozici rubriky, ať jednoduše nejsou zobrazeny. Oba příklady bych zkombinoval tak, aby v případě neexistence rubrik nebyly vypsány ani tagy začátku a konce seznamu. Vždycky je ale potřeba důkladně přemýšlet nad praktických dopadem řešením

ikona Dzoukr:

Omlouvám se za neboli. A teď k tématu. Pokud jsem v uzavřeném systému, tak mě validnost zajímat nemusí. Pokud ne, vypisovat "chybovou" hlášku mi připadá VELMI rozumné. To, že se v kategoriích žádná nezobrazí, nemusí uživatel pochopit. Zní to divně, ale je to tak. Hláška "Nic tu není" je pro něj daleko lepší, než nevypsat nic a čekat, jak to pochopí. Když to vezmeme důkladně, tak by se správně ani link pro seznam kategorií neměl zobrazit (pokud není už součástí designu - třeba v levém sloupci), pokud žádné nejsou k dispozici. Možná je to deformace, ale vždy když vidím někde, kde by nemělo být, prázdné místo, tak mám pocit, že došlo k chybě a programátor mi o tom jen zapomněl říct.

ikona finc:

Nesmyslna je chybova hlaska typu: "Exception ... line ...".

Navic, zde se nejedna o chybovou hlasku, ale o informaci, ktera oznamuje, ze nic nenalezl. Takovato hlaska je jiste dobra, uz jen z duvodu toho, ze pokud nic nezobrazim, uzivatel muze predpokladat, ze se stranka stale "nacita". Ne kazdy dokaze odhadnout, kdy uspesne provedl operaci (bohuzel).

Jinak, souhlasim s tim, ze toto neni rada, ale pouze navrh, jak danou vec resit. Vzdy je to jine a toto je prilis vytrzeno z kontextu, nez aby se dalo rict: "takto to delej".

I:

Exception ... line ... je naopak smyslne, a to predevsim pokud je rovnou vypsan backtrace. Ve skutecnosti totiz nedochazi k zadnym chybam, ale pouze k vyjimkam. Staci pridat standardni exception handler, ktery je bude ukladat a za chvili je program krasne odladen a navic hlaseni vyjimky muze byt graficky nadherne ztvarneno. Naopak pokud dojde k vyjimce a veskere co program vypise je "Doslo k chybe", pak bych nejradeji vzal kladivo a nekomu s nim zatloukl hrebik do cela...

ikona finc:

Samozrejme jsem mel na mysli neosetrenou vyjimku. Neco jineho je ladeni aplikace u vyvojare, jine muze byt pri testovani a jine pri pouziti u klienta.

ikona v6ak:

Uživatel by se měl dozvědět něco jako že došlo k chybě. To, že došlo třeba k PDOException asi bude zajímat spíše útočníka než běžného uživatele. (Jasně, nevypsání chyby není zabezpečením, jen ztížením zneužití případné chyby.)

BTW:Jednou jsem na Živě.cz náhodou našel skript podporující SQL injection a ten neměl problémy napsat, co ho trápí. Takže takto ne.

Podrobný popis chyby by měl jen být poslán programátorovi. Já osobně kašlu na šifrování a pošlu to normálně nešifrovaně mailem. Ale zase to mám přeposlaný na SMS e-mail a vím to hned včetně části podrobností.

Diskuse je zrušena z důvodu spamu.

avatar © 2005-2024 Jakub Vrána. Publikované texty můžete přetiskovat pouze se svolením autora. Ukázky kódu smíte používat s uvedením autora a URL tohoto webu bez dalších omezení Creative Commons. Můžeme si tykat. Skripty předpokládají nastavení: magic_quotes_gpc=Off, magic_quotes_runtime=Off, error_reporting=E_ALL & ~E_NOTICE a očekávají předchozí zavolání mysql_set_charset. Skripty by měly být funkční v PHP >= 4.3 a PHP >= 5.0.