nikic
PHP define dos SPL excepciones para claves inválidas:
OutOfRangeException
: Excepción lanzada cuando se solicitó un índice ilegal. Esto representa errores que deben detectarse en tiempo de compilación.
OutOfBoundsException
: Excepción lanzada si un valor no es una clave válida. Esto representa errores que no se pueden detectar en tiempo de compilación.
Como PHP no es un lenguaje compilado, la distinción entre tiempo de compilación y tiempo de ejecución parece extraña y, por lo tanto, me resulta difícil entender qué excepción usar y cuándo.
Actualmente tengo entendido que uno debe tirar…
… OutOfRangeException
si la clave tiene una forma fundamental e inherentemente incorrecta, por ejemplo, si se pasa una matriz como clave.
… OutOfBoundsException
si la clave generalmente está bien, pero no está en algunos límites, por ejemplo, si 100
se pasa pero 50
es la clave máxima.
¿Es correcto ese entendimiento?
edoriano
Si bien PHP no tiene un “tiempo de compilación” clásico (o un compilador que haga muchas verificaciones estáticas), trataría el “tiempo de compilación” como “cosas bastante estáticas que hice mal al escribir el código” y ” tiempo de ejecución” como “mi lógica, entrada o validación estaba desactivada en algún momento”.
Así que mi sugerencia sería tratarlo así:
"Compile Time" / "OutOfRangeException"
: El error siempre se puede arreglar en el código fuente sin o con muy poca lógica.
Siempre tomo los números del 1 al 10 y tú pones el 11
"Run Time" / "OutOfBoundsException"
: El error se debe a un uso incorrecto en tiempo de ejecución.
Me creaste y me dijiste que tomara valores del 1 al 5 y luego pusiste 7. No calcula
o
Solicitas un índice que no está porque no lo pusiste como deberías
Muestra:
Esperaría que un SplFixedArray lanzara un OutOfBoundsException
porque su tamaño es dinámico y puede cambiar en tiempo de ejecución mientras que esperaría algo como un Calender::getMonthName
tirar y OutOfRangeException
porque el número de meses definitivamente se fija en el momento de “compilar/escribir”.
Ejemplo de objeto de matriz:
Digamos que $array es un objeto que implementa ArrayAccess, podría lanzar un OutOfBoundsException
en estas circunstancias:
$array['bar'];
$array[7];
Como los valores son los que podría esperar para ArrayAccess, pero no tiene sentido en el caso de SplFixedArray(5). Las alternativas serían DomainException
o tal vez RangeException
Un OutOfRangeException
en estos casos:
$calendar->getMonth(15);
Al colocar una matriz o una nueva clase, definitivamente hay una falla lógica más grande en el código que generalmente resulta de un simple error “oh, puse la variable incorrecta” por parte de un programador. Una alternativa (quizás preferible) sería UnexpectedValueException
y buen viejo InvalidArgumentException
.
Para casos como:
$array[array()];
$array[new StdClass];
algunas de las excepciones alternativas parecen más adecuadas.
Las comparaciones con el mundo de Java sobre qué excepción usar cuando no siempre son aplicables, ya que los desarrolladores de Java tienen que lidiar con un problema de adiciones.
Excepciones marcadas/no marcadas. Con muchas personas argumentando que todo lo que no es una excepción de tiempo de ejecución tiene un uso muy limitado en Java / no debe usarse mucho internamente) esos nombres han perdido parte de su significado e intención originales.
-
Ayn comentarios sobre el voto negativo? Me gustaría saber qué está mal esto. Incluso un “Simplemente no estoy de acuerdo con eso” está bien 🙂
– edoriano
29 de noviembre de 2011 a las 12:55
Mi propia opinión sobre esto es:
LogicException
utilice para cualquier error el desarrollador hizo, por ejemplo, errores al programar/ensamblar la aplicación. Con suerte, se detectarán cuando el desarrollador esté ejecutando sus UnitTests (que entonces serían el equivalente al tiempo de compilación). Esas excepciones nunca deben ocurrir en el sitio de producción, ya que son errores en el software como tal.
RuntimeException
:
utilice para cualquier error el usuario hizo o que resulta de datos no válidos ingresados en la aplicación en tiempo de ejecución. Estos son errores que UnitTests puede anticipar pero no prevenir por completo, por ejemplo, pueden ocurrir en un sitio de producción. Esas excepciones podrían deberse a un uso incorrecto o errores de programación.
OutOfBounds
es IMO efectivamente lo que Wikipedia define como Rango de una matriz en Gama en Programación Informáticaa saber:
Cuando una matriz está indexada numéricamente, su rango es el límite superior e inferior de la matriz. Según el entorno, se producirá una advertencia, un error fatal o un comportamiento impredecible si el programa intenta acceder a un elemento de matriz que está fuera del rango.
En otras palabras, cuando tienes una matriz con índices [0,1,2] todo menos [0,1,2] está fuera de los límites. Tenga en cuenta que los límites también se pueden aplicar a otros tipos de datos, por ejemplo, intentar acceder al séptimo carácter en una cadena de 5 caracteres también sería fuera de los límites.
OutOfRange
:
esta es una galleta dura. En C++ Fuera de rango es una excepción genérica que extiende LogicException (al igual que en PHP). No estoy seguro de si el ejemplo dado es fácilmente traducible a código PHP o mi definición de tiempo de compilación anterior. Principalmente porque nadie iniciaría primero un new Vector(10)
y el inmediatamente tratar de acceder a ella at(20)
.
en Java OutOfRange
parece referirse a Rango en el sentido matemático
El rango de una función son los posibles valores de y de una función que resultan cuando sustituimos todos los posibles valores de x en la función.
Una referencia Sin embargo, podría encontrar que extiende RuntimeException, así que supongo que buscar en otros idiomas no ayudará a resolver este misterio. También hay un abierto informe de error sobre las excepciones de SPL en generaldeclarando que
- OutOfRangeException (el valor está fuera de rango) es LogicException, debería ser: RuntimeException
Pero si esto es correcto, ¿en qué se diferencia OutOfRange de DomainException? Y si su propia definición es correcta, ¿en qué se diferencia OutOfRange de InvalidArgumentException
?
Para abreviar una larga historia: no sé qué OutOfRangeException
se supone que es para.
-
Acordar
OutOfRangeException
. Inútil. También tenga en cuenta queInvalidArgumentException
es unLogicException
.–Levi Morrison
22 de noviembre de 2011 a las 19:49
-
LogicException “uso para cualquier error que cometió el desarrollador…”. Discrepar. InvalidArgumentException es un tipo de LogicException. Y suele ocurrir que el usuario final es el que proporciona los argumentos a un programa.
– spinkus
2 de marzo de 2020 a las 11:58
La respuesta a su pregunta es bastante difícil de alcanzar para mí también. Sin embargo, aquí hay algunas cosas para pensar:
- Si se pasa una matriz cuando esperamos una clave de matriz válida, también tenemos
InvalidArgumentException
porque no es el tipo de argumento adecuado. - También podríamos lanzar un
DomainException
porque las matrices no están en el dominio de las claves de matriz. - En php, generalmente no puede detectar tipos en tiempo de compilación debido al enlace estático tardío. Deliberadamente retrasan el enlace de las variables al tiempo de ejecución.
Cómo manejo esta situación:
- lanzar un
InvalidArgumentException
si una variable se pasa a cualquier función donde el argumento no es del tipo correcto. Todavía hago esto cuando trabajo con arreglos. - lanzar un
InvalidArgumentException
sinull
fue pasado cuando no debería ser. Este realmente podría ser un montón de cosas porque no se escribe nulo. Para simplificar la verificación del código de error, simplemente me quedo con el argumento inválido. - Lanzar
OutOfBoundsException
cuando un índice no está en el rango correcto, tal como lo sugirió. - Lanzar
BadFunctionCallException
si una función proporcionada por el usuario como parámetro no tiene la forma correcta. Si su estructura interna es una matriz, tiene sentido que puedan pasar una función para modificarla, por lo que esto surge ocasionalmente.
En general, puedo usar solo estas tres excepciones para representar todos los errores que ocurren fuera de los recursos especiales (las conexiones de red y base de datos serían recursos especiales). El tercero parece haber estado surgiendo con más frecuencia, pero principalmente acabo de tratar con los dos primeros.
Es bastante simple:
Fuera de rango significa “Su clave solicitada no está dentro del índice de un conjunto definido en código.”
Fuera de los límites significa “Su clave solicitada no está dentro del índice de un conjunto definido por la configuración cargada.”
La confusión en este caso proviene de un par de factores. Primero, PHP está de hecho compilado en bytecode. Hay varios entornos de ejecución en los que este formulario compilado persiste de forma relativamente permanente en el servidor. Sin embargo, el problema de OutOfRangeException/OutOfBoundsException no se trata de eso, se trata de un error de categorización cometido por las personas que documentaron estas clases de excepción específicas.
Dado que PHP se escribe dinámicamente, a menudo es imposible verificar rangos e incluso tipos en tiempo de compilación. El manual establece que OutOfRangeException debe generarse en tiempo de compilación y OutOfBoundsException debe aplicarse en tiempo de ejecución, lo cual es una distinción errónea en este contexto.
Ambas entradas manuales usan un lenguaje poco claro de lo que significa un índice ilegal, pero mirar el uso de sus clases principales da algunas pistas: LogicExceptions se extienden por clases como DomainException, InvalidArgumentException y LengthException, mientras que las excepciones de tiempo de ejecución son cosas como UnexpectedValueException, OverflowException y Excepción de subdesbordamiento. A partir de este patrón, se puede inferir que OutOfRangeException probablemente debería aplicarse a tipos de clave ilegales, y OutOfBoundsException debería aplicarse a valores de índice que son del tipo correcto pero que no están dentro de los límites de su contenedor.
Hubo cierta discusión en la lista de desarrolladores de PHP acerca de que estas categorizaciones eran incorrectas, pero el problema es más profundo que eso. En la práctica, ambas excepciones solo pueden generarse en tiempo de ejecución. Puede usar los caprichos de la documentación para sacar una distinción entre tipos de clave no válidos y valores de índice no válidos, pero en este punto estamos hablando de un error en la documentación de PHP.
-
Estoy de acuerdo contigo completamente. ¿Qué tal el siguiente escenario? Desea evitar que php cree propiedades dinámicas definiendo el método mágico __set. En caso de que esta función arroje una excepción OutOfBoundsException o OutOfRangeException o incluso una InvalidArgumentException. No estoy seguro de eso. Según su explicación, asumiría que OutOfBoundsException sería la correcta, ya que la clave del nombre de la propiedad no está dentro de los límites de las propiedades definidas.
– Alejandro Behling
15/10/2021 a las 15:00
MASS3RPE
- Si obtiene un índice inesperado. es decir, esperas un
string
pero termina con uninteger
o viceversa. Entonces deberías lanzar unUnexpectedValueException
excepción. - Si obtiene un tipo adecuado de índice pero no existe. Entonces levante un
warning
(trigger_error)
y continuar. No se espera que esto detenga el flujo de programación. - Si tiene un objeto que es iterable o se supone que debe iterarse en un rango y alcanza su límite (es decir, el final de un archivo), entonces debe lanzar un
OutOfBoundsException
. - Cualquier otra cosa es candidata a
OutOfRangeException
.
En términos sencillos. Un OutOfBoundsException
es algo normal No es tan grave. Es algo que sucede a menudo y debe ser atendido. puede ser utilizado por iteradores para seguir leyendo datos hasta que no haya más para leer. Es un error lógico. Hecho por alguien que usa el código, no por alguien que escribe el código.
Un OutOfRangeException
es algo serio Alguien debería mirar el código fuente. Alguien debería averiguar qué pasó. Esto es importante. Teóricamente, esto nunca se suponía que sucedería. Llame al 911. Es un error de tiempo de compilación. Hecho por el programador ficticio.
Los programadores escriben las excepciones fuera de rango para protegerse contra errores de otros programadores. O tal vez usted mismo en el futuro. Si siente que algo así nunca podría suceder, use Fuera de rango. Use Fuera de los límites para algo que probablemente suceda.
-
Estoy de acuerdo contigo completamente. ¿Qué tal el siguiente escenario? Desea evitar que php cree propiedades dinámicas definiendo el método mágico __set. En caso de que esta función arroje una excepción OutOfBoundsException o OutOfRangeException o incluso una InvalidArgumentException. No estoy seguro de eso. Según su explicación, asumiría que OutOfBoundsException sería la correcta, ya que la clave del nombre de la propiedad no está dentro de los límites de las propiedades definidas.
– Alejandro Behling
15/10/2021 a las 15:00
Sí, tu comprensión es correcta 🙂
–Ryan Casas
19 de noviembre de 2011 a las 11:42
Su comprensión es correcta; e incluso si PHP no está compilado, el “intérprete” transforma su código en una forma intermedia, mientras verifica los errores sintácticos y luego ejecuta el código desde ese punto si todo está bien. Esto es lo que significa “compilación” en el contexto de lenguajes interpretados como Python/PHP/Perl (no hablo PHP, pero los conceptos son similares).
– saga de yati
19 de noviembre de 2011 a las 11:46
la “compilación” de la que habla yati se llama “análisis”.
– biera
4 oct 2012 a las 16:15
@biera exactamente. PHP y también Java (tal vez también en otro idioma, pero estos son con los que estoy familiarizado) analizan el código y generan un código de bytes para una máquina virtual. La única diferencia entre Java y PHP es que Java almacena este código de bytes de forma permanente y este código luego pasa manualmente a través de la máquina virtual, mientras que PHP no lo almacena de forma permanente. Analiza el código fuente, genera el llamado código de operación y luego ejecuta este código de operación sobre la marcha.
– Alejandro Behling
15 oct 2021 a las 14:40