Mejores prácticas para la gestión de excepciones en Java o C# [cerrado]

Resuelto AtariPete asked hace 15 años • 15 respuestas

Estoy atascado decidiendo cómo manejar las excepciones en mi aplicación.

Mucho si mis problemas con las excepciones provienen de 1) acceder a datos a través de un servicio remoto o 2) deserializar un objeto JSON. Lamentablemente, no puedo garantizar el éxito de ninguna de estas tareas (cortar la conexión de red, objeto JSON con formato incorrecto que está fuera de mi control).

Como resultado, si encuentro una excepción, simplemente la capto dentro de la función y devuelvo FALSE a la persona que llama. Mi lógica es que lo único que realmente le importa a la persona que llama es si la tarea fue exitosa, no por qué no fue exitosa.

Aquí hay un código de muestra (en JAVA) de un método típico)

public boolean doSomething(Object p_somthingToDoOn)
{
    boolean result = false;

    try{
        // if dirty object then clean
        doactualStuffOnObject(p_jsonObject);

        //assume success (no exception thrown)
        result = true;
    }
    catch(Exception Ex)
    {
        //don't care about exceptions
        Ex.printStackTrace();
    }
    return result;
}

Creo que este enfoque está bien, pero tengo mucha curiosidad por saber cuáles son las mejores prácticas para gestionar excepciones (¿realmente debería incluir una excepción en toda la pila de llamadas?).

En resumen de las preguntas clave:

  1. ¿Está bien simplemente detectar excepciones pero no generarlas ni notificarlas formalmente al sistema (ya sea a través de un registro o una notificación al usuario)?
  2. ¿Qué mejores prácticas existen para las excepciones que no hacen que todo requiera un bloque try/catch?

Seguimiento/Editar

Gracias por todos los comentarios. Encontré algunas fuentes excelentes sobre gestión de excepciones en línea:

  • Mejores prácticas para el manejo de excepciones | O'Reilly Medios
  • Mejores prácticas de manejo de excepciones en .NET
  • Mejores prácticas: gestión de excepciones (el artículo ahora apunta a la copia de archive.org)
  • Antipatrones de manejo de excepciones

Parece que la gestión de excepciones es una de esas cosas que varían según el contexto. Pero lo más importante es que se debe ser coherente en la forma en que se gestionan las excepciones dentro de un sistema.

Además, tenga cuidado con la descomposición del código debido a intentos/capturas excesivos o al no respetar una excepción (una excepción es advertir al sistema, ¿qué más se debe advertir?).

Además, este es un comentario bastante elegido de m3rLinEz .

Tiendo a estar de acuerdo con Anders Hejlsberg y usted en que a la mayoría de las personas que llaman sólo les importa si la operación es exitosa o no.

De este comentario surgen algunas preguntas en las que pensar cuando se trata de excepciones:

  • ¿Cuál es el punto de que se lance esta excepción?
  • ¿Cómo tiene sentido manejarlo?
  • ¿A la persona que llama realmente le importa la excepción o solo le importa si la llamada fue exitosa?
  • ¿Es elegante obligar a una persona que llama a gestionar una posible excepción?
  • ¿Estás siendo respetuoso con los idomos del idioma?
    • ¿Realmente necesitas devolver un indicador de éxito como booleano? Devolver booleano (o un int) es más una mentalidad de C que de Java (en Java solo manejarías la excepción).
    • Siga las construcciones de gestión de errores asociadas con el idioma :) !
AtariPete avatar Jan 04 '09 01:01 AtariPete
Aceptado

Me parece extraño que quieras detectar excepciones y convertirlas en códigos de error. ¿Por qué cree que la persona que llama preferiría códigos de error a excepciones cuando esta última es la opción predeterminada tanto en Java como en C#?

En cuanto a tus preguntas:

  1. Sólo debes detectar excepciones que realmente puedas manejar. En la mayoría de los casos, simplemente detectar excepciones no es lo correcto. Hay algunas excepciones (por ejemplo, registro y clasificación de excepciones entre subprocesos), pero incluso en esos casos generalmente debería volver a generar las excepciones.
  2. Definitivamente no deberías tener muchas declaraciones try/catch en tu código. Nuevamente, la idea es detectar solo excepciones que puedas manejar. Puede incluir un controlador de excepciones superior para convertir cualquier excepción no controlada en algo útil para el usuario final, pero de lo contrario no debe intentar detectar todas y cada una de las excepciones en todos los lugares posibles.
Brian Rasmussen avatar Jan 03 '2009 18:01 Brian Rasmussen

Esto depende de la aplicación y la situación. Si está creando un componente de biblioteca, debe generar excepciones, aunque deben ajustarse para que sean contextuales con su componente. Por ejemplo, si está creando una base de datos Xml y digamos que está utilizando el sistema de archivos para almacenar sus datos y está utilizando permisos del sistema de archivos para proteger los datos. No querrás generar una excepción FileIOAccessDenied ya que eso filtra tu implementación. En su lugar, envolvería la excepción y arrojaría un error de AccesoDenied. Esto es especialmente cierto si distribuye el componente a terceros.

En cuanto a si está bien aceptar excepciones. Eso depende de tu sistema. Si su aplicación puede manejar los casos de falla y no hay ningún beneficio en notificar al usuario por qué falló, entonces continúe, aunque le recomiendo encarecidamente que registre la falla. Siempre me ha resultado frustrante que me llamen para ayudar a solucionar un problema y descubrir que se estaban tragando la excepción (o reemplazándola y lanzando una nueva sin establecer la excepción interna).

En general utilizo las siguientes reglas:

  1. En mis componentes y bibliotecas solo detecto una excepción si tengo la intención de manejarla o hacer algo basado en ella. O si quiero proporcionar información contextual adicional en una excepción.
  2. Utilizo un try catch general en el punto de entrada de la aplicación, o en el nivel más alto posible. Si llega una excepción, simplemente la registro y dejo que falle. Lo ideal sería que las excepciones nunca llegaran aquí.

Encuentro que el siguiente código es un olor:

try
{
    //do something
}
catch(Exception)
{
   throw;
}

Un código como este no tiene sentido y no debe incluirse.

JoshBerke avatar Jan 03 '2009 18:01 JoshBerke

Me gustaría recomendar otra buena fuente sobre el tema. Es una entrevista con los inventores de C# y Java, Anders Hejlsberg y James Gosling respectivamente, sobre el tema de la excepción marcada de Java.

Fallos y excepciones

También hay excelentes recursos al final de la página.

Tiendo a estar de acuerdo con Anders Hejlsberg y usted en que a la mayoría de las personas que llaman sólo les importa si la operación es exitosa o no.

Bill Venners : Mencionó problemas de escalabilidad y control de versiones con respecto a las excepciones marcadas. ¿Podrías aclarar qué quieres decir con esas dos cuestiones?

Anders Hejlsberg : Empecemos con el control de versiones, porque allí los problemas son bastante fáciles de ver. Digamos que creo un método foo que declara que genera las excepciones A, B y C. En la versión dos de foo, quiero agregar un montón de funciones y ahora foo podría generar la excepción D. Es un cambio importante para mí agregue D a la cláusula throws de ese método, porque es casi seguro que la persona que llama a ese método no manejará esa excepción.

Agregar una nueva excepción a una cláusula throws en una nueva versión rompe el código del cliente. Es como agregar un método a una interfaz. Después de publicar una interfaz, a todos los efectos prácticos es inmutable, porque cualquier implementación de la misma puede tener los métodos que desea agregar en la próxima versión. Entonces tienes que crear una nueva interfaz. De manera similar, con las excepciones, tendría que crear un método completamente nuevo llamado foo2 que arroje más excepciones, o tendría que detectar la excepción D en el nuevo foo y transformar la D en A, B o C.

Bill Venners : ¿Pero no estás rompiendo su código en ese caso de todos modos, incluso en un lenguaje sin excepciones marcadas? Si la nueva versión de foo va a generar una nueva excepción que los clientes deberían pensar en manejar, ¿no se rompe su código simplemente por el hecho de que no esperaban esa excepción cuando escribieron el código?

Anders Hejlsberg : No, porque en muchos casos a la gente no le importa. No van a manejar ninguna de estas excepciones. Hay un controlador de excepciones de nivel inferior alrededor de su bucle de mensajes. Ese controlador simplemente abrirá un cuadro de diálogo que dirá qué salió mal y continuará. Los programadores protegen su código escribiendo try finalmente en todas partes, por lo que retrocederán correctamente si ocurre una excepción, pero en realidad no están interesados ​​en manejar las excepciones.

La cláusula throws, al menos tal como está implementada en Java, no necesariamente te obliga a manejar las excepciones, pero si no las manejas, te obliga a reconocer con precisión qué excepciones podrían pasar. Requiere que detectes las excepciones declaradas o las coloques en tu propia cláusula de lanzamiento. Para evitar este requisito, la gente hace cosas ridículas. Por ejemplo, decoran cada método con "lanza excepción". Eso anula completamente la función y acabas de hacer que el programador escriba más tonterías. Eso no ayuda a nadie.

EDITAR: Se agregaron más detalles sobre la conversación.

Gant avatar Jan 03 '2009 21:01 Gant