Kdy je nejlepší čas nasadit testy do vývoje a kdy už je pozdě?
Poslední oblastí, kde se chyby projeví nejpozději, je správa paměti. Swift používá automatické počítání referencí, ale cyklické reference umí potrápit. Pokud si dva objekty drží silnou referenci navzájem, nikdy se neuvolní. Řešením je slabá reference na jednom z nich. Kontrolujte to hlavně u delegátů a uzávěrů. Uzávěr, který zachytí objekt a zároveň je jím vlastněn, vytvoří smyčku. Pomůže záchytný seznam s slabou referencí. Tento problém se neprojeví hned, ale po delším používání aplikace začne růst spotřeba paměti a aplikace se zpomalí.
Prvním krokem není psát testy na všechno. Vyberte jednu kritickou funkci, kterou si nejčastěji rozbijíte, a napište pro ni jeden test, který ověří její základní chování. Nemusí jít o unit test na izolovanou metodu. Často stačí integrační test, který projde celou cestou od vstupu po výstup. Důležité je, aby test byl deterministický a nezávisel na datech v produkční databázi.
Podepisování a ověřování Pro symetrické podepisování (HS256) používejte dostatečně dlouhý a náhodný klíč, ideálně z proměnné prostředí, nikdy ne v kódu. Asymetrické algoritmy (RS256, ES256) jsou vhodné, když token vydává jedna služba a ověřuje jiná – veřejný klíč lze bezpečně distribuovat. Vždy explicitně povolte pouze jeden algoritmus a při ověřování ho vynuťte. Typická chyba je přijetí algoritmu none nebo toho, který útočník vloží do hlavičky. Totéž platí pro ignorování podpisu u knihoven, které to umožňují konfigurací.
Asynchronní logiku držte mimo komponenty. Thunky nebo middlewary jsou v pořádku, ale nesmí se z nich stát druhá vrstva byznys logiky. Načtení dat, transformace a uložení do storu patří do jednoho místa. V komponentě pak zůstane jen volání dispatch a čtení stavu. Pokud fetchujete data v useEffect a zároveň je ukládáte do Reduxu, hlídejte závislosti a rušte požadavky při odpojení komponenty, jinak si vyrobíte race condition.
Prvním krokem je pochopit, že Swift není jen jazyk, ale i ekosystém. Když vytvoříte nový projekt, dostanete kostru s několika soubory. Neignorujte je. Rozdělte logiku do menších typů – struktury a třídy mají jasně daný účel. Struktury používejte pro data, která se nemění, třídy pro objekty se stavem. Typickým omylem je snaha nacpat vše do jedné velké třídy, která dědí z uživatelského rozhraní. Výsledkem je nečitelný kód, kde se nedá dohledat, co vlastně mění data.
Redux sám o sobě není pomalý ani složitý. Problém začíná ve chvíli, kdy do globálního storu cpete data, která patří lokálně, a kdy každou změnu řešíte ručním překreslováním. Základem je rozhodnout, co skutečně patří do globálního stavu: přihlášený uživatel, nastavení aplikace, data sdílená mezi vzdálenými částmi stromu. Formulářová pole, otevřené modaly nebo hodnoty jednoho inputu nechte v lokálním stavu komponenty. Čím menší store, tím méně problémů s výkonem i čitelností.
Mezi typické chyby patří spouštění procesu jako root. Kontejner s právy root uvnitř znamená, že případný únik z izolace má vážnější dopady. Řešením je vytvořit v Dockerfile běžného uživatele a přepnout se na něj instrukcí USER. Další opakovanou chybou je ukládání dat do zapisovatelné vrstvy kontejneru. Ta zmizí při smazání kontejneru. Data patří do svazku, tedy volume, nebo do připojeného adresáře z hostitele. Stejně tak se nastavení nemá zapisovat natvrdo do obrazu, ale předávat přes proměnné prostředí nebo připojený konfigurační soubor.
Akce navrhujte jako události, ne jako settery. Místo SET_ITEMS použijte itemsLoaded nebo itemsFetchFailed. Akce by měla popsat, co se stalo, a reducer rozhodne, co to znamená pro stav. Do payloadu posílejte jen to, co reducer potřebuje. Když do akce přidáte celý objekt i s daty, která se nikdy nezmění, zbytečně nafukujete historii a ztěžujete ladění.
Testy se do projektu nasazují v momentě, kdy začíná růst složitost a počet lidí, kteří na kódu pracují. Pokud jste jediný vývojář a píšete malý skript, který za týden smažete, nemá smysl investovat čas do testovací infrastruktury. Jakmile ale kód přežije víc než jedno vydání, začnou se v něm objevovat závislosti a přestanete si pamatovat, proč která podmínka existuje, je čas začít.
Poslední věc, kterou začátečník podcení, je síť a porty. Kontejner má vlastní síťový prostor, takže aplikace naslouchající na portu uvnitř kontejneru není z hostitele dostupná sama od sebe. Je potřeba port zveřejnit při spuštění. Když se aplikace uvnitř kontejneru nedá spojit s databází běžící na hostiteli, problém bývá v tom, že localhost uvnitř kontejneru znamená samotný kontejner, ne hostitele. Řešením je adresa hostitele nebo společná síť, do které se oba kontejnery připojí.