David Majda mi poslal v komentářích výborný odkaz na svůj článek, kde upoutává na přestřelku dvou (zřejmě významných) programátorů na téma „výjimky vs. návratové kódy“.

U toho se musím zastavit. A už teď je mi jasné, že se tento seriál trošku protáhne.

Joel vs. Ned vs. dgx

Joel Spolsky tvrdí, že návratové kódy jsou dobré, protože výjimky jsou z nejrůznějších důvodů špatné. Ned Batchelder oponuje, že výjimky jsou kůl, protože návratové kódy jsou fuj.

Pokud trošku „děláte do demagogie“, tak vám z uvedeného je jasné, že taková diskuze je pouhý flame, neb se implikuje nesmyslně. Totiž názor, že něco je špatné, není možné použít jako argument, že něco jiného (a nikoliv doplňkového) je dobré. Či alespoň lepší. To by se mohli hádat donekonečna. Svou pravdu mají oba a jen těžko mohou vyvrátit pravdu toho druhého.

Jak návratové kódy, tak výjimky, mají obrovské nedostatky. Ano, řekl bych, že špatné je obojí. A nemá smysl řešit, co víc. Naopak má smysl nad celou situací trošku popřemýšlet, pokusit se celý problém abstrahovat a najít uspokojivé řešení. A pak se ho pokusit zrealizovat v programovacím jazyce.

No, takže teď už alespoň víte, že tohle není jen další článek na téma Abc je lepší než Xyz 😉

Abstrakce problému

Minule jsem tu naznačoval určitý mechanismus správy chyb, ve kterém hrály hlavní roli tři pojmy: funkce, chyby a varování. Když tak se na to ještě mrkněte.

  • Funkce – základní jednotka programu
  • Chyba – stav, kdy funkce nedosáhne svého cíle. Informace o chybě se předá volající funkci (je ve tvaru, aby ji funkce dovedla pochopit)
  • Varování – informace určená programátorům. Nezpůsobí ukončení funkce, program na ni nereaguje.

Logickou jednotkou programu je tedy funkce. Ta se buď zdárně vykoná a vrátí výslednou hodnotu, nebo dojde k chybě a s tím se funkce ukončí. Volající funkce je o chybě informována a nějakým způsobem ji ošetří. Třeba také vyvolá chybu, nebo varování, či pokračuje po určité větvi vykonávání dále. Nebo ji prostě ignoruje! Ano, ošetření ignorováním je zcela legitimní způsob ošetření.

V reálném světě je tomu stejně. Pokud se drobně škrábneme, nejedeme kvůli tomu do nemocnice, ale problém ignorujeme. V této analogii se výjimky chovají tak, že pokud se dostatečně škrábnutí nebudeme věnovat, dojde k odumření orgánu či dokonce okamžité smrti. Pro návratové kódy by zase sedělo, že sice škrábnutí umí v pohodě přejít, ale ignorují také uříznutí nohy cirkulárkou, neboť obojí jen stěží rozliší.

Volba mezi výjimkami a návratovým kódem je tedy volba mezi rychlou smrtí a postupným vykrvácením, dojde-li k neštěstí. Obojí má své zastánce 🙂

No, a teď zase vážně.

Problematika výjimek

Zatímco minule jsem si stěžoval, jak ubohou informační hodnotu má tzv. chybový návratový kód false, dnes se podívejme, jaké úskalí nám umí přichystat výjimky.

Představme si, že by v PHP najednou všechny funkce začaly namísto chybových kódů (jakým bývá často false) vracet výjimky. Položím vám otázku: co udělá (resp. může udělat) tento kód?

// korektně zjisti jméno uživatele
$user = isset($_GET['user']) && is_string($_GET['user'])
	  ? $_GET['user']
	  : '';

// ořízni na max. délku
$user = substr($user, 0, 30);

// pokusíme se zalogovat
try {
  $logged = in_array($user, myGetAllowedUsers(), true);
} catch (Exception $e) {
  die('Nelze pokračovat.');
}

...