He visto esta pregunta pero tengo algunas preguntas más sobre el uso de la assert
palabra clave. Estaba debatiendo con otros codificadores sobre el uso assert
. Para este caso de uso, había un método que puede devolver nulo si se cumplen ciertos requisitos previos. El código que escribí llama al método, luego afirma que no devuelve nulo y continúa utilizando el objeto devuelto.
Ejemplo:
class CustomObject {
private Object object;
@Nullable
public Object getObject() {
return (object == null) ? generateObject() : object;
}
}
Ahora imagina que lo uso así:
public void useObject(CustomObject customObject) {
object = customObject.getObject();
assert object != null;
// Do stuff using object, which would throw a NPE if object is null.
}
Me dijeron que debería eliminar el assert
, que nunca deberían usarse en el código de producción, solo deberían usarse en las pruebas. ¿Es eso cierto?
-ea
o equivalente.Objects.requireNonNull
Java 8).Respuestas:
Úselo
Objects.requireNonNull(Object)
para eso.En su caso esto sería:
Esta función se realiza para los fines que mencionó, es decir, marque explícitamente lo que no debe ser nulo; También en producción. El gran beneficio es que se asegura de encontrar valores nulos justo donde no deberían aparecer en primer lugar. Tendrá menos problemas para depurar los problemas causados por valores nulos que se pasaron a un lugar donde no deberían estar.
Otro beneficio es la flexibilidad adicional con respecto a los cheques nulos en contraste con
assert
. Si bienassert
es una palabra clave para verificar un valor booleano,Objects.requireNonNull(Object)
es una función y, por lo tanto, puede integrarse en un código mucho más flexible y legible. P.ej:Tenga en cuenta que
Objects.requireNonNull(Object)
es exclusivamente para la verificación nula dondeassert
se generaliza.assert
tiene propósitos ligeramente diferentes a ese respecto, es decir, principalmente pruebas. Tiene que estar habilitado, para que pueda habilitarlo para las pruebas y deshabilitarlo para la producción. De todos modos, no lo use para el código de producción. Podría ralentizar la aplicación con validaciones innecesarias y complicadas destinadas a pruebas. Úselo para separar las comprobaciones de solo pruebas de las comprobaciones destinadas a la producción también.Consulte la documentación oficial para obtener más información
assert
.fuente
Lo más importante que debe recordar acerca de las afirmaciones es que se pueden deshabilitar, por lo que nunca suponga que se ejecutarán.
Por compatibilidad con versiones anteriores, la JVM deshabilita la validación de aserción de forma predeterminada. Deben habilitarse explícitamente utilizando el argumento de línea de comando -enableassertions o su abreviatura -ea:
Por lo tanto, no es una buena práctica confiar en ellos.
Como las aserciones no están habilitadas por defecto, nunca puede asumir que se ejecutarán cuando se usen en el código. Por lo tanto, siempre debe verificar los valores nulos y los opcionales vacíos, evite usar aserciones para verificar las entradas en un método público y, en su lugar, use una excepción no verificada ... En general, haga todas las verificaciones como si la aserción no estuviera allí.
fuente
Seguramente lo que te dicen es una mentira descarada. Este es el por qué.
Las aserciones están deshabilitadas de manera predeterminada si solo ejecuta jvm independiente. Cuando están deshabilitados, tienen cero huella, por lo tanto, no afectarán su aplicación de producción. Sin embargo, probablemente sean sus mejores amigos cuando desarrollen y prueben su código, y la mayoría de los corredores de framework de prueba habilitan aserciones (JUnit lo hace), por lo que su código de aserción se ejecuta cuando ejecuta sus pruebas unitarias, lo que lo ayuda a detectar cualquier error potencial antes (por ejemplo, puede agregar afirmaciones para algunas comprobaciones de límites de lógica empresarial, y eso ayudará a detectar algún código que use valores inapropiados).
Dicho esto, como sugiere la otra respuesta, exactamente por esa razón (no siempre están habilitados) no puede confiar en las afirmaciones para hacer algunas comprobaciones vitales, o (¡especialmente!) Mantener cualquier estado.
Para ver un ejemplo interesante de cómo podría usar afirmaciones, eche un vistazo aquí : al final del archivo hay un método
singleThreadedAccess()
que se llama desde la declaración de aserción en la línea 201 y está allí para detectar cualquier acceso multiproceso potencial en las pruebas.fuente
Las otras respuestas ya cubren esto bastante bien, pero hay otras opciones.
Por ejemplo, Spring tiene un método estático:
org.springframework.util.Assert.notNull(obj)
También hay otras bibliotecas con sus propios
Assert.something()
métodos. También es bastante simple escribir el tuyo.Sin embargo, tenga en cuenta qué excepciones lanza si se trata de un servicio web. El método anterior mencionado, por ejemplo, arroja un
IllegalArgumentException
que por defecto en Spring devuelve un 500.En el caso de un servicio web, esto a menudo no es un error interno del servidor, y no debe ser un 500, sino un 400, que es una mala solicitud.
fuente
assert
es obtener un bloqueo inmediato con un archivo central producido para que pueda realizar una autopsia con su depurador favorito justo en el lugar donde se violó la condición.assert
lanzar. Interesante. La versión C / C ++ no hace tal cosa. Inmediatamente genera una señal de que a) mata el proceso yb) crea un volcado de núcleo. Lo hace por una razón: es muy simple depurar una falla de aserción porque todavía tiene toda la información disponible sobre la pila de llamadas. La definiciónassert
de lanzar una excepción en su lugar, que luego puede ser atrapada (no) intencionalmente mediante programación, derrota el propósito, en mi humilde opinión.Throwable
. Siempre pueden ser atrapados. Si eso es bueno o no, no lo sé. Supongo que depende. Muchos programas Java son servicios web, y sería indeseable que se bloquee por casi cualquier motivo, por lo que casi todo se captura y se registra. Una de las mejores cosas es el seguimiento de la pila, y eso suele ser suficiente para diagnosticar el motivo de una excepción o error por sí mismo.El uso afirma libremente cuando hacerlo ayuda a detectar errores de programación, es decir, errores.
No use asir para atrapar algo que podría suceder lógicamente, es decir, una entrada mal formateada. Use afirmar solo cuando el error sea irrecuperable.
No coloque ninguna lógica de producción en el código que se ejecuta cuando se verifica la aserción. Si su software está bien escrito, esto es trivialmente cierto, pero si no es así, podría tener efectos secundarios sutiles y un comportamiento general diferente con afirmaciones habilitadas y deshabilitadas.
Si su empresa tiene "código de prueba" y "código de producción" haciendo lo mismo pero como diferentes bases de código (o diferentes etapas de edición), salga de allí y nunca regrese. Intentar arreglar ese nivel de incompetencia es probablemente una pérdida de tiempo. Si su empresa no pone ninguna declaración de afirmación fuera del código de las pruebas, dígales amablemente que las afirmaciones están deshabilitadas en la compilación de producción y que si no lo están, corregir su error es ahora su primera prioridad.
El valor de las afirmaciones debe usarse precisamente dentro de la lógica empresarial y no solo en el conjunto de pruebas. Esto facilita la producción de muchas pruebas de alto nivel que no tienen que probar explícitamente muchas cosas para pasar por grandes fragmentos de su código y desencadenar todas estas afirmaciones. En algunos de mis proyectos, las pruebas típicas ni siquiera afirmaron nada, simplemente ordenaron que se realizara un cálculo basado en datos específicos y esto provocó que se verificaran cientos de afirmaciones y se encontraran problemas incluso en pequeñas piezas de lógica en el fondo.
fuente
Puede usar afirmar en cualquier momento. El debate que viene es cuándo usar. Por ejemplo en la guía :
fuente