Pregunta

Los errores que ocurren en lo profundo de una capa de acceso a datos o incluso en niveles superiores (por ejemplo, dentro de las operaciones de ADO.net) rara vez tienen mucho sentido para un usuario final.Simplemente publicar estos errores en una interfaz de usuario y mostrarlos generalmente no logrará nada más que frustración para el usuario final.

Recientemente he empleado una técnica básica para informar errores como este mediante la cual capto el error y al menos agrego un texto fácil de usar para que al menos el usuario final entienda qué falló.

Para hacer esto, detecto una excepción dentro de cada función específica (digamos, por ejemplo, una función de recuperación en una capa de acceso a datos), luego genero un nuevo error con un texto fácil de usar sobre la función que falló y probablemente la causa, pero luego incrusto el original. excepción en la nueva excepción como la "excepción interna" de esa nueva excepción.

Luego, esto puede ocurrir en cada capa si es necesario, cada consumidor de la función de nivel inferior agrega su propio contexto al mensaje de error, de modo que lo que llega a la interfaz de usuario es un mensaje de error cada vez más fácil de usar.

Una vez que el error llega a la interfaz de usuario (si es necesario), puede iterar a través de las excepciones anidadas para mostrar un mensaje de error que primero le indica al usuario qué operación falló, pero también proporciona un poco de información técnica sobre lo que realmente salió mal.

p.ej.

"No se pudo mostrar la lista de nombres de clientes que solicitó".

"Obtener la lista de clientes que solicitó falló debido a un error con la base de datos".

"Hubo un error que se conectaba a la base de datos al recuperar una lista de clientes"

"Error de inicio de sesión para el usuario xx"

Mi pregunta es esta:¿Es esto terriblemente ineficiente (todas esas excepciones anidadas)?Sospecho que no es una buena práctica, entonces, ¿qué debería hacer para lograr lo mismo o, de hecho, debería intentar lograr algo mejor?

¿Fue útil?

Solución

Es un poco horrible.

Si le muestra un error al usuario final, se supone que el usuario puede actuar al respecto.En "La lista de nombres de clientes que su solicitado no se pudo mostrar". Caso, su usuario solo pensará "¿Y qué?" En todos estos casos, solo muestre un mensaje de "algo malo".Ni siquiera necesita detectar estas excepciones; cuando algo sale mal, deje que algún método global (como application_error) lo maneje y muestre un mensaje genérico.Cuando usted o su usuario puedan hacer algo con respecto al error, detectelo y hágalo o notifique al usuario.

Pero querrás registrar todos los errores que no manejes.

Por cierto, mostrar información sobre los errores que se producen puede generar vulnerabilidades de seguridad.Cuanto menos sepan los atacantes sobre su sistema, es menos probable que encuentren formas de piratearlo (recuerde esos mensajes como "Error de sintaxis en la declaración SQL:Seleccione * De usuarios donde nombre de usuario = 'a';base de datos drp;--'..." esperado:'soltar' en lugar de 'drp'.Ya no hacen sitios como estos).

Otros consejos

Es técnicamente costoso lanzar nuevas excepciones, sin embargo, no haré un gran debate al respecto, ya que "costoso" es relativo: si lanza 100 excepciones de este tipo por minuto, probablemente no verá el costo;Si lanza 1000 excepciones de este tipo por segundo, es muy posible que vea un impacto en el rendimiento (por lo tanto, no vale la pena discutirlo aquí; el rendimiento es su decisión).

Supongo que tengo que preguntar por qué se utiliza este enfoque.¿Es realmente cierto que puede agregar información de excepción significativa en cada nivel en el que se podría generar una excepción y, de ser así, también es cierto que la información será:

  • Algo que realmente desear para compartir con tu usuario?
  • Algo que su usuario podrá interpretar, comprender y usar?
  • ¿Escrito de tal manera que no interfiera con la reutilización posterior de componentes de bajo nivel, cuya utilidad podría no conocerse cuando se escribieron?

Le pregunto acerca de compartir información con su usuario porque, en su ejemplo, su pila artificial comienza informándole al usuario que hubo un problema de autenticación en la base de datos.Para un hacker potencial, esa es una buena información que expone algo sobre lo que estaba haciendo la operación.

En cuanto a devolver una pila de excepciones personalizada completa, no creo que sea algo que sea útil para la mayoría de los usuarios (honestos).Si tengo problemas para obtener una lista de nombres de clientes, por ejemplo, ¿me ayudará (como usuario) saber que hubo un problema al autenticarme con la base de datos?A menos que esté utilizando autenticación integrada y cada uno de sus usuarios tenga una cuenta y la capacidad de comunicarse con un administrador del sistema para averiguar por qué su cuenta carece de privilegios, probablemente no.

Primero comenzaría por decidir si realmente existe una diferencia semántica entre la excepción de Framework lanzada y el mensaje de excepción que le gustaría proporcionar al usuario.Si es así, continúe y utilice una excepción personalizada en el nivel más bajo ("error de inicio de sesión" en su ejemplo).Los pasos siguientes, hasta la presentación real de la excepción, realmente no requieren ninguna excepción personalizada.La excepción que le interesa ya se generó (el inicio de sesión falló): continuar empaquetando ese mensaje en cada nivel de la pila de llamadas no tiene otro propósito real que exponer su pila de llamadas a sus usuarios.Para esos pasos "intermedios", suponiendo que existan bloques try/catch, una estrategia simple de "registrar y lanzar" funcionaría bien.

En realidad, sin embargo, esta estrategia tiene otro defecto potencial:impone al desarrollador la responsabilidad de mantener el estándar de excepción personalizado que se ha implementado.Dado que no es posible conocer todas las permutaciones de la jerarquía de llamadas al escribir tipos de bajo nivel (es posible que sus "clientes" ni siquiera se hayan escrito todavía), parece poco probable que todos los desarrolladores, o incluso un desarrollador, recuerden ajustar y personalizar cualquier condición de error en cada bloque de código.

En lugar de trabajar de abajo hacia arriba, normalmente me preocupo por la visualización de las excepciones lanzadas lo más tarde posible en el proceso (es decir,lo más cerca posible de la "parte superior" de la pila de llamadas).Normalmente, no intento reemplazar ningún mensaje en las excepciones lanzadas en niveles bajos de mis aplicaciones, particularmente porque el uso de esos miembros de bajo nivel tiende a volverse más y más abstracto cuanto más profunda es la llamada.Tiendo a detectar y registrar excepciones en el nivel empresarial e inferior, luego me ocupo de mostrarlas de manera comprensible en el nivel de presentación.

Aquí hay un par de artículos decentes sobre las mejores prácticas en el manejo de excepciones:

http://www.codeproject.com/KB/architecture/exceptionbestpractices.aspx

http://aspalliance.com/1119

Dios, esto se volvió complicado... disculpas de antemano.

Sí, las excepciones son costosas, por lo que existe un costo involucrado en capturar y volver a lanzar o lanzar una excepción más útil.

¡Pero espera un minuto!Si el código del marco o la biblioteca que estás usando arroja una excepción, entonces las cosas ya se están despegando.¿Tiene requisitos no funcionales sobre la rapidez con la que se propaga un mensaje de error después de una excepción?Lo dudo.¿Es realmente un gran problema?Ha sucedido algo imprevisto y 'excepcional'.Lo principal es presentar información útil y sensata al usuario.

Creo que estás en el camino correcto con lo que estás haciendo.

Por supuesto que es terriblemente ineficiente.Pero en el momento en que ocurre una excepción que es lo suficientemente importante como para mostrársela al usuario final, eso no debería importarle.

Donde trabajo tenemos sólo unas pocas razones para detectar excepciones.Sólo lo hacemos cuando...

  1. Podemos hacer algo al respecto; por ejemplo, sabemos que esto puede suceder a veces y podemos rectificarlo en el código a medida que sucede (muy raro).

  2. Queremos saber qué sucede y dónde (luego simplemente volvemos a lanzar la excepción).

  3. Queremos agregar un mensaje amigable, en cuyo caso envolvemos la excepción original en una nueva excepción derivada de la excepción de la aplicación y le agregamos un mensaje amigable y luego dejamos que surja sin cambios desde ese punto.

En su ejemplo, probablemente solo mostraríamos "Se produjo un error de inicio de sesión". ANBD deja eso mientras registra el error real y proporciona un por qué para que el usuario profundice en la excepción si también quería.(Quizás un botón en el formulario de error).

  1. Queremos suprimir la excepción por completo y seguir adelante.No hace falta decir que solo hacemos esto para los tipos de excepción esperados y solo cuando no hay otra forma de detectar la condición que genera la excepción.

Generalmente, cuando se trata de excepciones, el rendimiento y la eficiencia son la menor de sus preocupaciones.Debería preocuparse más por hacer algo para ayudar al usuario a recuperarse del problema.Si hubo un problema al escribir un determinado registro en la base de datos, revierta los cambios o al menos descarte la información de la fila para que el usuario no la pierda.

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top