Estoy un poco en desacuerdo con un desarrollador más experimentado en este tema, y me pregunto qué piensan los demás al respecto; nuestro entorno es Java, EJB 3, servicios, etc.
El código que escribí llama a un servicio para obtener cosas y crear cosas. El problema con el que me encontré fue que obtuve excepciones de puntero nulo que no tenían sentido. Por ejemplo, cuando le pido al servicio que cree un objeto, me devuelve el valor nulo; cuando intento buscar un objeto con una identificación válida conocida, me devuelve el valor nulo. Pasé algún tiempo tratando de descubrir qué estaba mal en mi código; Como tengo menos experiencia, por lo general asumo que he hecho algo mal, pero resulta que la razón de los retornos nulos fue la seguridad. Si el usuario principal que usa mi servicio no tenía los permisos correctos para el servicio de destino, entonces simplemente devuelve nulo. La mayoría de los otros servicios aquí tampoco están bien documentados, por lo que aparentemente esto es algo que debe saber.
Esto es bastante confuso como un desarrollador que escribe código que interactúa con el servicio. Tendría mucho más sentido para mí si el servicio fuera una excepción que me dijera que el usuario no tenía los permisos adecuados para cargar esta cosa o crearla; Entonces sabría de inmediato por qué mi servicio no funcionaba como se esperaba.
El desarrollador más experimentado que escribió el servicio argumentó que pedir los datos no es una condición de error, y que las excepciones solo deben generarse en una condición de error, no cuando el usuario no tiene acceso a los datos. Estos datos a menudo se buscan en una GUI, y para aquellos usuarios sin los permisos correctos, estas cosas simplemente "no existen". En resumen: preguntar no está mal, por lo tanto, no hay excepción. Obtener métodos devuelve nulo porque para esos usuarios esas cosas "no existen". Los métodos de creación devuelven nulo cuando al usuario no se le permitió crear esa cosa.
¿Es esto normal y / o buena práctica? Prefiero usar excepciones porque me resulta mucho más fácil saber qué está pasando. Entonces, por ejemplo, también preferiría lanzar una NotFoundException si solicitó un objeto con una ID no válida, en lugar de devolver nulo.
fuente
Respuestas:
Pedir algo puede no ser un error, pero no tener permisos para algo que solicitó es seguramente algún tipo de error. Las excepciones son una forma alternativa de informar condiciones excepcionales, que se utilizarán en lugar de valores de retorno especiales (como
null
, como usted escribió, no es de ninguna ayuda si hay> 1 posibles razones por las cuales las cosas podrían salir mal (incluso si hay exactamente 1 posible razón ahora, podría haber 2 posibles razones en la próxima versión, por lo que usarlonull
como un valor de retorno que indica una falla sería pintarlo en la esquina)). Si el servicio no informa de ninguna manera por qué no hará lo que pediste, entonces definitivamente es un mal diseño.Si se debe usar un valor de retorno especial (por ejemplo, los enteros negativos son útiles para funciones que normalmente devuelven un entero no negativo), una excepción, un controlador de error global o un registrador, etc., es un detalle de implementación al final. La elección depende del idioma, de la situación, de las convenciones, y también es una cuestión de gustos. El punto principal es que debería haber alguna forma directa de descubrir por qué algo no funciona. De lo contrario, su única opción es buscar basura con diferentes opciones y lo que sea para averiguar qué se correlaciona con el comportamiento de la caja negra, y es una pérdida de tiempo.
String.substring()
arroja unIndexOutOfBoundsException
si el índice está fuera de los límites. No puedo pensar en ninguna ventaja de regresarnull
, aunque, filosóficamente, se podría argumentar que aString
no contiene nada fuera de sus límites, pornull
lo que sería un valor de retorno lógico. Ser lógico-filosófico y ser práctico son obviamente dos animales diferentes.fuente
substring
devolver una referencia nula. En mi humilde opinión, debería haber dos funciones separadas, una de las cuales promete devolver el número solicitado de caracteres o lanzar una excepción, y una de las cuales devuelve tanto como sea posible. Cada método sería sustancialmente superior al otro en algunos contextos.Todo se reduce a lo que es el contrato. Si su contrato dice que puede solicitar algo que no existe, debe decir qué sucede (nulo u objeto nulo).
Por otro lado, si su contrato dice que primero debe llamar a un método diferente (
DoesSomethingExist()
) y luego llamar alGet
método, entonces su contrato podría decir que solo puede obtener cosas que existen y lanzar una excepción si no lo hacen. El mensaje de excepción podría decir algo como "Asegúrese de llamarDoesSomethingExist()
primero", que es un mensaje de error útil.fuente
findAllThings
método, entonces diría que es apropiado devolver una lista vacía o un subconjunto si hay algunas o todas las cosas que no puede ver. De la misma manera, en un blog solo puedo enumerar publicaciones para editar pertenecientes al usuario actual. Pero si ese usuario trató de modificar la URL y editar una publicación diferente ...No hay una única respuesta única para la pregunta. El uso de excepciones o devolver nulo depende de la situación.
En lugar de ver esto puramente desde un punto de vista dogmático, mira la interfaz como una interfaz de usuario . Las interfaces de usuario deben ser utilizables . Entonces, independientemente de sus propias opiniones sobre la forma "correcta" de hacer algo, elija el método que sea más útil desde la perspectiva de alguien que use su interfaz.
Si la persona que llama necesita saber por qué no se devuelve un objeto, es apropiada una excepción. Sin embargo, si el concepto general es "si no tiene permiso, no existe", el valor nulo es aceptable.
Específicamente en su caso, yo diría que los nulos son perfectamente aceptables para buscar un artículo si primero se requiere que la persona que llama inicie sesión o se conecte al servidor. Es entonces cuando le dirían que tiene o no tiene permiso. Una vez que pasa la puerta, es razonable que cuando busque algo que no tenga permiso para ver (o incluso sepa que existe), debería obtener un valor nulo.
Si, por otro lado, no tiene una conexión inicial o un paso de inicio de sesión, una excepción tiene sentido. Si la persona que llama sabe que existe un elemento y no lo está recuperando, la API no está siendo útil para devolver un valor nulo.
Sin embargo, para crear un artículo, esa es una historia diferente. Presumiblemente, podría haber muchas razones para que eso falle: sin permisos, parámetros incorrectos, servidor sin memoria, etc. Si al desarrollador se le da un valor nulo para todas esas condiciones, no tienen forma de determinar un curso de acción adecuado .
Entonces, para responder la pregunta, pregúntese cuál es la solución más útil desde la perspectiva de alguien que usa el servicio. Puede ser que la forma en que lo esté usando sea atípica, y para el caso más común, un nulo es la respuesta correcta.
Por lo tanto, no entre en una guerra religiosa por esto, decida qué es lo correcto para este problema en particular.
fuente
Definitivamente creo que es un mal diseño . El puntero nulo no es una respuesta válida para mí y puede ser difícil de manejar.
Si el usuario intenta conectar un servicio sin la credencial adecuada, debería responder con una respuesta clara y concisa. La respuesta podría ser una excepción o un objeto especial pero no nulo.
Debe dejar la respuesta nula cuando el enlace de red está roto u otro mal funcionamiento crítico inesperado.
Además, el tiempo que pasa entendiendo por qué obtuvo un valor nulo es un argumento fuerte. Cualquier código debe ser fácil de entender y usar. Tener un valor nulo no es el caso.
fuente
Teniendo en cuenta un buen diseño de software, debe pensar en la vida de su proyecto.
Al regresar
null
, como se ha dicho, usted no da ninguna información al cliente. Mira lo que te pasó, al principio no te diste cuenta de dónde estaba el problema. Además, si no se proporciona documentación, esto es un desastre.Al lanzar una excepción, puede saber qué salió mal. Incluso puede personalizar el texto que se muestra para que sea más específico si lo desea.
Por otro lado, al regresar
null
, hace que el cliente investigue lo que está sucediendo.Además, se dio cuenta de que había un problema porque llegó a otra parte a
NullPointerException
. Ahora imagine que no almacena el retorno de esa función ... Se verá obligado a rodear cada llamada a esa función con unif else
bloque ...Desde mi punto de vista, regresar
null
es una mala práctica.fuente
Desde mi punto de vista, esto no tiene sentido.
La consulta de datos sin permiso debería dar como resultado una excepción, porque es un resultado inesperado , para no obtener ningún resultado, sin el acceso adecuado.
Analogía : el código de respuesta para un
GET
sin autorización no es200 ok
sin datos, en realidad es401 Unauthorized
.fuente
Devolver nulo no es genial. No te dice nada. Para tomar su ejemplo, si una aplicación está tratando de buscar algo y la respuesta es nula para ambos problemas de seguridad y si el elemento no existe, entonces, ¿cómo puede saber la diferencia entre los dos?
Una respuesta significativa puede permitir que la aplicación tome decisiones lógicas sobre qué hacer a continuación o cómo resolver problemas.
fuente
Si la causa raíz es un usuario no autenticado, entonces prefiero una respuesta HTTP 401 dura, tal vez con una redirección a una página de mensajes bonitos (y una notificación a alguien a quien le importe). Las causas relacionadas con la autorización son más caso por caso; existen argumentos para devolver errores HTTP (403, por ejemplo) y argumentos para devolver códigos / mensajes especiales bien formados en la respuesta del servicio.
Las excepciones solo deben usarse en circunstancias excepcionales y significan que algo ha salido mal. No estoy de acuerdo en que deberían estar sobrecargados para significar "no permitido". (Lo mismo es cierto para el valor de retorno nulo: no estoy de acuerdo con que deba usarse para significar "no permitido").
fuente
Para hacer de abogado del diablo, intentaré ponerme del lado de volver nulo.
En mi opinión, solo hay una situación en la que este tipo de respuesta es casi aceptable y es, como en este caso, cuando se trata de la seguridad.
Es muy fácil regalar accidentalmente detalles de su sistema que las personas no autorizadas no deben conocer. Esto debe ser evitado.
Tome, por ejemplo, un verificador de nombre de usuario y contraseña. Devolver un error de "Nombre de usuario no encontrado" y un error de "Contraseña incorrecta" como códigos de error separados obviamente lo abriría a serios problemas de seguridad ya que alguien primero podría buscar un nombre de usuario válido y luego buscar una contraseña. Devolver un "nombre de usuario / contraseña no válido" genérico sería una mejor opción.
Por lo tanto, en este caso particular, yo diría que es casi bien para volver
null
pero estoy de acuerdo, sería muy desagradable para trabajar.fuente
null
es exactamente la respuesta menos útil. Casi cualquier otra cosa podría utilizarse para descubrir algo sobre el sistema. La razón por la que OP se quejó fue porque lanull
devolución no solo explicaba nada, sino que incluso no era útil. Ese es el objetivo deliberado ... no decir absolutamente nada y ser inútil. Misión cumplida en mi opinión.Creo que return null no es amigable, cuando el cliente invoca este método y devuelve null, el cliente no sabe qué sucedió y por qué regresó nulo. Por lo tanto, deberíamos lanzar la ejecución, que tiene sentido y proporcionar una documentación para describir esta ejecución.
fuente