2009-06-10 18 views
5

Me gustaría obtener una segunda opinión sobre cómo manejar excepciones dentro de "eventos" (entrada de clave, actualización de pantalla, etc.). En este caso, tengo control sobre el evento-emisor.Manejo de excepciones Java dentro de "eventos"

Así que un módulo está configurado para manejar un evento (que implementa una interfaz de escucha, y se ha registrado en contra de un emisor del evento):

public void DefaultSet (CardData oldDefault, CardData newDefault) 
{ 
} 

El emisor del evento es simplemente:

 for (Enumeration e = listeners.elements(); e.hasMoreElements();) 
     { 
      RetrieverListener thisListener = (RetrieverListener) e.nextElement(); 
      thisListener.DefaultSet(oldDefault, newDefault); 
     } 

Así si/cuando algo sale mal en el receptor:

  • Debo tratar de hacer frente a la excepción del re, y nunca arrojar nada de nuevo al remitente? A veces los oyentes no tienen el "contexto" para manejar un error correctamente, ¿es así?

  • ¿Está mal visto lanzar una excepción a un módulo de envío de eventos, que se manejará de manera documentada? p.ej. "Lanzar una IOException dará como resultado un reinicio ...". Esto parece no estándar de los javadocs que he leído.

  • ¿Debo iniciar sesión e ignorar la excepción cuando algo va mal & no se puede hacer nada al respecto?

Respuesta

6

La convención de Java es que los métodos de escucha no arrojan excepciones. Obviamente, los errores de programación pueden hacer que un oyente arroje una RuntimeException, pero no hay manera de que el origen del evento se pueda recuperar de eso porque habrá dejado los objetos del programa en un estado desconocido, tal vez incoherente.

Depende, por lo tanto, que el oyente capte las excepciones marcadas y se recupere de ellas (por ejemplo, retrotrae una transacción) o las informe a algún otro objeto. A menudo utilizo una interfaz ManejadorError que se ve algo como:

public interface ErrorHandler { 
    public void errorOccurred(String whatIWasTryingToDo, Exception failure); 
} 

un detector de eventos cuenta su ManejadorError sobre los errores que se han producido.

public class SomeClass implements SomeKindOfListener 
    private final ErrorHandler errorHandler; 
    ... other fields ... 

    public SomeClass(ErrorHandler errorHandler, ... other parameters ...) { 
     this.errorHandler = errorHandler; 
     ... 
    } 

    public void listenerCallback(SomeEvent e) { 
     try { 
      ... do something that might fail ... 
     } 
     catch (SomeKindOfException e) { 
      errorHandler.errorOccurred("trying to wiggle the widget", e); 
     } 
    }   
} 

Me inicializar los detectores de eventos con una implementación de este que maneja el fracaso de cualquier manera tiene sentido en ese momento de la aplicación. Podría aparecer un cuadro de diálogo, mostrar un icono de error parpadeante en la barra de estado, registrar un mensaje de auditoría o abortar el proceso, por ejemplo.

+0

Arquitectura interesante y respuesta útil, gracias! Supongo que mi problema es que los oyentes no siempre están preparados para mostrar cosas o proporcionar comentarios al usuario, el uso de eventos realmente sesga la analogía de la pila descendente que hace que las Excepciones sean tan potentes (maneje la excepción en un punto apropiado en la pila , donde se puede hacer algo). De todos modos, creo que los oyentes tendrán que lidiar con el error, de una forma u otra. –

+0

Debe diseñar el sistema para que los oyentes puedan manejar el error. Una excepción desenrollará la pila nuevamente al oyente. El oyente ha sido invocado por algo que no puede saber cómo reaccionar a la excepción, por ejemplo, un botón llamado en el hilo de envío del evento Swing o el hilo de envío de mensajes de un proveedor JMS. Debe instanciar al oyente en un lugar y momento en el que puede darle todo el contexto que necesita para reaccionar a la excepción de una manera sensata. – Nat

1

Cuando no se pueda hacer nada al respecto, debe iniciar sesión y enviar un mensaje al usuario. Si algo sale mal y puede dañar los datos o dar resultados incorrectos si no puede recuperarlo, cierre la aplicación.

0

El enfoque habitual es ignorar el problema. Los oyentes no deben lanzar excepciones sin marcar.

Un mejor enfoque sería capturar y registrar RuntimeException s. Estos generalmente indican un error de programación. Si un widget en la pantalla arroja un NPE, entonces no hay ninguna razón por la cual el resto de la ventana no debería terminar de pintar. El usuario puede guardar sus datos y reiniciar o solucionar el problema. En el caso de Error s, generalmente significa que hay una situación grave, como OutOfMemeory, y la captura solo provocará una paliza. Nadie se molesta en hacer esto.

+0

"no hay ninguna razón por la cual el resto de la ventana no debe terminar de pintar": seguro que sí; el widget que falta podría ser muy importante, y el resto de la ventana podría ser inútil. De hecho, podría ser inútil y parece estar haciendo algo, lo cual es una experiencia de usuario peor que simplemente fallar. Si el programador no esperaba un estado en particular, debe suponer que el estado simplemente se ha roto. – cdhabecker