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.
Diskuse
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..
Aneb praxí mnohokrát ověřený "Murphyho" zákon zvaný "tahle situace NIKDY nenastane".
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
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.
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...
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.
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.