Umění házet chyby JavaScriptu

Když jsem byl mladší, nejzáludnější částí programovacích jazyků byla schopnost vytvářet chyby. Moje první reakce na throw Operátor v Javě byl:„To je hloupé, proč byste to někdy chtěli způsobit chyba?" Chyby byly pro mě nepřítelem, čemu jsem se snažil vyhnout, takže schopnost způsobit chybu mi připadala jako zbytečná a nebezpečná stránka jazyka. Myslel jsem, že je hloupé zahrnout stejný operátor do JavaScriptu, jazyka, kterému lidé v první řadě prostě nerozuměli. Nyní s velkým množstvím zkušeností na svém kontě jsem velkým fanouškem házení vlastních chyb. Pokud to uděláte správně, může to vést ke snadnějšímu ladění a údržbě kódu.

Při programování dojde k chybě, když se stane něco neočekávaného. Možná byla do funkce předána nesprávná hodnota nebo matematická operace měla neplatný operand. Programovací jazyky definují základní sadu pravidel, která, když se odchýlí, vedou k chybám, takže vývojář může kód opravit. Ladění by bylo téměř nemožné, pokud by chyby nebyly vyvolány a nahlášeny vám. Pokud by vše tiše selhalo, trvalo by vám dlouho, než byste si všimli, že došlo k problému, natož ho izolovat a opravit. Chyby jsou přátelé vývojářů, ne nepřátelé.

Problém s chybami je v tom, že mají tendenci se objevovat na neočekávaných místech a v neočekávanou dobu. Aby toho nebylo málo, výchozí chybové zprávy jsou obvykle příliš stručné na to, aby skutečně vysvětlily, co se pokazilo. Chybové zprávy JavaScriptu jsou notoricky neinformativní a záhadné (zejména v Internet Exploreru), což problém jen zhoršuje. Představte si, že by se objevila chyba se zprávou, že „tato funkce selhala, protože se to stalo“. Okamžitě se váš úkol ladění zjednoduší. To je výhoda házení vlastních chyb.

Pomáhá chápat chyby jako vestavěné případy selhání. Vždy je snazší naplánovat selhání v konkrétním bodě kódu, než předvídat selhání všude. To je velmi běžná praxe v produktovém designu, nejen v kódu. Auta jsou vyrobena s deformačními zónami, oblastmi rámu, které jsou navrženy tak, aby se při nárazu zhroutily předvídatelným způsobem. Znalost toho, jak bude rám reagovat při nárazu, které části selžou, umožňuje výrobcům zajistit bezpečnost cestujících. Váš kód lze sestavit stejným způsobem.

Přestože JavaScript ušel v posledních letech dlouhou cestu, vývojáři JavaScriptu mají stále mnohem méně nástrojů na pomoc při ladění než vývojáři jiných jazyků. Vhazování chyb ve vašem JavaScriptu je pravděpodobně cennější než v jakémkoli jiném jazyce kvůli potížím s laděním. Můžete vyvolat pomocí throw operátora a poskytnutí předmětu k odhození. Lze hodit jakýkoli typ objektu, avšak Error objekt je nejtypičtější k použití:

throw new Error("Something bad happened.")

Když vyvoláte chybu tímto způsobem a chyba není zachycena pomocí try-catch prohlášení, prohlížeč zobrazí text chyby obvyklým způsobem. Pro Internet Explorer to znamená, že se v levém dolním rohu prohlížeče zobrazí malá ikona a po poklepání na tuto ikonu se zobrazí dialogové okno s textem chyby; Firefox s nainstalovaným Firebugem zobrazí chybu v konzole; Safari a Chrome vypisují chybu do webového inspektoru; Opera zobrazuje chybu v Error Console. Jinými slovy, je to považováno za chybu, kterou jste nevyvolali.

Rozdíl je v tom, že musíte zadat přesný text, který má prohlížeč zobrazit. Namísto pouze čísel řádků a sloupců můžete zahrnout jakékoli informace, které budete potřebovat k úspěšnému odladění problému. Obvykle doporučuji, abyste v chybové zprávě vždy uvedli název funkce a také důvod, proč funkce selhala. Zvažte následující funkci:

function addClass(element, className){
    element.className += " " + className;
}

Účelem této funkce je přidat k danému prvku novou CSS třídu (velmi běžná metoda v knihovnách JavaScriptu). Ale co se stane, když element je null ? Zobrazí se záhadná chybová zpráva, například „očekávaný objekt“. Poté se budete muset podívat na spouštěcí zásobník (pokud jej váš prohlížeč podporuje), abyste skutečně našli zdroj problému. Ladění je mnohem snazší vyvoláním chyby:

function addClass(element, className){
    if (element != null && typeof element.className == "string"){
        element.className += " " + className;
    } else {
        throw new Error("addClass(): First arg must be a DOM element.");
    }
}

Diskuse o přesné detekci, zda je objekt prvkem DOM či nikoli, tato metoda nyní poskytuje lepší zasílání zpráv, když selže kvůli neplatnému element argument. Vidíte-li takovou podrobnou zprávu v chybové konzoli, okamžitě se dostanete ke zdroji problému. Rád přemýšlím o házení chyb jako o tom, že si nechám post-it poznámky, proč něco selhalo.

Pochopení toho, jak házet chyby, je jen jedna část rovnice; pochopení kdy házet chyby je druhá. Protože JavaScript nemá kontrolu typu nebo argumentů, mnoho vývojářů nesprávně předpokládá, že by to měli implementovat pro každou funkci. Je to nepraktické a může to nepříznivě ovlivnit celkový výkon skriptu. Klíčem je identifikovat části kódu, které pravděpodobně určitým způsobem selžou, a pouze tam házet chyby. Stručně řečeno, vyhazujte chyby pouze tam, kde k chybám již dojde.

Pokud funkci budou volat pouze známé entity, kontrola chyb pravděpodobně není nutná (to je případ soukromých funkcí); pokud nemůžete předem identifikovat všechna místa, kde bude funkce volána, pak budete pravděpodobně potřebovat nějakou kontrolu chyb a ještě pravděpodobněji budete mít prospěch z vyvolání vlastních chyb. Nejlepší místo pro vyvolání chyb je v obslužných funkcích, těch funkcích, které jsou obecnou součástí skriptovacího prostředí a lze je použít na libovolném počtu míst. To je přesně případ JavaScriptových knihoven.

Všechny knihovny JavaScriptu by měly generovat chyby ze svých veřejných rozhraní pro známé chybové stavy. YUI/jQuery/Dojo/atd. nelze předvídat, kdy a kde zavoláte jejich funkce. Jejich úkolem je říct vám, když děláte hlouposti. Proč? Protože byste neměli muset ladit jejich kód, abyste zjistili, co se pokazilo. Zásobník volání pro chybu by měl končit v rozhraní knihovny, ne hlouběji. Není nic horšího, než vidět chybu, která má 12 funkcí hluboko v knihovně; vývojáři knihoven mají odpovědnost za to, aby se tomu nestalo.

To platí i pro soukromé JavaScriptové knihovny. Mnoho webových aplikací má své vlastní proprietární knihovny JavaScriptu, buď vytvořené pomocí známých veřejných možností nebo namísto nich. Cílem knihoven je usnadnit vývojářům život, a to pomocí abstrakce od špinavých implementačních detailů. Vyhazování chyb pomáhá udržet tyto nečisté detaily implementace bezpečně skryté před vývojáři.

JavaScript také poskytuje try-catch příkaz, který je schopen zachytit vyvolané chyby dříve, než je zpracuje prohlížeč. Vývojáři mají obvykle potíže s rozlišením, zda je vhodné vyvolat chybu nebo ji zachytit pomocí try-catch . Chyby by měly být vyvolány pouze v nejhlubší části zásobníku aplikací, což, jak bylo uvedeno dříve, obvykle znamená knihovny JavaScriptu. Jakýkoli kód, který zpracovává logiku specifickou pro aplikaci, by měl mít možnosti zpracování chyb, a proto by měl zachycovat chyby vyvolané komponentami nižší úrovně.

Aplikační logika vždy ví, proč volala určitou funkci, a proto se nejlépe hodí pro řešení chyby. Je důležité zmínit, že byste nikdy neměli mít try-catch příkaz s prázdným catch doložka; chyby byste měli vždy nějakým způsobem řešit. To se může lišit ve vývoji oproti výrobě, ale musí se to udělat. Pokud dojde k chybě, odpověď by nikdy neměla být jednoduše zabalit ji do try-catch a nech to být – tím se chyba spíše maskuje, než aby se jí zabývala.

Házení chyb v JavaScriptu je umění. Chvíli trvá, než zjistíte, kde by příslušné části vašeho kódu měly způsobit chyby. Jakmile to však zjistíte, zjistíte, že se doba ladění zkrátí a vaše spokojenost s kódem se zvýší.