WP Desk Care - zadbaj o swój biznes online!

Sprawdzona opieka techniczna dla Twojego sklepu

Używaj wyjątków – sugestie po przeprowadzeniu kilkuset code review

W WP Desk przywiązujemy ogromną uwagę do tego, by wszystko, co robimy, było naprawdę świetnej jakości. Gwarancją sukcesu jest zastosowanie najlepszych z możliwych rozwiązań, dlatego na porządku dziennym jest u nas praktyka Code Review. Niektóre uwagi pojawiające się na review, wracają wyjątkowo często.

Wszystkie gałęzie przed scaleniem (ang. merging) muszą w WP Desk przejść obowiązkowe Code Review, czyli sprawdzenie kodu bądź jego fragmentu przez innego członka zespołu. Dzięki review wymiana wiedzy pomiędzy developerami jest wyraźnie szybsza, znacznie lepiej panujemy nad długiem technologicznym, wystarcza mniejsza liczba spotkań i, przede wszystkim, pojawia się mniej bugów. Jeden z tematów najczęściej pojawiających się na review to temat wyjątków. Problem jest też widoczny podczas rozmów rekrutacyjnych. Programiści WordPress bardzo często nie są przyzwyczajeni, nie widzą zalet i nie wiedzą, jak poprawnie używać tego mechanizmu.

Studium przypadku

Przyjmijmy, że chcemy wykonać trywialne pod WordPressem zadanie: pokazać tytuł posta. Oto prosty kod realizujący to zadanie:

Na pierwszy rzut oka kod wygląda nieźle. Małe funkcje, proste, ale jednoznaczne nazwy, dobrze zastosowana reguła SRP (Single Responsibility Principle). Co jednak poszło nie tak i z czego wynika Fatal Error po jego wykonaniu?

Przede wszystkim już pierwsza linia tego kodu wprowadza nas w błąd. Informacja, że funkcja get_wpdesk_post zawsze zwróci obiekt klasy WP_Post jest nieprawdziwa. To bardzo częsta sytuacja w kodzie WordPress, ponieważ większość funkcji WP w przypadku jakichkolwiek problemów rzuca w nas nullem. Funkcja get_wpdesk_post też w przypadku, gdy nie może znaleźć posta o zadanym identyfikatorze, nie może zwrócić wartości zgodnej z zadeklarowanym typem i zwraca null. Wezmę teraz pod uwagę ten kluczowy detal i spróbuję dostosować kod:

Teraz kod wykona się poprawnie, ale biorąc pod uwagę, jak trywialne zadanie stało przed programistą, to nie wygląda już zbyt ładnie. Funkcje zwracają różne typy danych w zależności od warunków. Gdyby zadanie było trudniejsze, sytuacja byłaby gorsza. Null, który pojawił się przy po użyciu get_wpdesk_post zaczął propagować się w dół drzewa wykonań funkcji i każda z funkcji musi sprawdzić, czy przypadkiem nie otrzymała nulla. Jeśli chociaż w jednym przypadku sprawdzanie zostanie przez przypadek pominięte, użytkownik zobaczy Fatal Error lub Warning. Jeśli funkcja get_wpdesk_post została użyta jeszcze w jakimś innym miejscu w kodzie, tam sytuacja ponownie się powtórzy i konieczna będzie kolejna kaskada warunków if null. Co za bałagan!

Ale o co chodzi, przecież działa

Główną wadę zastosowanego rozwiązania można podsumować jednym zdaniem:

Każde użycie funkcji, która zwraca więcej niż jeden typ danych, zmusza nas każdorazowo do obsługi każdego z tych typów danych.

Zwracanie null jest wyjątkowo paskudne, ale to zdanie jest prawdziwe także w przypadku innych stosowanych w takiej sytuacji rozwiązań:

  • Zwracanie \WP_Error z funkcji.
  • Własna klasa, która w praktyce jest jakimś odpowiednikiem \WP_Error.
  • Zwracanie kodu błędu.
  • String z komunikatem błędu zamiast danych.
  • Zwracanie pustego stringa – w przypadku gdy funkcja standardowo zwracała inny niż string typ danych.

Dlatego null jest najgorszym z wymienionych rozwiązań? Programiście używającego funkcji wcale nie jest tak łatwo odtworzyć, z jakiej przyczyny funkcja zwróciła null. Powodów może być wiele: problem z połączeniem z bazą, post nie istnieje, post nie spełnia jakiegoś warunku etc. Wiele potencjalnych powodów, a na wszystkie tylko jedna odpowiedź: null. To powoduje, że taka konstrukcja pozbawia programistę możliwości poprawnego zareagowania na sytuację wyjątkową.

Jeśli masz problem i do jego rozwiązania użyjesz nulla, to teraz masz dwa problemy.

Wyjątki na ratunek

Rozwiążmy teraz ten problem przy użyciu wyjątków. Gdy funkcja get_wpdesk_post nie może zwrócić danych o zadeklarowanym typie, ponieważ z różnych przyczyn nie ma to sensu, rzuca (ang. throw) odpowiedni wyjątek.

Od razu lepiej. Kod znów wygląda ładnie, funkcje zwracają jeden jednoznaczny typ danych, a problem z brakiem posta został elegancko rozwiązany. Dodatkowo, dzięki takiemu rozwiązaniu, autor funkcji get_wpdesk_post nie zadecydował za nas kiedy wystąpi obsługa błędu. Każda z funkcji w drzewie wywołań może, ale nie musi obsłużyć wyjątek spowodowany przez get_wpdesk_post. Możemy ten wyjątek złapać bardzo wcześnie, już na etapie get_wpdesk_post_title, ale możemy też pozwolić nadal mu się propagować. Na przykład do momentu, gdy zostanie przechwycony przez klasę logującą błędy.

Dobrym pomysłem jest tagowanie wyjątków w ramach jednego rozwiązania za pomocą spójnych interfejsów. Na przykład w ten sposób:

Dzięki temu możemy w jednym miejscu przechwycić całe grupy wyjątków i odpowiednio je obsłużyć.

Dobrym usprawnieniem jest też stosowanie statycznego konstruktora do tworzenia predefiniowanych błędów:

Mam nadzieję, że artykuł trochę nakreślił, jak działamy w WP Desk. Dajcie znać w komentarzach, czy chcecie wiedzieć jeszcze więcej o naszych praktykach pracy! :)

Zobacz inne artykuły

Dołącz do ponad 10 000 czytelników

Poradniki WooCommerce i nowości –
wprost na Twój e-mail.