OutOfRangeException vs. OutOfBoundsException

PHP definiuje dwa wyjątkiSPL dla nieprawidłowych kluczy:

OutOfRangeException: wyjątek wyrzucony, gdy zażądano nielegalnego indeksu. Oznacza to błędy, które powinny zostać wykryte podczas kompilacji.

OutOfBoundsException: wyjątek wyrzucony, jeśli wartość nie jest poprawnym kluczem. Oznacza to błędy, których nie można wykryć podczas kompilacji.

Ponieważ PHP nie jest językiem skompilowanym, rozróżnienie między czasem kompilacji a czasem wykonywania wydaje się dziwne i dlatego jestem trudno zrozumieć, którego wyjątku użyć, kiedy.

Obecnie rozumiem, że należy rzucać...
... OutOfRangeException jeśli klucz jest zasadniczo i z natury zniekształcony, np. jeśli tablica jest przekazywana jako klucz.
... OutOfBoundsException Jeśli klucz jest ogólnie w porządku, ale nie znajduje się w pewnych granicach, np. jeśli 100 jest przekazany, ale 50 jest kluczem maksymalnym.

Czy to zrozumienie jest poprawne?
Author: NikiC, 2011-11-19

6 answers

Podczas gdy PHP nie ma klasycznego "czasu kompilacji" (lub kompilatora, który wykonuje wiele statycznych kontroli w tym zakresie) traktowałbym "czas kompilacji" jako "raczej statyczne rzeczy, które zrobiłem źle podczas pisania kodu" i "czas wykonania "jako"moja logika, wejście lub Walidacja była w pewnym momencie wyłączona".

Więc moją propozycją byłoby potraktowanie tego w ten sposób:

"Compile Time" / "OutOfRangeException": Błąd można zawsze naprawić w kodzie źródłowym bez lub z bardzo małą logiką.

Zawsze biorę liczby od 1-10 a Ty wstawiasz 11


"Run Time" / "OutOfBoundsException": błąd jest spowodowany niewłaściwym użyciem w czasie wykonywania.

Stworzyłeś mnie i kazałeś mi przyjmować wartości od 1 do 5, a potem dodałeś 7. Nie oblicza

Lub

Żądasz indeksu, którego nie ma, ponieważ nie umieściłeś go tam tak, jak powinieneś


Próbka:

Spodziewałbym się, że splfixedarray rzuci OutOfBoundsException, ponieważ jego rozmiar jest dynamiczny i może się zdarzyć podczas wykonywania spodziewaj się czegoś takiego jak Calender::getMonthName do rzucania i OutOfRangeException, ponieważ liczba miesięcy jest definitywnie ustalona w czasie "kompilacji/zapisu".

Próbka obiektu tablicy:

Powiedzmy, że $ tablica jest obiektem, który implementuje ArrayAccess, możesz rzucić OutOfBoundsException w takich okolicznościach:

$array['bar'];
$array[7];

Ponieważ wartości są tym, czego można oczekiwać od ArrayAccess, ale nie ma to sensu w przypadku splfixedarray (5). Alternatywą byłoby DomainException a może RangeException

An OutOfRangeException w tych przypadki:

$calendar->getMonth(15);

Jako umieszczenie tablicy lub nowej klasy istnieje na pewno jakaś większa wada logiczna w kodzie, która zwykle wynika z prostego błędu" oh, I put in the wrong variable " programisty. Alternatywą może być UnexpectedValueException i stary dobry InvalidArgumentException.

Dla takich przypadków jak:

$array[array()];
$array[new StdClass];

Niektóre z alternatywnych WYJĄTKÓW wydają się bardziej odpowiednie.

Porównania ze światem Javy, na których wyjątkach używać, gdy nie zawsze mają zastosowanie jako Java Deweloperzy mają problem z dodatkami do czynienia.

Zaznaczone/niezaznaczone wyjątki. Wiele osób argumentuje, że wszystko, co nie jest wyjątkiem uruchomieniowym, ma bardzo ograniczone zastosowanie w Javie / nie powinno być używane zbyt wewnętrznie) nazwy te straciły część swojego pierwotnego znaczenia i intencji.

 25
Author: edorian,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2011-12-04 10:16:33

Moje własne zdanie na ten temat to:

LogicException

Użyj dla wszelkich błędów programisty , np. błędów podczas programowania/montażu aplikacji. Miejmy nadzieję, że zostaną one przechwycone, gdy deweloper uruchomi swoje Unittesty (które będą wtedy odpowiednikiem czasu kompilacji). Wyjątki te nigdy nie powinny wystąpić w miejscu produkcji, ponieważ są to błędy w oprogramowaniu jako takim.

RuntimeException:

Użyj dla wszelkich błędów użytkownik zrobił lub wynik z nieprawidłowych danych wprowadzonych do aplikacji w czasie wykonywania. Są to błędy, które mogą być przewidywane, ale nie można w pełni zapobiec przez Unittesty, np. te mogą się zdarzyć w zakładzie produkcyjnym. Wyjątki te mogą wynikać z niewłaściwego użytkowania lub błędów programistycznych.

OutOfBounds

Jest IMO efektywnie tym, co Wikipedia definiuje jako zakres tablicy W zakres w programowaniu komputerowym , a mianowicie:

Gdy tablica jest indeksowana numerycznie, jej zakres jest górną i dolną granicą tablicy. W zależności od środowiska, jeśli program spróbuje uzyskać dostęp do elementu tablicy, który znajduje się poza zakresem, pojawi się ostrzeżenie, błąd krytyczny lub nieprzewidywalne zachowanie.

Innymi słowy, gdy macie tablicę z indeksami [0,1,2] wszystko poza [0,1,2]jest poza granicami. Należy pamiętać, że ograniczenia mogą również dotyczyć innych typów danych, np. próba uzyskania dostępu do 7.znaku w ciągu 5 znaków również byłaby OutOfBounds.

OutOfRange:

Ten jest twardy. W C++ OutOfRange jest ogólnym wyjątkiem rozszerzającym LogicException (podobnie jak w PHP). Nie jestem pewien, czy podany przykład jest łatwy do przetłumaczenia na kod PHP, czy też moja definicja czasu kompilacji powyżej. Głównie dlatego, że nikt nie pierwszy init a new Vector(10) i natychmiast spróbować uzyskać do niego dostęp at(20).

W Javie OutOfRange wydaje się odnosić do zakresu w sensie matematycznym

Zakres a funkcja jest możliwymi wartościami y funkcji, które wynikają, gdy zamienimy wszystkie możliwe wartości x na funkcję.

Jeden odniesienie znalazłem ma to rozszerzenie RuntimeException choć, więc myślę, że patrząc na inne języki nie pomoże rozwiązać tej zagadki. Istnieje również otwarty raport o błędzie o wyjątkach SPL w ogóle , stwierdzający, że

  • OutOfRangeException (wartość jest poza zakresem) jest LogicException, powinno być: RuntimeException

Ale jeśli to jest poprawne, to czym OutOfRange różni się od DomainException? A jeśli twoja własna definicja jest poprawna, to czym się różni OutOfRange od InvalidArgumentException?

Krótko mówiąc: Nie wiem, Do czego ma służyć OutOfRangeException.

 11
Author: Gordon,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2011-11-22 16:46:57

Odpowiedź na twoje pytanie jest dla mnie nieuchwytna. Jednak oto kilka rzeczy do przemyślenia:

  • jeśli tablica jest przekazywana, gdy oczekujemy poprawnego klucza tablicy, mamy również InvalidArgumentException, ponieważ nie jest to właściwy typ argumentu.
  • możemy również rzucić DomainException, ponieważ tablice nie są w domenie dla kluczy tablicy.
  • w php, zazwyczaj nie można wykryć typów w czasie kompilacji z powodu późnego wiązania statycznego. Celowo opóźniają Wiązanie zmiennych do runtime.

Jak sobie radzę z tą sytuacją:

  • rzut InvalidArgumentException jeśli zmienna zostanie przekazana do dowolnej funkcji, w której argument nie jest prawidłowym typem. Nadal to robię podczas pracy z tablicami.
  • Rzuć InvalidArgumentException Jeśli null zostało przekazane, kiedy nie powinno być. To naprawdę może być wiele rzeczy, ponieważ null nie jest wpisany. Aby sprawdzanie kodu błędu było proste, po prostu trzymam się nieprawidłowego argumentu.
  • Throw OutOfBoundsException gdy indeks nie jest w prawidłowy zasięg, tak jak sugerowałeś.
  • Throw BadFunctionCallException jeśli podana przez użytkownika funkcja jako parametr nie ma prawidłowej formy. Jeśli twoja struktura wewnątrz jest tablicą, ma sens, że mogą one przekazać funkcję, aby ją zmodyfikować, więc pojawia się to od czasu do czasu.

Ogólnie, mogę użyć tylko tych trzech WYJĄTKÓW do reprezentowania wszystkich błędów, które występują poza specjalnymi zasobami (Połączenia sieciowe i bazodanowe byłyby specjalnymi zasobami). Trzeci wydaje się być coraz częściej, ale przede wszystkim miałem do czynienia z dwoma poprzednimi.

 4
Author: Levi Morrison,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2011-11-19 17:34:12

To dość proste:

OutOfRange oznacza " żądany klucz nie mieści się w indeksie zbioru zdefiniowane w kodzie."

OutOfBounds oznacza " wymagany klucz nie mieści się w indeksie zbioru zdefiniowana przez załadowaną konfigurację."

 4
Author: kriss,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2013-12-09 22:47:08

Zamieszanie w tym przypadku wynika z kilku czynników. Po pierwsze, PHP jest w rzeczywistości skompilowany do kodu bajtowego. Istnieje kilka środowisk wykonawczych, w których ta skompilowana forma utrzymuje się w stosunkowo trwałej formie na serwerze. Jednak problem OutOfRangeException/OutOfBoundsException Nie dotyczy tego, ale błędu kategoryzacji popełnionego przez osoby, które udokumentowały te specyficzne klasy WYJĄTKÓW.

Ponieważ PHP jest wpisywane dynamicznie, często nie można sprawdzić zakresy, a nawet typy w czasie kompilacji. Podręcznik stwierdza, że OutOfRangeException powinien być podniesiony w czasie kompilacji, a OutOfBoundsException powinien mieć zastosowanie w czasie wykonywania, co jest błędnym rozróżnieniem w tym kontekście.

Oba wpisy podręcznika używają niejasnego języka, co oznacza nielegalny indeks, ale patrząc na użycie ich klas nadrzędnych daje pewne wskazówki: LogicExceptions są rozszerzane o klasy takie jak DomainException, InvalidArgumentException i LengthException, podczas gdy Wyjątkami Runtime są rzeczy takie jak UnexpectedValueException, OverflowException i UnderflowException. Z tego wzorca można wywnioskować, że OutOfRangeException powinien być prawdopodobnie zastosowany do nielegalnych typów kluczy, a OutOfBoundsException powinien mieć zastosowanie do wartości indeksu, które są właściwego typu, ale nie mieszczą się w granicach ich kontenera.

Była dyskusja na liście deweloperów PHP o błędnych kategoryzacjach, ale problem sięga głębiej. W praktyce zarówno wyjątki mogą być wywoływane tylko w czasie wykonywania. Możesz użyć kaprysów dokumentacji, aby wycisnąć rozróżnienie między nieprawidłowymi typami kluczy i nieprawidłowymi wartościami indeksu, ale w tym momencie mówimy o błędzie w dokumentacji PHP.

 1
Author: Udo,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2011-11-28 23:18:04
  1. jeśli otrzymasz nieoczekiwany indeks. ie spodziewasz się string / align = "left" / integer albo odwrotnie. Następnie należy rzucić UnexpectedValueException wyjątek.
  2. Jeśli otrzymasz odpowiedni typ indeksu, ale nie istnieje. Następnie podnieść warning (trigger_error) i kontynuuj. Nie oczekuje się, że to zatrzyma przepływ programowania.
  3. jeśli masz obiekt, który jest iterowalny lub powinien być iterowalny w zakresie i osiąga jego limit (tj. koniec pliku), następnie należy rzucić OutOfBoundsException.
  4. Anything else is a candidate for OutOfRangeException.

W kategoriach laika. An OutOfBoundsException jest czymś normalnym. To nic poważnego. Jest to coś, co zdarza się często i powinno być załatwione. może być używany przez Iteratory do czytania danych, dopóki nie będzie ich więcej. Jest to błąd logiczny. Wykonane przez kogoś używającego kodu, a nie przez kogoś piszącego kod.

An OutOfRangeException to coś poważnego. Ktoś powinien spojrzeć na kod źródłowy. Ktoś powinien się dowiedzieć, co się stało. To ważne. Teoretycznie nie miało do tego dojść. Zadzwoń na 911. Jest to błąd czasu kompilacji. Wykonane przez programatora atrapy.

Wyjątki spoza zakresu są pisane przez programistów, aby chronić się przed błędami innych programistów. A może siebie w przyszłości. Jeśli czujesz, że coś takiego nigdy nie może się zdarzyć, użyj poza zasięgiem. Użyj poza granicami dla czegoś, co może się wydarzyć.

 0
Author: mAsT3RpEE,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2014-01-31 20:22:13