Un compañero de trabajo ha agregado el comando assert varias veces dentro de nuestras bibliotecas en lugares donde habría usado una declaración if y lanzado una excepción. (Nunca había oído hablar de la afirmación antes de esto). Aquí hay un ejemplo de cómo lo usó:
assert('isset($this->records); /* Records must be set before this is called. */');
Yo habría hecho:
if (!isset($this->records)) {
throw new Exception('Records must be set before this is called');
}
Después de leer los documentos de PHP sobre aserción , parece que se recomienda que se asegure de que la aserción esté activa y agregue un controlador antes de usar la aserción. No puedo encontrar un lugar donde haya hecho esto.
Entonces, mi pregunta es, ¿usar aserción es una buena idea dado lo anterior y debería usarlo con más frecuencia en lugar de if y excepciones?
Otra nota, estamos planeando usar estas bibliotecas en una variedad de proyectos y servidores, incluidos proyectos de los que es posible que ni siquiera seamos parte (las bibliotecas son de código abierto). ¿Esto hace alguna diferencia en el uso de assert?
'isset
(la línea de código conassert
)? ¿No soloisset
(sin las comillas simples'
)?Respuestas:
La regla general que se aplica en la mayoría de los lenguajes (todo lo que sé vagamente) es que an
assert
se usa para afirmar que una condición siempre es verdadera, mientras que anif
es apropiado si es concebible que a veces fallará.En este caso, yo diría que
assert
es apropiado (basado en mi débil comprensión de la situación) porquerecords
debe siempre ser establecido antes de llamar al método dado. Por lo tanto, no establecer el récord sería un error en el programa en lugar de una condición de tiempo de ejecución. Aquí, elassert
está ayudando a asegurar (con las pruebas adecuadas) que no hay una posible ruta de ejecución del programa que pueda causar que el código que está siendo protegido con elassert
sea llamado sinrecords
haber sido configurado.La ventaja de usar
assert
en lugar deif
es queassert
generalmente se puede desactivar en el código de producción, lo que reduce los gastos generales. El tipo de situaciones con las que se maneja mejorif
posiblemente podría ocurrir durante el tiempo de ejecución en el sistema de producción y, por lo tanto, no se pierde nada al no poder apagarlas.fuente
assert_options(ASSERT_BAIL)
. De todos modos, es más rápido que el manual si / lanza soluciones.Piense en afirmaciones como "comentarios de poder". En lugar de un comentario como:
// Note to developers: the parameter "a" should always be a number!!!
utilizar:
assert('is_numeric(a) /* The parameter "a" should always be a number. */');
Los significados son exactamente los mismos y están destinados a la misma audiencia exacta, pero el primer comentario se olvida o ignora fácilmente (sin importar cuántos signos de exclamación), mientras que el "comentario de poder" no solo está disponible para que los humanos lo lean y comprendan, También se prueba constantemente en la máquina durante el desarrollo y no se ignorará si configura un buen manejo de aserción en el código y en los hábitos de trabajo.
Visto de esta manera, las afirmaciones son un concepto completamente diferente que si (error) ... y las excepciones, y pueden coexistir.
Sí, debería comentar su código, y sí, debería utilizar "comentarios de poder" (afirma) siempre que sea posible.
fuente
Depende totalmente de su estrategia de desarrollo. La mayoría de los desarrolladores desconocen
assert()
y utilizan las pruebas unitarias posteriores. Pero los esquemas de prueba proactivos e integrados a veces pueden ser ventajosos.Afirmar es útil porque se puede activar y desactivar. No agota el rendimiento si no se define tal controlador de aserción. Su colega no tiene uno, y debe diseñar algún código que lo habilite temporalmente en el entorno de desarrollo (si E_NOTICE / E_WARNINGs están activados, también debería estar el controlador de aserción). Lo uso ocasionalmente cuando mi código no puede soportar tipos de variables mixtas; normalmente no me dedico a la escritura estricta en un PHP de tipo débil, pero hay casos de uso aleatorios:
function xyz($a, $b) { assert(is_string($a)); assert(is_array($b));
Lo que, por ejemplo, compensaría la falta de especificadores de tipo
string $a, array $b
. PHP5.4 los admitirá, pero no los comprobará.fuente
Assert no es un sustituto de los me gusta
if
o las excepciones de control de flujo normales , porque solo está destinado a ser utilizado para depurar durante el desarrollo.fuente
Una nota importante sobre la aserción en PHP anterior al 7. A diferencia de otros lenguajes con una construcción de aserción, PHP no descarta las declaraciones de aserción por completo - las trata como una función (hacer un debug_backtrace () en una función llamada por una aserción). Apagar afirmaciones parece simplemente conectar la función para que no haga nada en el motor. Tenga en cuenta que se puede hacer que PHP 7 emule este comportamiento estableciendo zend.assertions en 0 en lugar de los valores más normales de 1 (activado) o -1 (desactivado).
El problema surge en que la aserción acepta cualquier argumento, pero si el argumento no es una cadena, la aserción obtiene los resultados de la expresión, ya sea que la aserción esté activada o desactivada. Puede verificar esto con el siguiente bloque de código.
<?php function foo($a) { echo $a . "\n"; return TRUE; } assert_options(ASSERT_ACTIVE, FALSE); assert( foo('You will see me.')); assert('foo(\'You will not see me.\')'); assert_options(ASSERT_ACTIVE, TRUE); assert( foo('Now you will see')); assert('foo(\'both of us.\')');
Dada la intención de afirmar, esto es un error, y uno de larga data, ya que ha estado en el lenguaje desde que se introdujo aseverar en PHP 4.
Las cadenas pasadas para afirmar se evalúan, con todas las implicaciones de rendimiento y los peligros que vienen con eso, pero es la única forma de hacer que las declaraciones de aserción funcionen como deberían en PHP (este comportamiento es obsoleto en PHP 7.2).
EDITAR: Cambiado arriba para notar cambios en PHP 7 y 7.2
fuente
zend.assertions
configuración ini para apagar completamenteassert()
.Assert solo debe usarse en desarrollo, ya que es útil para depurar. Entonces, si lo desea, puede usarlos para desarrollar su sitio web, pero debe usar excepciones para un sitio web activo.
fuente
No, su compañero de trabajo no debería usarlo como un controlador de errores de propósito general. Según el manual:
Si está familiarizado con los conjuntos de pruebas automatizados, el verbo "afirmar" se usa generalmente para verificar el resultado de algún método o función. Por ejemplo:
function add($a, $b) { return $a + $b; } assert(add(2,2) == 5, 'Two and two is four, dummy!'); assert(is_numeric(add(2,2)), 'Output of this function to only return numeric values.');
Su compañero de trabajo no debería usarlo como un controlador de errores de propósito general y, en este caso, como una verificación de entrada. Parece que es posible que algún usuario de su biblioteca no configure el campo de registros.
fuente
Su compañero de trabajo realmente está intentando aplicar el diseño por contrato (DbC) del lenguaje Eiffel y basado en el libro: Construcción de software orientado a objetos, 2da edición.
La aserción, tal como la usó, sería la {P} -parte de la lógica de Hoare o el triple de Hoare: {P} C {Q}, donde {P} es la precondición (ion) sy {Q} son las afirmaciones posteriores a la condición.
Tomaría nota crítica de los consejos dados sobre la función de aserción en PHP que tiene errores. No quieres usar código con errores. Lo que realmente quiere es que los creadores de PHP corrijan el error en la aserción. Hasta que lo hagan, puede utilizar la aserción, pero utilícela teniendo en cuenta su actual estado defectuoso.
Además, si la función de aserción tiene errores, le sugiero que no la use en el código de producción. Sin embargo, le recomiendo que lo use en el desarrollo y en el código de prueba cuando sea apropiado.
Finalmente, si realiza un estudio de diseño por contrato, encontrará que el uso de aserciones booleanas a la luz de la herencia clásica orientada a objetos tiene consecuencias, es decir, nunca debe debilitar una condición previa ni debilitar una condición posterior. Hacerlo podría ser peligroso para los objetos descendientes polimórficos que interactúan entre sí. Hasta que comprenda lo que eso significa, ¡lo dejaría en paz!
Además, recomiendo encarecidamente que los creadores de PHP realicen un estudio completo del diseño por contrato e intenten ponerlo en PHP lo antes posible. Entonces, todos podemos beneficiarnos de tener un compilador / intérprete compatible con DbC, que manejaría los problemas señalados en las respuestas (arriba):
NOTA: Incluso el uso de una
if
declaración -como sustituto de la aserción (condición previa) sufrirá consecuencias nefastas si se usa para fortalecer una condición previa o debilitar una condición posterior. Para comprender lo que eso significa, ¡necesitará estudiar diseño por contrato para saberlo! :-)Feliz estudiando y aprendiendo.
fuente