Najważniejsze zagadnienia, które musisz znać
5 godz. 53 min · JavaScript · Full-stack i Programowanie
Adam GospodarczykPrzesyłanie oraz transformacja danych to jeden z najważniejszych elementów działania każdej aplikacji. Dobre zrozumienie tego w jaki sposób odbywa się ten proces, daje równocześnie lepsze zrozumienie całej struktury oraz podejmowania decyzji projektowych. W tym kursie znajdziesz lekcje, które pozwolą Ci uporządkować wiedzę na temat protokołu HTTP oraz formatów wymiany danych.
REST oraz GraphQL to nadal nieodłączone zagadnienia tematu wymiany informacji w kontekście aplikacji webowych. Pomimo tego, że ich koncepcje zwykle są bardzo dobrze opisane w różnych źródłach, tak ich wykorzystanie "na produkcji" potrafi sprawić problemy. W szczególności gdy weźmiemy pod uwagę, wyjątki oraz fakt, że nie każda aplikacja będzie wymagać implementacji REST czy GraphQL w 100%. W tym kursie znajdziesz wiele praktycznych wskazówek związanych z pracą z REST API oraz wprowadzenie do pracy z GraphQL.
Niektóre błędy w aplikacji są bardzo pożądane, w szczególności gdy jasno informują użytkownika o tym, co się wydarzyło oraz o tym, co może z tym zrobić. Pomimo tego, że w wielu przypadkach opracowanie komunikatów leży w rękach osoby odpowiedzialnej za copywriting (i/lub ux writing), tak sama implementacja tych komunikatów odbywa się po stronie kodu. Nie rzadko okazuje się, że poprawna i skuteczna walidacja danych oraz obsługa błędów nie jest oczywista w "produkcyjnych" sytuacjach. W tym kursie znajdziesz najczęściej spotykane problemy oraz sposoby ich rozwiązania.
Bazy danych są praktycznie nieodłączną częścią każdej aplikacji. W roli full-stacka prędzej czy później przyjdzie Ci z nimi pracować a nie rzadko nawet projektować oraz rozbudowywać ich struktury. W tym kursie znajdziesz informacje o bazach danych, które pozwolą Ci je zrozumieć oraz od razu poznać użyteczne techniki, które pomogą Ci w pracy z nimi, zarówno na produkcji jak i w środowisku lokalnym czy testowym.
Nie wszystkie informacje w aplikacji są publiczne. Niektóre wprost nie mogą takie być. Z tego powodu niezbędne są sposoby na to aby poznać a potem weryfikować tożsamość użytkownika, by na jej podstawie przydzielać mu dostęp wyłącznie do zasobów, do których odczytywania posiada uprawnienia. Istnieje wiele technik, które umożliwiają zarządzanie dostępem do danych i w tym kursie poznasz najważniejsze z nich. Dowiesz się nie tylko w jaki sposób zabezpieczać dane ale poznasz też najpopularniejsze sposoby na to aby te zabezpieczenia łamać i obchodzić. Mając świadomość takiej możliwości, będziesz w stanie lepiej podejmować decyzje o tym jak projektować dostęp do informacji.
Istnieją problemy charakterystyczne dla niemal każdej aplikacji. W związku z ich powszechnością, istnieje też szereg rozwiązań lub sposobów na to, aby możliwie zredukować ich następstwa. Na przestrzeni lekcji tego kursu zobaczysz wiele przykładów, które pomogą Ci w codziennej pracy a niekiedy nawet, pozwolą uniknąć błędów, których konsekwencje nie zawsze występują natychmiast.
Kurs powstał z myślą o osobach, które chcą rozwijać się w roli full-stack web developera / developerki, przeprowadzając przez najważniejsze zagadnienia z obszaru wymiany, transformacji oraz przechowywania informacji w aplikacji oraz pomiędzy aplikacjami. Jeżeli potrzebujesz zobaczyć szeroką perspektywę tego, w jaki sposób dane przepływają pomiędzy różnymi częściami aplikacji, lub ugruntować swoją wiedzę na ten temat, to ten kurs jest miejscem, którego szukasz.
Sama komunikacja to nie tylko te elementy,
o których powiedzieliśmy sobie na przestrzeni.
Poprzednich lekcji, ale też różnego
rodzaju problemy bądź wątki, na które warto zwrócić uwagę.
Tutaj nie są wcale oczywiste.
Chciałbym więc tutaj w tym materiale na
dość ogólnym poziomie poruszyć te, które uznaję za najważniejsze.
Pierwszym z nich jest walidacja danych.
I tutaj, pomimo tego, że już zdarzyło mi
się o tym wspomnieć, tak, chciałbym podkreślić, że walidacja w przypadku
takowych aplikacji odbywa się na kilku poziomach.
Po pierwsze mamy walidację po stronie frontendu, która jest o tyle istotna, że w
wielu przypadkach może wydarzyć się bez konieczności kontaktowania z backend.
W rezultacie użytkownik natychmiast może dowiedzieć się, że np.
format jego adresu email nie jest poprawny.
Z drugiej strony w niektórych sytuacjach może zaistnieć potrzeba, aby skontaktować
się z backendu i również wyświetlić tą informację.
Użytkownikowi, pomimo tego. Że np.
formularz, który w danej chwili uzupełnia nie został jeszcze wysłany.
Jest to całkiem dobra praktyka, aby informować użytkownika na bieżąco o
ewentualnych błędach, zamiast czekać do momentu, w którym wyśle formularze.
Drugim etapem walidacji jest backend.
Jest to o tyle istotne, że to właśnie tutaj powinna odbywać się faktyczna
walidacja tego, czy wprowadzane dane są poprawne.
Na tym etapie pamiętaj, aby nie ufać żadnym informacjom, które pochodzą ze
strony frontendu, ponieważ mogą zdarzyć się nawet takie przypadki, w których te
informacje nie będą pochodziły od użytkownika, tylko od różnego rodzaju
botów, które będą próbowały atakować Twoją aplikację.
Coś takiego zdarza się nawet w przypadku małych.
Projektów, gdy po.
Prostu mamy pecha.
Jednocześnie też nawet w momencie, gdy użytkownik nie ma żadnych złych.
Intencji, może się po prostu pomylić.
I przypadkowo przesłać nam jakieś informacje, które nie powinny trafić do
naszej aplikacji, a już tym bardziej zostać w niej zapisane.
Przykładem może być iCloud plików, w
przypadku którego użytkownik może wybrać nie ten, który chciał i w rezultacie np.
bez naszej aplikacji zamiast pliku
graficznego trafi jakiś plik wykonywalny, który może po prostu być źle
zinterpretowany i ostatnią fazą walidacji danych jest sama baza danych.
Czyli nawet w momencie, gdy nasz backend
uzna, że dane przesłane przez użytkownika są poprawne i można je zapisać, to i tak
na koniec dnia to baza danych weryfikuje to, czy faktycznie może to zrobić.
W niektórych sytuacjach dochodzi do błędów typów, które.
Również musimy odpowiednio obsłużyć.
No i tutaj mamy przykład dokumentacji
narzędzia Object Rejestr, z którego ja osobiście korzystam w wielu aplikacjach
produkcyjnych i w przypadku którego mamy bardzo obszerny interface do tego, aby
radzić sobie z błędami i konkretnymi komunikatami.
Zwróć uwagę, że te błędy mogą dotyczyć różnych wątków.
Może to być niepoprawna struktura danych zawierająca np.
niewłaściwe typy, które zdefiniowaliśmy w bazie, bądź też np.
błąd relacji oznaczający np.
to, że nie można utworzyć połączenia pomiędzy tabelami.
O tym, co to dokładnie oznacza, będziemy sobie jeszcze mówić.
I ponownie też na samym końcu mogą wystąpić błędy, które nie są w jakiś
sposób zdefiniowane, więc traktujemy je jako nieznane, ale jednocześnie w takiej
sytuacji warto przynajmniej posiadać jakiś.
System logów, który będzie.
Nam w stanie wskazać, co dokładnie się tam wydarzyło.
W momencie, gdy użytkownik zwróci się chociażby do supportu z prośbą o pomoc.
W takiej sytuacji możemy zajrzeć w logi i
dokładnie prześledzić co dokładnie się wydarzyło.
I teraz jeżeli pójdziemy dalej, to zwróć uwagę, że tych błędów jest naprawdę bardzo
dużo, w tym również takich, które mogą dotyczyć serwera, ponieważ np.
z jakiegoś powodu baza danych może być całkowicie nieosiągalna.
Na koniec dnia oczywiście w Twoim
przypadku nie musi być konieczne obsługiwanie wszystkich błędów, które
zostały tutaj wymienione, ponieważ jest to przykład z.
Dokumentacji, tylko.
Bardziej warto się zastanowić jakie błędy chcesz.
Obsługiwać i w. Przypadku których komunikaty chcesz
rozróżniać i też wskazywać użytkownikowi, co ewentualnie może z tym zrobić.
Na koniec dnia chodzi w tym wszystkim o
to, aby po prostu pamiętać o tym, że walidacja powinna zostać obsłużona zarówno
po stronie frontendu backendu, jak i bazy danych.
Jeżeli chodzi o to, jak to zrobić w
praktyce, o tym oczywiście będziemy sobie jeszcze rozmawiać.
Na koniec dnia liczy się też informacja zwrotna.
I tutaj chodzi o nic innego jak po prostu
poinformowanie użytkownika o tym, co dokładnie poszło nie tak.
Czyli przykładowo jeżeli użytkownik
podając hasło nie dopełni jakiś standardów, które wymagamy.
Co do samej siły tego hasła,
to zamiast informować go o tym, że hasło jest niepoprawne bądź niezgodne z
wymaganiami, to warto też wskazać co dokładnie poszło tam nie tak.
No i ostatecznie wspomniane logi również mogą okazać się przydatne dla nas, bądź
też ewentualnie dla działu obsługi klienta.
Kolejnym wątkiem. Które trzeba zaznaczyć raz jeszcze.
Jest obsługa błędów.
I tutaj nie mówię tylko o.
Błędach dotyczących walidacji, ale również
o błędach serwera, błędach wynikających z połączeniem.
Bądź też błędach samej aplikacji.
Lub też takich wynikających z architektury i na przykład tego, że serwer może.
Tymczasowo nie działać.
W takiej sytuacji należy zadbać o.
Odpowiedni format błędów i tutaj również nie.
Tylko o tym, w jaki sposób zostają one
zwracane przez API, ale również w jaki sposób zostają wyświetlane użytkownikowi,
co może z nimi zrobić, jak dokładne informacje zawierają oraz czy są
gdziekolwiek zalogowane oraz czy dostajesz informację o tym, że te błędy występują.
Oczywiście alerty zwykle dotyczą tych najbardziej krytycznych błędów, ale
jednocześnie nic nie stoi na przeszkodzie, aby skonfigurować je również na wypadek
często powtarzających się błędów, które mogą umykać Twojej uwadze.
I tutaj nie wiem, czy korzystasz z
podobnych usług, natomiast istnieją serwisy takie jak chociażby Uptime Robot,
w ramach których jesteś w stanie nie tylko informować siebie, ale również
użytkowników Twojej aplikacji bądź Twojego API o aktualnym statusie Twoich usług.
Niejednokrotnie może zdarzyć się tak, że
będziesz potrzebować wyłączyć na jakiś czas swoje usługi, aby np.
dokonać migracji serwera.
W takiej sytuacji warto przede wszystkim
poinformować użytkowników o tym fakcie oraz ewentualnie przeprowadzić samą
migrację w czasie, gdy tych użytkowników jest najmniej.
Jednocześnie też bardzo pomocne bywają
takie strony statusu, gdzie można obserwować to, czy np.
podczas pracy z udostępnionym przez Ciebie
API występujące błędy mają źródła po naszej stronie, czy też po Twojej.
Podobnie też jeżeli chodzi o błędy, to po raz kolejny zachęcam do tego, aby
podglądać sobie popularne API, aby dowiedzieć się
w jaki sposób ustrukturyzowane są odpowiedzi zawierające błędy.
I chociażby tak jak w tym przypadku, jakie
statusy błędów są wykorzystywane oraz w jakich sytuacjach do nich dochodzi.
W przypadku Snapa akurat chciałbym się
tutaj nieco bardziej zatrzymać, ponieważ jak być może wiesz, zdarza mi się z nim
pracować, a jednocześnie też zawierać szczegóły, które warto naśladować.
Przykładowo, jeżeli w aplikacji podamy klucz API dla sandboxa, to będziemy
chcieli wykonać akcję na serwerze produkcyjnym.
To Snap jest na tyle sprytny, że jest w stanie nas poinformować o tym, że
połączenie nie zostało poprawnie nawiązane, ponieważ klucz API nie został
dopasowany do naszego konta, ale jednocześnie ten sam klucz API istnieje w
środowisku testowym i prawdopodobnie pomyliliśmy się w konfiguracji aplikacji.
Coś takiego naprawdę robi wrażenie i zapewnia dobry developer experience oraz
też świetne doświadczenia użytkowników końcowych tej aplikacji.
Kolejnym wątkiem, z którym być może będzie spotykać się jako full stack lub też
przynajmniej będziesz adresować go w minimalnym stopniu jest tzw.
offline mode.
Tutaj sytuacja jest o tyle ciekawa, że
warto poczytać sobie o aplikacjach budowanych w myśl zasady offline first.
Oczywiście w przypadku webowych nie zawsze coś takiego w ogóle jest wymagane, ale
jednocześnie nawet poinformowanie użytkownika o tym, że jego połączenie z
internetem zostało zerwane bywa całkiem pomocne.
Jednocześnie też tutaj możesz wykorzystać pamięć lokalną np.
przeglądarki do tego, aby przechowywać
informacje, które nie zawsze muszą być za każdym razem pobierane z serwera.
Oczywiście tutaj musisz zadbać jeszcze o ewentualne konflikty i synchronizacje np.
w momencie gdy aplikacja ponownie nawiąże połączenie z naszym serwerem, ale to już
jest wątek, o której będziesz martwić się w momencie, gdy spotkasz taki problem.
Jednocześnie też pamiętaj proszę o tym, że
niektóre informacje po prostu nie powinny zostać przechowywane po stronie klienta i
być dostępne wyłącznie wtedy, gdy połączenie jest nawiązane.
Mowa tutaj chociażby o informacjach wrażliwych.
No i teraz skoro wspomniałem już o spójności danych, to tutaj pamiętaj o tym,
że ten wątek dotyczy nie tylko sytuacji, w której tracimy połączenie z naszą
aplikacją, ale również w bardzo klasycznej sytuacji polegającej na tym, że użytkownik
wykonuje jakieś akcje modyfikujące informacje po stronie frontendu, a potem,
jeżeli nie zadbamy o to, aby to backend był naszym jedynym źródłem,
to może dojść do sytuacji, że dane zostaną niepoprawnie zapisane i np.
gdy użytkownik będzie wracać do naszej
aplikacji, otrzyma zupełnie inny efekt niż byśmy się tego spodziewali.
Coś takiego nawet dzisiaj doświadczyłem w
momencie, gdy korzystałem z aplikacji Head Liner.
Z pomocą tutaj można generować tak zwane audio gramy.
Rezultat końcowy jest taki, że w wyniku
braku spójności pomiędzy frontend i backend, pomimo tego, że skonfigurowałem
wygląd generowanego wideo po stronie dostępnej aplikacji, tak już przy
wygenerowanym wideo otrzymałem nieco inny rezultat, który doprowadził do sytuacji, w
której musiałem przygotować projekt od samego początku.
W temacie spójności danych zaznaczyłem
jeszcze temat typów, ponieważ to również w pewnych momentach jest sposób na to, aby
sobie poradzić z tą ewentualną nie spójnością.
Kolejnym wątkiem jest bezpieczeństwo i to również poruszałem już niejednokrotnie.
Natomiast mam tutaj na myśli ponownie
bezpieczeństwo typów i upewnienie się tego, czy zapisywane dane spełniają
odpowiednie ograniczenia oraz też czy są odpowiednio zaszyfrowane.
O tym będziemy sobie jeszcze mówić, ale informacje takie jak np.
hasła po stronie Twojej aplikacji powinny być zaszyfrowane w taki sposób,
aby były niemożliwe do odczytania również dla twórców aplikacji, czyli dla nas.
Takie jednostronne szyfrowanie.
Większości przypadków środowisko notebook odbywa się za pomocą bitmap.
Natomiast w praktyce istnieje jeszcze
kilka narzędzi, z których można skorzystać.
Tym bardziej, że w niektórych sytuacjach może być potrzebne tylko jednostronne
szyfrowanie, czyli takie, której jesteśmy w stanie odwrócić.
W przypadku BIG
zwykle stosujemy to jednostronne szyfrowanie, czyli w momencie, gdy
zapisujemy hasło po prostu do naszej bazy trafia jego zaszyfrowana forma, a potem w
momencie, gdy użytkownik loguje się i raz jeszcze podaje swoje hasło, po prostu
szyfruje przekazaną przez niego wartość, a następnie porównujemy hasła.
O detalach dotyczących szyfrowania
będziemy sobie jeszcze mówić i wykonywać to w praktyce.
Natomiast pamiętaj też o tym, że
bezpieczeństwa dotyczy również kluczy oraz ewentualnej kontroli dostępu.
W niektórych sytuacjach może zdarzyć się tak, że użytkownik np.
upublicznił przypadkowo swój klucz, bądź też przekaże go osobie, która już nie
powinna mieć dostępu do danej aplikacji i wtedy konieczna będzie jego zmiana.
Dobrze jest upewnić się, że Twoja aplikacja daje taką możliwość.
No i na samym końcu na liście problemów związanych z komunikacją naszej aplikacji
czy też w ogóle jej funkcjonowaniem jest naturalnie skala.
I tutaj co ciekawe, w większości
przypadków problemy bardzo dużej skali raczej nas nie dotyczą, ponieważ większość
firm rozwijają raczej aplikacje działające na małej bądź średniej skali, ale
jednocześnie istnieje szereg problemów, które mogą wygenerować problemy z
wydajnością nawet na stosunkowo małej skali i nawet w środowisku developerskim.
Przykładem takich błędów może być np.
nie dodanie indeksu do bazy danych, bądź też tzw.
problem n+1, które można łatwo spotkać w momencie zagnieżdżonych pętli.
Poza tymi prostymi problemami może również dojść do sytuacji, w której konieczne
będzie kasowanie danych, czyli wykorzystanie pamięci podręcznej.
I to również można zaadresować na wiele różnych sposobów, o czym wspominałem przy
okazji wyjaśniania schematu komunikacji w aplikacji webowej.
No i ostatecznie temat skali może
rozwiązać nam zaawansowana architektura, wliczając w to architekturę mikro serwisów
czy też wykorzystanie skalowania poprzez architekturę serwerów.
Ostatecznie jednak jeden i drugi temat
jest na tyle zaawansowany, że nie będziemy poruszać go szczegółowo w tym kursie.
Teraz mam nadzieję, że Twoja świadomość ewentualnych błędów, które może spotkać
jest nieco większa i jednocześnie też, że ten kontekst tutaj to już nie działanie
wyłącznie na froncie bądź wyłącznie na backend do pełnego obrazu aplikacji i
przepływu aplikacji pomiędzy jej różnymi obszarami.
Te wszystkie wątki będą pojawiać się jeszcze w kolejnych lekcjach.
W związku z tym po raz kolejny zaznaczam, że jeżeli coś nie jest jasne, to powinno
się tak stać na przestrzeni kolejnych lekcji.
Teraz dziękuję Ci za uwagę i do usłyszenia w kolejnych filmach.