Programowanie i WWW

„Coś poszło nie tak”, czyli obsługa błędów na kolanie

Błędy się zdarzają. Każdemu. I podczas gdy te dotyczące logiki biznesowej lub stabilności aplikacji możemy eliminować, tak tych związanych z interakcją użytkownika nie powinniśmy…

Błędy się zdarzają. Każdemu. I podczas gdy te dotyczące logiki biznesowej lub stabilności aplikacji możemy eliminować, tak tych związanych z interakcją użytkownika nie powinniśmy ignorować. Z jakiegoś powodu dzieje się jednak inaczej.

Ile razy zdarzyło Ci się stworzyć formularz, którego walidacja ograniczała się do komunikatu "coś poszło nie tak"? Bo mi wiele razy i nadal czasem się zdarza. W ostatnim czasie w końcu uświadomiłem sobie jak duży jest to błąd.

Wystarczy wejść na chwilę w buty użytkownika, który np. próbując dokonać zakupu otrzymuje wyżej wspomniany błąd. Jak myślisz, czy dokończy zakup? Być może. Ale szansa na to znacznie spada.

Co ciekawe taka sytuacja zdarzyła mi się nawet dzisiaj. I to w mojej aplikacji! Wtedy zacząłem zastanawiać się – DLACZEGO?!

Gdy spojrzymy na to z boku, wydaje się jasne że obsługa błędów powinna być naszym priorytetem. Odpowiednia informacja zwrotna dla użytkownika nie tylko zwiększa szansę na to, że ukończy realizowaną akcję. Unikniemy w ten sposób sytuacji w której ten użytkownik z niej zrezygnuje, zapamiętując negatywne doświadczenie związane z naszą aplikacją. Mało tego jesteśmy w stanie doprowadzić do momentu w którym obsługa błędów będzie tak dobra, że zamienimy to w naszą dobrą stronę.

We wspomnianym przypadku z dzisiaj głównym powodem jest fakt, że aplikacja nie jest jeszcze ukończona ale bardzo zależało mi na … czasie i tym aby sprawdzić ją w boju możliwie jak najszybciej, będąc świadomym ewentualnych konsekwencji. Ale to nie jedyny taki przypadek.

Warto tutaj pamiętać tylko jedno: brak informacji zwrotnej do użytkownika oznacza złe doświadczenia. To niweczy wysiłek wszystkich zaangażowanych w rozwój projektu.

"Nie mam czasu"

To jeden z głównych powodów niedopracowanych aplikacji posiadających obsługę błędów zrealizowaną po najniższej linii oporu. Mogłoby się wydawać że nie mamy na to wpływu ale w rzeczywistości jest tak tylko, gdy reagujemy za późno.

Przykładowo od chwili uświadomienia sobie tego problemu, moja biblioteka snippetów poszerza się o kod, który ułatwia mi np. tworzenie walidacji czy efektów wczytywania. Wszystko po to aby jak najbardziej ułatwić sobie wdrażanie obsługi błędów w przyszłości.

Drugą rzeczą, która już teraz mocno wpływa na moje podejście do obsługi błędów to ZROZUMIENIE tego jakie niesie to za sobą konsekwencje. Dzięki temu że stało się to dla mnie ważniejsze, automatycznie poświęcam więcej uwagi aby dopracować pod tym kątem moje API lub wizualne elementy interfejsu.

Ostatnia bardzo praktyczna rzecz to po prostu uwzględnianie w estymacji czasowej, przestrzeni na to aby dopracować aplikację również pod kątem walidacji, powiadomień, loaderów itd – czyli wszystkiego, co składa się na przekazywanie informacji zwrotnej do użytkownika. Co ciekawe można w tym uwzględnić również animacje, które również mogą sugerować użytkownikowi co się aktualnie dzieje i przy okazji wizualnie zwiększać atrakcyjność naszej aplikacji.

Czasem jest to trudniejsze niż się wydaje

Spotkałem się z sytuacjami w których wprowadzenie sensownej obsługi błędów było bardzo trudne albo wręcz niemożliwe (biorąc pod uwagę zasoby które miałem do dyspozycji).

Mowa głównie o przypadkach pracy z aplikacjami posiadającymi dużo "legacy" kodu, gdzie wprowadzenie odpowiedniej walidacji danych i obsługi błędów po prostu wiązałoby się z koniecznością przepisania dużej części wybranych modułów, co często nie wchodziło w grę.

Czasem też zdarzało mi się pracować z zewnętrznym API, które również nie przekazywało kompletu informacji niezbędnego do poprawnego obsłużenia każdego rodzaju błędów.

W takich momentach jesteśmy trochę podstawieni pod ścianą, natomiast nadal możemy kreatywnie podejść do takiego wyzwania, upewniając się że wystąpienie "nieoczekiwanego błędu" nie będzie wiązało się z frustracją (np. poprzez odpowiedni komunikat czy wspomniane wcześniej animacje wywołujące pozytywne emocje). Ostatecznie jeżeli wchodzi to w grę możemy ułatwić kontakt z pomocą techniczną, co również nie rzadko jest bardzo doceniane przez użytkowników.

Niech błędy krzyczą! Czyli kilka praktycznych wskazówek

Jeżeli programujesz w JavaScript, prawdopodobnie nierzadko sięgasz po console.log w instrukcji try .. catch lub IF'ach sprawdzających jakiś warunek, nie? Zapewne tak, ponieważ jest to spotykane na każdym kroku.

Problem w tym, że taka "obsługa" błędu niczemu nie służy, może poza etapem developmentu (ale w tym przypadku i tak sto razy lepiej jest sięgnąć po debugger).

Świetną taktyką na pracę z błędami na przykładzie JavaScriptu, jest to aby błędy "krzyczały". Mowa o wyrzucaniu wyjątków które zatrzymują program o ile nie zostaną odpowiednio przechwycone i obsłużone.

W takiej sytuacji niejako wymuszamy na sobie przechwycenie błędu ale nadal musimy zadbać o jego odpowiednie obsłużenie.

Kluczem do tego jest odpowiednie zorganizowanie naszego kodu polegającego na tym, aby błędy obsługiwać możliwie z jednego miejsca aplikacji (np. z pomocą dedykowanych helperów). Tak samo komunikaty o błędach raczej powinny być zapisane w formie stałych a nie być pisane "z palca" za każdym razem. (W przypadku obsługi wielu języków / tłumaczeń, jest to niejako wymuszone).

Przykłady takiej obsługi błędów najlepiej jest podejrzeć w open source'owych repozytoriach na githubie. Niestety z wielu względów jest to coś niemal całkowicie pomijanego zarówno w książkach jak i tutorialach czy nawet kursach programowania.

Jeżeli zadbasz o obsługę błędów na samym początku i zbudujesz prosty i elastyczny system, z czasem będzie Ci łatwiej. Mam na myśli: trzymanie się standardów w kontekście statusów odpowiedzi, dołączanych wiadomości zwrotnych z API, utworzenie rodzajów błędów (np. ApiError czy ValidationError) ze zrozumiałymi komunikatami.

Przekładając to na działanie:

  • korzystaj z "wyrzucania" wyjątków
  • obsługuj wyjątki w sposób spójny, najlepiej z jednego miejsca aplikacji
  • nie doprowadzaj do sytuacji w której jakiś błąd jest nieobsłużony
  • nie stosuj po informacje generyczne, np. "wystąpił błąd."
  • wykorzystuj wszelkie możliwe sposoby na przekazywanie interakcji zwrotnej do użytkownika. Niech będzie to czytelne, zrozumiałe i jeżeli to możliwe – przyjemne.

Ostatecznie biorąc na poważnie obsługę błędów podnosisz jakość tworzonej aplikacji oraz doświadczenia płynące z jej korzystania. To przekłada się na szereg korzyści biznesowych i bardzo dobrze świadczy o Tobie – programiście – ponieważ dbasz o szczegóły i detale. A dopracowane aplikacje są świetną wizytówką i materiałem do portfolio. Chyba już nie muszę pisać jakie korzyści z tego płyną również dla Ciebie.

Mam nadzieję że ten wpis zwrócił Twoją uwagę kwestię obsługi błędów i uświadomił lub zwiększył świadomość tego, jak istotny jest to temat.

Dzięki,
Adam

Lista linków z Newslettera:

UDOSTĘPNIJ ARTYKUŁ:

Powiązane artykuły

Programowanie i WWW

Proces rekrutacji w IT z różnych perspektyw

Podczas ostatnich konsultacji Full-Stack Dev Q&A padło kilka pytań o proces rekrutacyjny. Ze względu na pozytywny feedback oraz zwrócenie uwagi na istotę tego tematu, pomyślałem że zbiorę…

Programowanie i WWW

Umarł VSC, niech żyje InteliJ!

W ciągu ostatnich długich miesięcy miałem okazję zaangażować się w dwa większe projekty o skali zbliżonej do największych, jakie realizowałem w ciągu ostatnich 10 lat. Ponad 6…

Programowanie i WWW

Problemy z wydajnością to nie żart, nie?

Trudno dyskutować z tym, jak istotna jest kwestia wydajności w programowaniu. To często poruszany temat, mający wpływ na podejmowanie decyzji przy rozwoju oprogramowania oraz samym pisaniu kodu.…

Pozostań na bieżąco!

Już nigdy nie przegapisz ważnych informacji, promocji oraz nowych kursów. Zapisz się na newsletter już teraz!

Zapisując się do newslettera akceptujesz naszą politykę prywatności