Witaj Gościu! ( Zaloguj | Rejestruj )

Forum PHP.pl

> Używanie Exceptionów a typowanie
athabus
post
Post #1





Grupa: Zarejestrowani
Postów: 898
Pomógł: 48
Dołączył: 2.11.2005
Skąd: Poznań

Ostrzeżenie: (0%)
-----


Ostatnio ciekawi mnie temat używania Exceptionów - muszę przyznać, że trochę słabo to czuję. Kiedyś Exception stosowałem do rzeczy, które po prostu mogły spowodować niedziałanie aplikacji - np. brak dostępu do pliku czy coś podobnego. Ostatnio jednak widzę, że coraz częściej w nowych bibliotekach Exceptiony stosuje się w inny sposób tj. do wymuszenia typowania metody bez zwracania NULL.

Np taka klasa:

  1. <?php
  2.  
  3. class MySampleRepository
  4. {
  5. public function getItemV1(int $id): SomeObject
  6. {
  7. //pobieramy item, który może nie istnieć (null)
  8. $item = $this->fetch($id);
  9.  
  10. if (!$item) {
  11. throw new ItemNotFoundException('Item does not exist');
  12. }
  13.  
  14. return $item;
  15. }
  16.  
  17. public function getItemV2(int $id): ?SomeObject
  18. {
  19. //pobieramy item, który może nie istnieć (null)
  20. $item = $this->fetch($id);
  21.  
  22. return $item;
  23. }
  24. }


Pierwsza metoda (podejście o którym mówię) nigdy nie zwraca nulla, tylko obiekt lub rzuca wyjątek. Druga metoda (tradycyjna) zwraca obiekt lub null.

Które podejście stosujecie? Dlaczego.

Ja po rozmowie z kolegą zacząłem skłaniać się ku pierwszej wersji i brak możliwości zwrócenia oczekiwanego obiektu traktuję jako wyjątek.Podświadomie wydaje mi się to bardziej logiczne i wymusza trochę więcej dyscypliny.
Go to the top of the page
+Quote Post
 
Start new topic
Odpowiedzi
athabus
post
Post #2





Grupa: Zarejestrowani
Postów: 898
Pomógł: 48
Dołączył: 2.11.2005
Skąd: Poznań

Ostrzeżenie: (0%)
-----


Haha nie rozawżajmy przypadków skrajnych jak ten z początku posta ;-)

Przykład z repozytorium jest dosyć ciekawym casem. Czy jeśli odpytuję bazę czegoś (np. produktów) po ID/SKU to nie zakładam, że to coś istnieje? Przecież takiego SKU nie wygenerowałem losowo. Poprawnie logicznie w takiej sytuacji faktycznie byłoby najpierw sprawdzić czy coś istnieje a potem dopiero to pobrać, ale z wiadomych względów nie zawsze jest to dobre rozwiązanie (np. jeśli to obiekt w bazie to wykonujemy 2 zapytania zamiast 1)

Weźmy też na tapet inny przykład - PSR-6, czyli interfejs dla cache. Tam właśnie chyba powstał problem co ma zwracać metoda $cache->getItem($key). Co ciekawe ta metoda nie posługuje się ani wyjątkiem, ani null, tylko null object pattern. Zawsze zwracany jest taki sam obiekt CacheItem, który w interfejsie ma metodą isHit() umożliwiającą sprawdzenie, czy jest pusty czy nie. Pośrednio jest to coś o czym piszesz, ale to jednak zupełnie co innego niż zwrócenie null.

Dla mnie osobiście null object pattern nie przemawia - rozumiem, że jego zaletą jest możliwość polimofricznego traktowania każdego rezultatu, ale w sumie tak czy siak jest to taki jakby slow failing, bo przed klientem ukrywa nulla.

Taki jeszcze jeden aspekt przemawiający za wyjątkami to właśnie failing fast. Zwracając null (czy null object), możemy doprowadzić w większym kodzie do dość niespodziewanych zachowań. Przykładowo załóżmy, że z jakichś powodów metoda pobiera 3 obiekty po id (np. $repository->getBestsellerInCategory($categoryId)) i zapisuje je do jakiejś tablicy. Ta tablica potem wędruje sobie po systemie i 30 funkcji dalej dostajemy errora "trying using null as a object". Takie sytuacje bywają dosyć trudne do debugowania. Ja na przykład pracuje na Magento, gdzie przy mocno customizowanych sklepach pod niektóre metod wpina się wiele pluginów/obserwatorów i potem znalezienie takiego błędu trochę trwa.

Użycia Exceptiona zmusza klienta kodu do jawnego obsłużenia takiej sytuacji. Przy dużej bazie kodowej trzeba więcej na kliencie wymuszać.

Tutaj ciekawy artykuł w temacie: https://www.yegor256.com/2014/05/13/why-null-is-bad.html

PS. oczywiście zgadam się z tym, że nie ma jednej uniwersalnej zasady. Mamy wiele możliwości do wyboru (null, exception, wartość domyślna, null object itp). Z drugiej strony staram się ostatnio coraz częściej myśleć gdy używam pewnych rzeczy - np. staram się unikać wartości domyślnych w funkcjach czy na przykład dziedziczenia gdy tylko mogę. Ostatnio do listy dodałem function(): ?someObject.

Ten post edytował athabus 1.01.2019, 13:31:34
Go to the top of the page
+Quote Post

Posty w temacie


Reply to this topicStart new topic
2 Użytkowników czyta ten temat (2 Gości i 0 Anonimowych użytkowników)
0 Zarejestrowanych:

 



RSS Aktualny czas: 14.10.2025 - 02:21