OutOfRangeException и OutOfBoundsException

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

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

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

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

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

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

6 ответов


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

поэтому мое предложение было бы так:

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

I всегда беру цифры от 1-10 и 11


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

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

или

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


пример:

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

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

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

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

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

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

$calendar->getMonth(15);

как положить массив или новый класс, безусловно, есть какой-то больший логический недостаток в коде, который обычно является результатом простой ошибки "О, я положил неправильную переменную" программистом. Альтернативой (возможно, предпочтительной) будет UnexpectedValueException и InvalidArgumentException.

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

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

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

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

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


мой собственный взгляд на это:

LogicException

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

RuntimeException:

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

OutOfBounds

ИМО эффективно то, что Википедия определяет как


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

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

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

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

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


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

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

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


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

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

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

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


  1. если вы получите неожиданный индекс. т. е. вы ожидаете string но в конечном итоге с помощью integer или наоборот. Тогда вы должны бросить UnexpectedValueException исключения.
  2. если вы получаете правильный тип индекса, но его не существует. Тогда поднимите warning (trigger_error) и перейти на. Это не должно остановить поток программирования.
  3. если у вас есть объект, который является Iterable или должен быть повторяемого в диапазон и он достигает своего предела (т. е. конца файла), тогда вы должны бросить OutOfBoundsException.
  4. все остальное является кандидатом на OutOfRangeException.

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

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

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