Gestori multipli di un'eccezione e gestione delle eccezioni nell'interfaccia utente

6

Correlato a: Il gestore onError è migliore delle eccezioni?

Premessa

Sto scrivendo una parte del codice della libreria che esegue determinati compiti, per separare le preoccupazioni, abbiamo deciso che non dovremmo scrivere in un log o scrivere direttamente sul display, ma invece fornire un meccanismo di registrazione degli eventi che consenta l'ascolto del codice del client interessato agli eventi del suo ciclo di vita.

Fin qui tutto bene. Abbiamo un gestore di eventi per il registro e un gestore di eventi per la visualizzazione, vengono informati quando si verifica un evento e scrivono in modo indipendente sul log / display.

Quindi abbiamo finora (pseudo codice)

class MyLib(List<MYLibEventHandler> listeners) 

class Display implements MYLibEventHandler

class Log implements MYLibEventHandler

Domanda

La domanda sollevata era: come informare i clienti delle eccezioni? Un modo di guardarlo è che un'eccezione può essere vista come solo un altro evento. È qualcosa di esterno che accade e ai clienti interessa sapere quando accade.

Quindi possiamo semplicemente aggiungere un altro evento per le eccezioni che ricevono l'oggetto eccezione. (possiamo rilanciare l'eccezione per consentire a qualsiasi altro costrutto try / catch di gestirlo, ma il log / display non sono in realtà che gestiscono l'eccezione, sono appena stati avvisati che è successo così possono fare ciò che vogliono con esso. Non possono davvero recuperare da esso)

D'altra parte, ha un cattivo odore. Un'eccezione non è un evento normale, è un'interruzione nel flusso, quindi possiamo dire che il nostro "main" catturerà eventuali eccezioni e passerà esplicitamente alle istanze Display e Log , al di fuori del meccanismo di invio dell'evento.

Questo odora anche perché abbiamo già un elenco di listener, ma chiamiamo esplicitamente il log e il display per gestire l'eccezione.

(Forse non dovrei essere allarmato dal fatto che il codice stia facendo qualcosa di "eccezionale" quando consegna una "eccezione", ma sente ancora l'odore di dover tenere traccia dei client due volte)

Quindi sono bloccato con un odore di codice, non importa quello che scelgo.

Esiste un modello di progettazione per gestire più listener / gestori per la stessa eccezione? try catch è una struttura molto "single listener" / "hierarchical", non sembra lo strumento giusto per un ampio scenario di "distribuzione". Forse una sorta di pattern AOP?

Il mio tentativo di rispondere a questo è che se ho un server remoto, con più client, e il server deve comunicare che si è verificata un'eccezione del server, non ci sarebbe stata alcuna domanda dato che il client non può realmente "provare / catturare" l'eccezione. Sarà più probabile che venga inviato come evento (ad esempio in Akka come oggetto Try). Anche in RMI, l'eccezione viene inviata più come un "evento" e solo in seguito attiva un RemoteException localmente.

Esiste uno schema di progettazione conosciuto per gestire listener multipli, indipendenti e di sola lettura per un'eccezione (ad esempio, gli ascoltatori che non possono e non si ripristinano dall'eccezione, devono solo sapere che è successo)

Forse in questo caso, inviare l'eccezione come evento (e poi rilanciarlo) è la strada giusta da fare?

    
posta Eran Medan 15.07.2014 - 18:25
fonte

3 risposte

2

La gestione degli errori è per definizione disordinata. Stai praticamente cercando di gestire qualcosa che non dovrebbe essere accaduto in modo aggraziato.

I think the biggest thing that smells is that you are mixing concerns

Uno sviluppatore è interessato alla possibilità di ricreare una condizione di errore e impedire che ciò accada in futuro. Le tracce dello stack più vicino a dove si è verificato l'errore sono uno strumento molto utile a tale scopo.

Un utente è preoccupato che l'azione intrapresa sia riuscita o meno. Se non si preoccupano se c'è qualcosa che possono fare al riguardo. NOTA: ci sono più di un modo per gestirlo visivamente, ma la preoccupazione di fondo è la stessa.

Come regola generale, preferisco separare queste preoccupazioni e gestirle un po 'più appropriatamente per l'utente finale:

  • Se ottengo un'eccezione, registrala immediatamente. È utile per il debug.
  • Se l'eccezione impedisce che l'azione dell'utente abbia esito positivo, genera un evento per informare l'utente che il problema si è verificato con parole comprensibili dall'utente.

La linea di fondo è che gli utenti non vogliono vedere le tracce dello stack perché non li aiuta. Vogliono sapere se il motivo per cui i loro dati non sono stati inviati è perché hanno fatto qualcosa di sbagliato, o se hanno solo bisogno di riprovare più tardi. Ecco perché dovresti sempre adattare il messaggio che dai all'utente. Se è qualcosa di completamente inaspettato, è meglio fornire un modo per inviare dettagli di errore o fare riferimento a un ID che può essere trovato nei registri su un server piuttosto che mostrare un messaggio di eccezione non elaborato all'utente. Non possono davvero fare nulla con quello.

In conclusione: non confondere la gestione degli errori con la segnalazione degli errori. E la segnalazione degli errori dovrebbe essere adattata al pubblico appropriato.

    
risposta data 17.11.2017 - 14:57
fonte
1

Penso che i client non siano interessati all'innalzamento delle eccezioni, ma piuttosto alla gestione di tali eccezioni (un numero arbitrario di livelli sopra cui è stata generata l'eccezione). In alcuni casi non sono nemmeno interessati ad esso, ad esempio se è stato gestito da riprovare e quindi l'operazione è riuscita.

Una volta gestita un'eccezione, diventa normale come sempre e quindi penso che sia opportuno far conoscere ai clienti interessati attraverso il normale meccanismo di notifica.

Anche se un'eccezione non viene gestita fino a quando non raggiunge la tua funzione principale, dovrai fare qualcosa per evitare che il tuo programma venga terminato. Anche questo gestisce l'eccezione e, a mio avviso, giustifica una notifica regolare.

    
risposta data 18.08.2017 - 19:57
fonte
0

Se i client ascoltano il ciclo di vita della libreria, uno stato sensibile del ciclo di vita sarebbe uno stato "non riuscito", che si verifica quando la libreria presenta un'eccezione dalla quale non può verificarsi. Dovrebbero essere avvisati dal codice della biblioteca, non dalla funzione principale, per lo stesso motivo per cui la funzione principale non li notifica ad altri eventi.

Come ha detto @ Griffon26, se l'eccezione è stata gestita, potrebbe non essere necessario notificarli.

Ciò che ha più senso per me è non ripensare all'eccezione, ma qualsiasi chiamata alla libreria quando ha raggiunto lo stato di errore genererà immediatamente un'eccezione.

Includerei l'oggetto eccezione nella notifica se sei sicuro che la libreria verrà utilizzata solo internamente perché più informazioni puoi fornire e meglio è. Se è esterno allora come @Berin Loritsch ha detto che la notifica deve essere ripulita e non includere la traccia completa dello stack e l'oggetto eccezione.

    
risposta data 17.12.2017 - 17:33
fonte

Leggi altre domande sui tag