Подтвердить что ты не робот

OutOfRangeException и OutOfBoundsException

PHP определяет два SPL исключения для недопустимых ключей:

OutOfRangeException: Исключение, возникшее при запросе незаконного индекса. Это означает ошибки, которые должны быть обнаружены во время компиляции.

OutOfBoundsException: Исключение выбрано, если значение не является допустимым. Это означает ошибки, которые не могут быть обнаружены во время компиляции.

Поскольку PHP не является компилируемым языком, различие между временем компиляции и временем выполнения кажется странным, и поэтому мне трудно понять, какое исключение использовать, когда.

В настоящее время я понимаю, что нужно бросить...
... OutOfRangeException, если ключ фундаментально и по своей сути искажен, например. если массив передается в качестве ключа.
... OutOfBoundsException, если ключ вообще хорошо, но не находится в некоторых границах, например. если 100 передается, но 50 - это максимальный ключ.

Правильно ли это понимание?

4b9b3361

Ответ 1

В то время как у PHP нет классического "времени компиляции" (или компилятора, который делает много статических проверок, если на то пошло), я бы рассматривал "время компиляции" как "довольно статический материал, который я делал неправильно при написании кода" и "время выполнения", так как "моя логика, ввод или проверка были отключены в какой-то момент".

Итак, мое предложение было бы относиться к этому так:

"Compile Time" / "OutOfRangeException": ошибка всегда может быть исправлена ​​в исходном коде без или с очень малой логикой.

Я всегда беру числа от 1 до 10, и вы кладете 11


"Run Time" / "OutOfBoundsException": ошибка вызвана неправильным использованием во время выполнения.

Вы создали меня и сказали мне принимать значения от 1 до 5, после чего вы помещаете 7. Не вычисляет

или

Вы запрашиваете индекс, которого нет, потому что вы его не поместили, как вы должны


Пример:

Я бы ожидал, что SplFixedArray выкинет OutOfBoundsException, потому что он является динамическим и может иметь шанс во время выполнения, в то время как я ожидаю что-то вроде Calender::getMonthName для throw и OutOfRangeException, потому что число месяцев определенно фиксировано во время компиляции/записи.

Пример объекта массива:

Скажем $array - это объект, который реализует ArrayAccess, вы можете выбросить OutOfBoundsException в этих обстоятельствах:

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

В качестве значений вы можете ожидать ArrayAccess, но это не имеет смысла в случае SplFixedArray (5). Альтернативы были бы DomainException или, может быть, RangeException

An OutOfRangeException в этих случаях:

$calendar->getMonth(15);

Как размещение массива или нового класса, в коде есть определенная большая логическая ошибка, которая обычно возникает из-за простой ошибки "oh, я put in the wrong variable" программиста. Альтернативой (возможно, предпочтительнее) будет UnexpectedValueException и старый добрый InvalidArgumentException.

Для таких случаев, как:

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

некоторые из альтернативных исключений кажутся более подходящими.

Сравнение с миром Java, на котором исключение использовать, когда не всегда применимы, поскольку разработчики Java имеют проблемы с дополнениями.

Проверено/отменено исключение. Со многими людьми, утверждающими, что все, что не является исключением во время выполнения, очень ограничено в Java/не должно использоваться многократно), эти имена потеряли часть своего первоначального значения и намерения.

Ответ 2

Собственно, это:

LogicException

использовать для любых ошибок, которые разработчик сделал, например. ошибки при программировании/сборке приложения. Это, надеюсь, будет уловлено, когда разработчик запускает свои UnitTests (который тогда будет эквивалентом времени компиляции). Эти исключения никогда не должны возникать на месте производства, поскольку они являются ошибками в программном обеспечении как таковом.

RuntimeException:

использовать для любых ошибок, которые сделал пользователь, или из-за недействительных данных, помещенных в приложение во время выполнения. Это ошибки, которые могут быть предсказуемыми, но не полностью предотвращаемыми UnitTests, например. это может произойти на производственной площадке. Эти исключения могут быть связаны с неправильным использованием или ошибками программирования.

OutOfBounds

является эффективным IMO, что Википедия определяет как диапазон массива в Диапазон в программировании на компьютере, а именно:

Когда массив численно индексируется, его диапазон является верхней и нижней границей массива. В зависимости от среды предупреждение, фатальная ошибка или непредсказуемое поведение произойдет, если программа попытается получить доступ к элементу массива вне диапазона.

Другими словами, когда у вас есть массив с индексами [0,1,2], все, кроме [0,1,2], выходит за пределы. Обратите внимание, что Bounds также могут применяться к другим типам данных, например, попытка получить доступ к 7-му символу в 5-символьной строке также будет OutOfBounds.

OutOfRange:

этот жесткий файл cookie. В С++ OutOfRange является общим исключением, расширяющим LogicException (как и в PHP). Я не уверен, что приведенный пример легко переводится на PHP-код, хотя или мое определение времени компиляции выше. Главным образом, потому что никто не будет сначала инициализировать new Vector(10) и немедленно попытаться получить к нему доступ at(20).

В Java OutOfRange, похоже, ссылается на Диапазон в математическом смысле

Диапазон функции - это возможные значения y функции, которые возникают при подстановке всех возможных значений x в функцию.

Один ссылка Я мог найти, что он расширяет RuntimeException, хотя, поэтому я думаю, что изучение других языков не поможет решить эту тайну. Существует также открытый отчет об исключениях SPL в целом, в котором указано, что

  • OutOfRangeException (значение вне диапазона) - это логическое исключение, должно быть: RuntimeException

Но если это правильно, то как OutOfRange отличается от DomainException? И если ваше собственное определение правильное, то как OutOfRange отличается от InvalidArgumentException?

Короче говоря: я не знаю, для чего должен быть OutOfRangeException.

Ответ 3

Ответ на ваш вопрос для меня довольно неуловим. Однако, вот о чем подумать:

  • Если массив передается, когда мы ожидаем действительный массив, мы также имеем InvalidArgumentException, потому что это не правильный тип аргумента.
  • Мы также могли бы выбросить DomainException, потому что массивы не находятся в домене для ключей массива.
  • В php вы обычно не можете обнаруживать типы во время компиляции из-за позднего статического привязки. Они целенаправленно переносят привязку переменных во время выполнения.

Как я справляюсь с этой ситуацией:

  • Бросьте InvalidArgumentException, если переменная передается в любую функцию, где аргумент не является правильным. Я все еще делаю это при работе с массивами.
  • Бросьте InvalidArgumentException, если null был передан, когда этого не должно быть. Этого действительно может быть много, потому что null не набирается. Чтобы проверка кода ошибки была простой, я просто придерживаюсь недопустимого аргумента.
  • Throw OutOfBoundsException, когда индекс не находится в правильном диапазоне, как вы и предполагали.
  • Throw BadFunctionCallException, если предоставленная пользователем функция в качестве параметра не имеет правильной формы. Если ваша структура внутри представляет собой массив, имеет смысл, что они могут передавать функцию для ее изменения, поэтому иногда это происходит.

Как правило, я могу использовать только эти три исключения, чтобы представлять все ошибки, которые происходят за пределами специальных ресурсов (соединения в сети и базы данных будут особыми ресурсами). Третий, похоже, чаще всего возникал, но в основном я только что занимался с бывшими двумя.

Ответ 4

Это довольно просто:

OutOfRange означает "Ваш запрошенный ключ не находится в индексе набора , определенного в коде."

OutOfBounds означает "Ваш запрошенный ключ не находится в индексе набора , определяемом загруженной конфигурацией."

Ответ 5

Путаница в этом случае происходит от нескольких факторов. Во-первых, PHP фактически скомпилирован в байт-код. Существует несколько условий исполнения, в которых эта скомпилированная форма сохраняется в относительно постоянной форме на сервере. Однако проблема OutOfRangeException/OutOfBoundsException заключается не в том, что она касается ошибки категоризации, сделанной людьми, которые задокументировали эти конкретные классы исключений.

Поскольку PHP динамически типизирован, часто невозможно проверить диапазоны и даже типы во время компиляции. В руководстве указано, что OutOfRangeException должно быть поднято во время компиляции, а OutOfBoundsException должно применяться во время выполнения, что является ошибочным различием в этом контексте.

В обоих руководствах используется нечеткий язык того, что означает незаконный индекс, но при изучении использования их родительских классов дает некоторые подсказки: логические исключения дополняются такими классами, как DomainException, InvalidArgumentException и LengthException, тогда как исключения Runtime - это такие вещи, как UnexpectedValueException, OverflowException и UnderflowException. Из этого шаблона можно сделать вывод, что OutOfRangeException, вероятно, следует применять к нелегальным типам ключей, а OutOfBoundsException должно применяться к значениям индекса, которые имеют правильный тип, но не находятся в пределах их контейнера.

Было некоторое обсуждение в списке разработчиков PHP о том, что эти категоризации ошибочны, но проблема идет глубже, чем это. На практике оба исключения могут только быть подняты во время выполнения. Вы можете использовать капризы документации, чтобы выжать различие между недопустимыми типами ключей и недопустимыми значениями индекса, но в этот момент мы говорим об ошибке в документации PHP.

Ответ 6

  • Если вы получите неожиданный индекс. т.е. вы ожидаете string, но в итоге получите integer или наоборот. Затем вы должны выбросить исключение UnexpectedValueException.
  • Если вы получаете нужный тип индекса, но его не существует. Затем поднимите warning (trigger_error) и продолжайте. Ожидается, что это не остановит поток программирования.
  • Если у вас есть объект, который итерируется или должен быть итерирован по диапазону, и он достигает предела (т.е. конец файла), тогда вы должны выбросить OutOfBoundsException.
  • Все остальное является кандидатом на OutOfRangeException.

В условиях неспециалиста. OutOfBoundsException - это что-то нормальное. Это не так серьезно. Это то, что часто случается и должно быть позабочено. он может использоваться итераторами для чтения данных, пока их больше не читать. Это логическая ошибка. Сделано кем-то, использующим код не кем-то, пишущим код.

An OutOfRangeException - это нечто серьезное. Кто-то должен посмотреть исходный код. Кто-то должен выяснить, что произошло. Это важно. Теоретически этого никогда не должно было случиться. Вызовите 911. Это ошибка времени компиляции. Сделано фиктивным программистом.

Исключения за пределами диапазона написаны программистами для защиты от ошибок других программистов. Или, может быть, в будущем. Если вы чувствуете, что чего-то подобного никогда не произойдет, используйте Out Of Range. Используйте "Вне границ" для чего-то, что может произойти.