• Najnowsze pytania
  • Bez odpowiedzi
  • Zadaj pytanie
  • Kategorie
  • Tagi
  • Zdobyte punkty
  • Ekipa ninja
  • IRC
  • FAQ
  • Regulamin
  • Książki warte uwagi

Optymalna obsługa wyjątków

Object Storage Arubacloud
0 głosów
305 wizyt
pytanie zadane 25 lutego 2017 w PHP przez Benek Szeryf (91,010 p.)

Załóżmy, że mamy klasę File. Klasa ta posiada konstruktor, nadający obiektowi nazwę zgodną z nazwą pliku. Konstruktor wywołuje także prywatną metodę, sprawdzającą czy plik da się obsłużyć:

    public function __construct($str)
    {
        $this->filename = $str;
        $this->readable();
    }

    private function readable()
    {
        if (!$this->ptr = @fopen($this->filename, 'r')) {
            throw new Exception("Cannot read " . $this->filename . " file");
        }
    }

I w kontrolerze mamy osadzony kod:

try {
    $fileobj = new File("filename.txt");
} catch (Exception $e) {
    $error = $e->getMessage();
    ...
}

Gdy nie ma pliku w podanej lokalizacji lub prawa dostępu nie pozwalają na jego otwarcie, to w obu przypadkach dochodzi do zrzucenia wyjątku. Załóżmy, że chciałbym obsłużyć obie te sytuacje niezależnie. Jak to zrobić?

Sposób 1:

if (plik nie istnieje) {
    throw new Exception("Brak pliku");
} else if (nie udalo sie otworzyc pliku) {
    throw new Exception("Plik odmawia dostepu")
}

Sposób 2:

if (plik nie istnieje) {
    throw new NoFileException("Brak pliku");
} else if (nie udalo sie otworzyc pliku) {
    throw new NoAccessException("Plik odmawia dostepu")
}

class NoFileException extends Exception
{
    ...
}

class NoAccessException extends Exception
{
    ...
}

Wiem, że można tworzyć klasy swoich wyjątków, nie wiem jednak co miałoby w nich być umieszczone, wszak wszystko da radę obsłużyć, drukując odpowiedni komunikat wyjątku. Jaka jest więc korzyść w definiowania własnych wyjątków?

Sposób 3:

Ten sposób opisywał Comandeer. Tylko że opis na stronie PHP jest dla mnie zbyt lakoniczny i nie mogę dopasować żadnego z predefiniowanych wyjątków do swoich potrzeb.

Pytanie jest więc jak to zrobić poprawnie? Nie rozumiem też dlaczego zrzuca się kod błędu. Używając kodu, który jest na samej górze wiadomości, zawsze otrzymuję wartość 0, niezależnie czy pliku nie ma w podanej lokalizacji, czy skrypt nie ma uprawnień do jego otwarcia. Wiem, że kod błędu podaje się jako drugi parametr, ja nie podałem, stąd 0. Ale czy nie powinno być tak, że wyjątek zrzuca wbudowany kod błędu? Skoro skrypt został przerwany, to pewnie wie z jakiego powodu. Zresztą jeśliby usunąć @ przy fopen() to są drukowane pewne informacje.

1 odpowiedź

+1 głos
odpowiedź 25 lutego 2017 przez CzikaCarry Szeryf (75,340 p.)

Myślę, że pierwszy sposób jest najbardziej przejrzysty i klarowny, ponieważ jeśli rzucisz wyjątek w taki sposób:

function foo()
{
 if (plik nie istnieje) {
     throw new NoFileException("Brak pliku");
 } else if (nie udalo sie otworzyc pliku) {
     throw new NoAccessException("Plik odmawia dostepu")
 }
}

To musisz obsłużyć wyjątki w taki sposób:

try
{
$obj->foo();
catch(NoFileException $e) {echo $e->getMessage();}
catch(NoAccessException $e) {echo $e->getMessage();}
}

2 typy wyjątków to jeszcze nic, gorzej, jak będziesz musiał obsłużyć 10 typów

Sposób 2 jest dłuższy od sposobu 1, ponieważ w sposobie 1 wszystkie wyjątki są typu exception:

try { $obj->foo(); catch(Exception $e) {echo $e->getMessage();} }

 

 

1
komentarz 25 lutego 2017 przez mbabane Szeryf (79,280 p.)
edycja 25 lutego 2017 przez mbabane

2 sposob bedzie chyba czytelniejszy dla programisty, zauwaz ze jesli bedzie 10 tych wyjatkow nie bedzie trzeba sie cofac do innego kodu w poszukiwaniu jaki jest powod wywolania wyjatku (patrzymy na nazwe wyjatku np. NoFileException i od razu widzimy - aha pliku nie ma w katalogu, nie cofajac sie do miejsca wywolania wyjatku i analizowania kodu), majac tylko obslugiwany ogolny Exception trzeba sie cofac do miejsca w kodzie gdzie jest wywolywany wyjatek i sprawdzic dlaczego zostal wywolany by pozniej powrocic do pierwotnego kodu. Przy duzej aplikacji 2 sposob bedzie korzystniejszy zwłaszcza jesli do aplikacji zagladamy rzadko, zapominajac co czym bylo.

komentarz 25 lutego 2017 przez CzikaCarry Szeryf (75,340 p.)
No ale przecież mamy wiadomości z wyjątków, które same mówią za siebie, dlaczego wyjątek został rzucony :)
komentarz 25 lutego 2017 przez mbabane Szeryf (79,280 p.)
try { $obj->foo(); catch(Exception $e) {echo $e->getMessage();} }

Gdzie tu sa wiadomosci?

komentarz 25 lutego 2017 przez CzikaCarry Szeryf (75,340 p.)
echo wyświetla wiadomość, wystarczy odpalić sobie stronę np. przez apache, czy użyć magicznego narzędzia jakim jest debugger.
1
komentarz 25 lutego 2017 przez draghan VIP (106,230 p.)

mbabane ma tutaj słuszność. Ta opcja nie jest czytelna. Szczególnie, jeśli chcemy zrobić coś bardziej finezyjnego, niż tylko wyplucie komunikatu.

komentarz 25 lutego 2017 przez CzikaCarry Szeryf (75,340 p.)

Autor tematu wrzucił kawałek kodu z controllera:

try {
    $fileobj = new File("filename.txt");
} catch (Exception $e) {
    $error = $e->getMessage();
    ...
}

Jeśli wyciągał wiadomość, to logiczne jest, że chciał ją wyświetlić :)

komentarz 25 lutego 2017 przez Benek Szeryf (91,010 p.)

Faktycznie jedyną rolą wyjątku jest wyświetlenie komunikatu. W takim razie uważam podobnie jak CzikaCarry, że nie ma sensu definiować nowych klas, czytałem że zrzucanie wątków jest zasobochłonne. Ale myślmy obiektowo, nastawiając się na ciągłe rozbudowanie aplikacji w przyszłości. Skoro tak, to wypadałoby zdefiniować klasy wątków, pytanie tylko co umieścić w ich ciałach? Jedynym zadaniem wyjątków póki co jest wyświetlenie odpowiednich komunikatów, a to można zrealizować za pomocą konstruktora klasy bazowej Exception.

1
komentarz 25 lutego 2017 przez CzikaCarry Szeryf (75,340 p.)
Tutaj jest rozpisane co powinno być w ciele klasy

http://php.net/manual/en/language.exceptions.extending.php

Podobne pytania

0 głosów
0 odpowiedzi 54 wizyt
+1 głos
0 odpowiedzi 219 wizyt
pytanie zadane 2 listopada 2020 w C# przez XavRock Obywatel (1,390 p.)
0 głosów
1 odpowiedź 183 wizyt
pytanie zadane 3 stycznia 2020 w C# przez dawid2002 Mądrala (5,190 p.)

92,575 zapytań

141,424 odpowiedzi

319,649 komentarzy

61,960 pasjonatów

Motyw:

Akcja Pajacyk

Pajacyk od wielu lat dożywia dzieci. Pomóż klikając w zielony brzuszek na stronie. Dziękujemy! ♡

Oto polecana książka warta uwagi.
Pełną listę książek znajdziesz tutaj.

Akademia Sekuraka

Kolejna edycja największej imprezy hakerskiej w Polsce, czyli Mega Sekurak Hacking Party odbędzie się już 20 maja 2024r. Z tej okazji mamy dla Was kod: pasjamshp - jeżeli wpiszecie go w koszyku, to wówczas otrzymacie 40% zniżki na bilet w wersji standard!

Więcej informacji na temat imprezy znajdziecie tutaj. Dziękujemy ekipie Sekuraka za taką fajną zniżkę dla wszystkich Pasjonatów!

Akademia Sekuraka

Niedawno wystartował dodruk tej świetnej, rozchwytywanej książki (około 940 stron). Mamy dla Was kod: pasja (wpiszcie go w koszyku), dzięki któremu otrzymujemy 10% zniżki - dziękujemy zaprzyjaźnionej ekipie Sekuraka za taki bonus dla Pasjonatów! Książka to pierwszy tom z serii o ITsec, który łagodnie wprowadzi w świat bezpieczeństwa IT każdą osobę - warto, polecamy!

...