V JavaScriptu a TypeScriptu je častým problémem správné řízení hodnot, které mohou být null nebo undefined. Abychom se vyhnuli zbytečným kontrolám a repetitivnímu kódu, můžeme využít funkce, jako je optional chaining a nullish coalescing operator (??), které nám umožní elegantně ošetřit tyto situace. Například zápis user?.name?.middle ?? '' nám zajistí, že pokud nějaká hodnota nebude dostupná, místo chyby dostaneme prázdný řetězec. To je užitečné pro zajištění stabilního a robustního kódu, který lépe zvládá dynamiku runtime prostředí JavaScriptu. Při návrhu kódu si musíme rozmyslet, zda zavádíme do logiky koncept null nebo jestli místo toho používáme výchozí hodnoty, jako je prázdný řetězec.
Další důležitou součástí návrhu kódu je vytváření tříd a entit, které definují chování našich datových modelů, jako je například třída User. V tomto kontextu je dobré aplikovat objektově orientované programování (OOP), což nám umožňuje nejen definovat strukturu, ale i implementovat chování. Třídy nám poskytují strukturovaný přístup k implementaci a snadnou údržbu, což je užitečné při práci na větších projektech.
Začněme tedy vytvářet třídu User, která bude obsahovat všechny potřebné vlastnosti a metody, jež nám umožní efektivně manipulovat s uživatelskými daty v rámci aplikace. Základem bude využití rozhraní (interface), které nám umožní specifikovat, jaké vlastnosti a metody by měly objekty obsahovat. Třída následně tyto vlastnosti implementuje a přidává vlastní chování.
V prvním kroku bychom měli definovat potřebné enums a interfaces pro uživatelské entity. Pro začátek vytvoříme enum pro role uživatele, což je důležité pro správnou autentizaci a autorizaci v aplikaci. Například role uživatele mohou být definovány jako:
Tato enumerace pomáhá nejen v definici uživatelských práv, ale také poskytuje konzistenci v kódu, čímž zamezuje chybám způsobeným nesprávným používáním řetězcových literálů.
Dále, pro lepší čitelnost a správnost kódu, je nutné vytvořit třídu pro User, která bude implementovat rozhraní IUser. To nám poskytne základní strukturu pro všechny vlastnosti, které uživatel může mít, jako jsou jeho e-mail, jméno, adresa nebo telefonní čísla. Tato třída bude mít i metody, které nám umožní snadno vytvářet instance uživatele na základě těchto dat.
Příklad definice uživatelského rozhraní IUser:
Toto rozhraní nám umožňuje nejen definovat strukturu dat, ale také lépe pracovat s hodnotami, které mohou být null nebo typu string, jako je například datum narození. Důležitým aspektem je také využití union types, které umožňují flexibilitu a zajišťují kompatibilitu mezi různými formáty dat.
V rámci této třídy implementujeme i metody pro manipulaci s těmito daty. Například statickou metodu Build, která umožňuje snadno vytvářet nové instance třídy User na základě dat z externího zdroje, což je běžná praxe při práci s API nebo při načítání dat z databáze.
Tato statická metoda nejenže vytváří nový objekt User, ale také řeší případy, kdy je datum narození reprezentováno jako řetězec, a bezpečně ho převádí na typ Date.
Důležitým prvkem v návrhu této třídy je využití OOP principů, jako jsou třídy, rozhraní a enums, které nám umožňují udržovat kód organizovaný a dobře strukturovaný. Takto navržená aplikace je mnohem lépe udržovatelná a rozšiřitelná, protože každý komponent je jasně definován a oddělen od ostatních. Kromě toho můžeme znovu využít stejné třídy a rozhraní v dalších částech aplikace, což zajišťuje konzistenci dat a snižuje možnost chyb.
Pokud jde o autentizaci a autorizaci, je kladeno důraz na to, aby se vytvoření výchozího objektu User provádělo na jednom centrálním místě, což eliminuje potřebu kopírovat kód na různých místech aplikace. Tento přístup pomáhá zajistit, že všechny instance uživatelů mají stejné počáteční hodnoty a že jejich stav je snadno a rychle přístupný z různých částí aplikace.
Jak implementovat validace a služby pro UI v Angular aplikaci?
Při vývoji webových aplikací na platformě Angular je velmi důležité nejen zajistit správnou funkčnost aplikace, ale také poskytnout uživateli intuitivní a příjemný zážitek. Tento proces zahrnuje efektivní správu formulářových validací, přehledné zobrazení notifikací a potvrzovacích dialogů a implementaci flexibilního navigačního systému. V této kapitole se zaměříme na konkrétní implementace těchto prvků, které mohou zjednodušit práci s aplikací a zlepšit uživatelský zážitek.
Při práci s validacemi formulářů je důležité mít dobře strukturovaný a snadno udržovatelný kód. Angular nabízí efektivní nástroje pro validaci, jako jsou Validators pro základní kontroly jako povinnost vyplnění nebo formát emailu. Pro složitější potřeby, jako je validace hesla, je možné využít regulární výrazy nebo specializované balíčky, jako je owasp-password-strength-test. Tento balíček umožňuje definovat požadavky na složitost hesla, což je důležité pro zajištění bezpečnosti aplikace. Doporučuje se také nastavit maximální délku a minimální délku hesla, což je v souladu s osvědčenými bezpečnostními standardy.
Při vývoji komponenty pro přihlášení uživatele (LoginComponent) s novými validacemi emailu a hesla použijeme FormBuilder pro vytvoření formuláře a následně implementujeme požadované validace. Formulář může vypadat takto:
Tato část kódu zajišťuje, že uživatel bude moci zadat pouze platnou emailovou adresu a heslo, které splňuje stanovené požadavky.
Další důležitou součástí aplikace je zobrazování notifikací a potvrzovacích dialogů. Ať už se jedná o rychlou informaci pro uživatele, nebo o potvrzení akce, je dobré mít centralizovaný mechanismus pro zobrazení těchto interakcí. K tomu lze využít Angular službu, která obaluje běžné chování pro zobrazení toast notifikací a dialogů. Služba UiService zjednodušuje opakované volání těchto funkcí ve všech částech aplikace, čímž šetří čas vývojářů a udržuje kód čistý.
V rámci této služby implementujeme dvě funkce: showToast pro zobrazování toast notifikací a showDialog pro potvrzovací dialogy. Používáme k tomu komponenty jako MatSnackBar pro toast notifikace a MatDialog pro dialogy. Tyto komponenty jsou součástí Angular Material, které poskytují jednoduché, přizpůsobitelné a dobře optimalizované možnosti pro práci s UI.
Například funkce showToast je implementována následovně:
Pokud chceme uživateli nabídnout možnost rozhodnutí, použijeme dialog. Pro tento účel je potřeba vytvořit vlastní komponentu, která zobrazuje dialogové okno. Tato komponenta může být použita v celé aplikaci, a to prostřednictvím MatDialog.
Pokud chceme přidat tuto funkcionalitu do aplikace, využijeme environment provider pro zajištění správného poskytování služeb napříč aplikací. To znamená, že definujeme službu tak, aby byla dostupná pro všechny komponenty a služby bez nutnosti jejího explicitního importování v každé komponentě.
Jakmile máme připravený základ pro validace a UI služby, můžeme je použít v přihlašovací komponentě pro zobrazování uživatelských informací nebo notifikací. Po úspěšném přihlášení například zobrazíme uživatelský toast:
Tento toast bude zobrazen na obrazovce po úspěšném přihlášení, což poskytuje uživateli zpětnou vazbu, že přihlášení probíhlo úspěšně.
Při rozhodování mezi zobrazováním toastu a dialogu je dobré mít na paměti, že toast je lepší volbou pro nenápadné informace, které nevyžadují okamžité rozhodnutí uživatele. Naproti tomu dialogy by měly být vyhrazeny pro situace, kdy uživatel musí provést akci, jako například potvrzení smazání dat nebo jiných nevratných operací. Pokud tedy není potřeba okamžitého zásahu, je lepší zvolit toast notifikace, které neruší uživatele v jeho workflow.
V rámci optimalizace uživatelského zážitku v aplikaci je také nutné implementovat flexibilní navigaci. Side navigation (boční navigace) je efektivní způsob, jak uživatelům nabídnout rychlý přístup k různým částem aplikace, aniž by byli rušeni složitými menu. Na mobilních zařízeních může být boční navigace aktivována ikonou hamburger menu, na desktopu může být trvale viditelná. Je důležité, aby tento systém byl responsivní a přizpůsobivý různým velikostem obrazovek.
Další doporučený přístup při návrhu navigace je zobrazení pouze těch možností, ke kterým má uživatel přístup na základě jeho rolí a oprávnění. Tímto způsobem se zamezí zbytečnému zobrazení odkazů, které uživatel nemůže použít, což činí aplikaci přehlednější a intuitivnější.
Tímto způsobem můžeme zajistit, že nejen backend aplikace bude bezpečný a správně validovaný, ale i frontend bude intuitivní a uživatelsky přívětivý, což je klíčové pro úspěch aplikace.
Jak správně používat NgRx pro správu stavu v aplikacích Angular: Reducery, selektory a efektivní testování
Při práci s architekturou NgRx v Angularu je klíčovým prvkem správná implementace reducerů, selektorů a efektivní správa stavu aplikace. Využití těchto nástrojů umožňuje aplikacím být prediktivními a dobře strukturovanými, přičemž každá akce a její výsledek jsou jasně definovány. Tento přístup je obzvláště užitečný pro aplikace, které pracují s dynamickými daty, jako jsou například meteorologické služby. Při implementaci efektů (effects) a reducerů pro zpracování asynchronních dat je nezbytné zajistit, aby všechny změny stavu byly reaktivní, izolované a neměnné.
Základní operátor, který se často používá k řízení sekvenčního zpracování akcí v NgRx, je concatMap. Tento operátor umožňuje zpracovávat akce po sobě, což znamená, že akce a jejich odpovídající API volání jsou prováděny v pořadí. Pokud například máme akce a, b, c, d a e, API volání pro b nebude provedeno, dokud nebude akce a zpracována a její výsledek vykreslen na obrazovce. Tento přístup je užitečný, pokud potřebujeme zajistit, že každá akce je provedena až po dokončení té předchozí.
Na druhou stranu operátor switchMap okamžitě provádí API volání pro každou akci, ale pouze poslední z těchto akcí bude skutečně vyvolána. Tento přístup je vhodný pro případy, kdy je důležité mít pouze poslední zpracovaný výsledek. Uživatel pak uvidí pouze výsledek poslední akce. Z pohledu UX je tedy switchMap často správnou volbou, protože minimalizuje nároky na zbytečné API volání a udržuje uživatelský zážitek hladký a bez zbytečných zpoždění.
Při práci s NgRx je nezbytné mít dobře definované reducery pro manipulaci se stavem aplikace. Představme si například implementaci reduceru pro uložení aktuálních meteorologických dat do stavu aplikace. Pro tento účel je důležité mít v aplikaci specifikovanou strukturu stavu, který bude obsahovat informace o aktuálním počasí. Vytvoříme reducer, který bude reagovat na akci weatherLoaded a zpracuje data o počasí, která přijde jako součást této akce. Reducer bude vypadat následovně:
Tento reducer zaručuje, že všechny změny stavu jsou neměnné, a pokud dojde k přijetí nových dat, stávající stav je jednoduše upraven na základě nových informací. Díky tomuto přístupu se minimalizuje riziko nechtěných vedlejších efektů.
Pro efektivní práci s těmito daty je potřeba také definovat selektory, které nám umožní přístup k aktuálním datům ve stavu aplikace. Příklad selektoru pro aktuální počasí vypadá takto:
Tento selektor pak může být použit v komponentě, která bude sledovat změny stavu a reagovat na ně. V praxi to znamená, že komponenta bude odbírat stav z aplikace a automaticky se aktualizovat při každé změně stavu.
V případě, že aplikace interaguje s externími službami, jako je například služba pro získávání informací o počasí, je dobré implementovat službu, která bude komunikovat s API a na základě přijatých dat spustí příslušnou akci. Například ve komponentě CurrentWeatherComponent bychom mohli mít následující kód pro odběr dat a jejich zobrazení:
Tento přístup zajišťuje, že komponenta bude reagovat nejen na změny stavu, ale i na nové hodnoty, které mohou být přijaty ze služby.
Konečně, pro zajištění kvality a stability aplikace je nezbytné provádět jednotkové testy reducerů a selektorů. Pro testování reduceru weatherLoaded a selektoru selectCurrentWeather můžeme napsat následující testy:
Testování těchto částí kódu zajistí, že logika v aplikaci zůstane neměnná a stabilní, což je klíčové pro udržení prediktivního chování aplikace.
Ačkoli NgRx poskytuje silné nástroje pro správu stavu aplikace, je třeba zvážit, zda je implementace takového složitého systému nezbytná. V některých případech může být jednoduchý RESTful API přístup s manipulací dat na serveru dostatečný a náročnost implementace NgRx může být neefektivní. Při rozhodování o použití NgRx je tedy důležité zhodnotit složitost aplikace a požadavky na její správu stavu.
Jak efektivně nasadit aplikaci do produkce s pomocí CI/CD a GitHub flow?
Když vyvíjíme software, hlavním cílem je přinést hodnotu. Automatizací procesu dodání software vytváříme hodnotovou streamovou linku, která umožňuje spolehlivé a efektivní nasazení změn. Aby tento proces probíhal bez problémů, je nezbytné zavést několik nástrojů a postupů, které zajistí, že každý krok bude proveden správně a že případné chyby budou včas odhaleny. V tomto kontextu se podíváme na to, jak správně nastavit CI (Continuous Integration) a GitHub flow, abychom zajistili kvalitní výstupy při nasazení aplikace do produkce.
Nejprve se zaměříme na Cypress, nástroj pro end-to-end testování, který pomáhá provádět automatizované testy aplikace před jejím nasazením. V tomto příkladu se používá soubor cypress/e2e/app.cy.ts, který obsahuje jednoduchý test pro ověření, že na stránce je správně zobrazený titulek "LocalCast Weather". Tato metoda používá testovací ID, což znamená, že test bude fungovat i v případě, že se element na stránce změní. Takto napsané testy jsou spolehlivější a snadněji udržovatelné.
Pokud chceme zajistit, že naše testy budou pravidelně spouštěny, i když se kód mění, musíme implementovat nástroj pro kontinuální integraci (CI). CircleCI je jedním z nástrojů, který umožňuje jednoduché nastavení tohoto procesu. CircleCI zajišťuje, že každý commit provedený do repozitáře spustí automatizovaný build a testy, čímž pomáhá detekovat problémy ještě předtím, než se změny dostanou na produkční prostředí. Po registraci do CircleCI a přidání projektu můžete nastavit .circleci/config.yml soubor, který definuje všechny kroky od instalace závislostí až po spuštění testů a uložení výsledků.
Po nastavení CircleCI můžeme přejít k dalšímu kroku, kterým je GitHub flow. Tento pracovní postup zajišťuje, že každý nový vývoj bude probíhat v samostatné větvi, která bude následně podrobena kontroly a testování před tím, než bude sloučena do hlavní větve. GitHub flow se skládá z několika fází: vytvoření větve, provedení commitů, vytvoření pull requestu, diskuze a revize, nasazení a nakonec sloučení změn do hlavní větve. Tento postup zajišťuje, že na hlavní větev se dostanou pouze kvalitní a prověřené změny.
Důležité je, že GitHub umožňuje nastavit ochranu větve, což znamená, že nebude možné přímo commitovat do hlavní větve. Místo toho je nutné vytvořit novou větev, provést změny a otevřít pull request, který bude podroben automatizovaným kontrolám (včetně běhu testů na CircleCI). Jakmile budou všechny kontroly úspěšně dokončeny, můžeme sloučit změny do hlavní větve. Tento přístup nejen zajišťuje kvalitní kód, ale také umožňuje snadné vrácení změn v případě problémů.
V případě, že používáte GitHub a CircleCI, je nezbytné správně nastavit pravidla pro větve, zejména pro hlavní větev. To znamená, že musíme vyžadovat, aby všechny změny prošly pull requestem a byly schváleny alespoň jedním kolegou. Dále je třeba nastavit povinné kontroly, které musí být úspěšně dokončeny, než bude možné změny sloučit.
Tento přístup nám nejen pomůže zlepšit kvalitu kódu, ale také zjednoduší správu verzí a nasazení aplikace. Jakmile bude vše nastaveno, GitHub flow a CircleCI se postarají o to, že každý commit projde testy a kontrolami, čímž se výrazně sníží riziko nasazení chybného kódu do produkce.
Je však třeba si uvědomit, že nasazení do produkce není pouze o automatizaci testů a správě větví. Je to také o tom, jak se tým vyrovnává s případnými problémy, které se mohou objevit. Je důležité mít nastavený proces pro rollback změn, pokud něco selže, a mít mechanismy pro rychlou detekci a opravu chyb.

Deutsch
Francais
Nederlands
Svenska
Norsk
Dansk
Suomi
Espanol
Italiano
Portugues
Magyar
Polski
Cestina
Русский