Gestione dei tipi di eccezione in base all'attuale "livello" dell'applicazione

2

Immagina questo semplice caso di utilizzo dell'applicazione, ad esempio, per scaricare i dati da outisde dell'app. Questi passaggi rappresentano la "profondità" dei livelli, dall'alto verso il basso.

  1. Evento tocco interfaccia utente
  2. ViewModel gestisce detto evento
  3. Alcuni servizi / gestori reagiscono di conseguenza
  4. La richiesta corretta viene creata ed eseguita
  5. L'oggetto viene recuperato e riportato al massimo.

Questo è un semplice esempio per esprimere il mio punto di vista, non stiamo cercando di essere super-precisi qui.

Ciò che conta è: sto scavando nei livelli e si verifica un'eccezione.

Più alto sono nella pila, meglio conosco il contesto dell'errore. So che è successo quando ho premuto il pulsante "login" o il pulsante "download". Quindi penso di avere molte informazioni sul contesto.

Più profondo sono nello stack, più mi avvicino alla causa effettiva dell'eccezione. So esattamente perché è successo in questa fase. Ho molte informazioni sull'errore vero e proprio. Ma non voglio davvero mostrarlo così com'è all'utente (se rilevante).

(Nota: supponiamo che l'eccezione si sia verificata ai livelli 5 o 4, la domanda non è rilevante se si verifica nel livello dell'interfaccia utente).

Come regola generale, provo ad avere messaggi di errore molto specifici in base al contesto piuttosto che al messaggio di errore stesso; lo stesso tipo di eccezione potrebbe visualizzare molti messaggi diversi a seconda di dove proviene nell'interfaccia utente. Voglio più precisione mentre salgo nello stack.

La mia domanda è:

Quale eccezione oggetto / design dovrei usare? Sono confuso, dovrei avere eccezioni molto specifiche più approfondisco, perché conosco dettagli specifici? Oppure, d'altra parte, dovrei usare eccezioni molto ampie e trasformarlo mentre è preso dai livelli, perché capisco meglio il contesto mentre mi alzo?

Non riesco davvero a capire come sia possibile ottenere messaggi precisi / piacevoli senza che tonnellate di eccezioni specifiche stiano troppo a fondo nell'architettura. Correggetemi se ho torto, ma il mio Request non dovrebbe avere molti tipi di eccezioni rilevati, poiché la richiesta non è a conoscenza del contesto corrente; tuttavia ho bisogno di loro se voglio essere più preciso nel mio messaggio.

Ad esempio, probabilmente utilizzerò la stessa Request class per più chiamate diverse, quindi sarebbe RequestException o ServerException ; ma quando l'utente lo vive, potrebbe fare due cose molto diverse.

Ancora una volta, sto solo facendo degli esempi per l'esempio, ma un login e un recupero dei dati dovrebbero essere gestiti in modo completamente diverso, tuttavia, in fondo, potrebbero essere entrambi lo stesso ServerException , che è troppo ampio se voglio mostrare qualcosa di specifico per l'interfaccia utente

Non sono sicuro di come gestirlo, sembra complicato / confuso, eppure dovrebbe essere molto semplice dato che mi sembra di avere tutte le informazioni che dovrei avere. Cosa mi manca?

E, ancora più importante, come gestisci le eccezioni , di solito, quando saliti nello stack?

    
posta Gil Sand 28.07.2016 - 11:39
fonte

2 risposte

4

The higher I am in the stack, the better I know the context of the error. I know it happened when I hit the "login" button or the "download" button. So I'm thinking I have a lot of information on context.

The deeper I am in the stack, the closer I get to the actual cause of the exception. I know exactly why it happened at this stage. I have a lot of information about the actual error itself. But I don't really want to show it as is to the user (if relevant).

La via d'uscita da questo enigma è riconoscere che le eccezioni devono essere consumate dal software e non dai tuoi utenti finali.

Quando i livelli inferiori incontrano un problema, devono generare un'eccezione che contenga quante più informazioni sul problema effettivo disponibile in quel punto. Questa informazione è probabilmente completamente inutile per il tuo utente finale, ma sarà preziosa per i tuoi sviluppatori (se finisce in un file di registro).

Nel livello dell'interfaccia utente, dovresti catturare tutte le eccezioni e mostrare all'utente una finestra di dialogo di errore in base sia al contesto di ciò che l'utente sta facendo sia alle informazioni pertinenti contenute nell'eccezione.
L'eccezione stessa potrebbe essere registrata in un file di log, ma non dovrebbe certamente essere scaricata sul tuo utente finale.

    
risposta data 28.07.2016 - 14:24
fonte
3

UI touch event

ViewModel handles said event

Some service / manager reacts accordingly

The correct request is built and executed

The object is fetched and returned all the way up.

Dovresti concatenare le eccezioni.

Ogni blocco di eccezioni cattura le eccezioni catturate da quelle inferiori, dovrebbe spiegare il contesto in cui si è verificata l'eccezione e lanciarle a un livello più alto.

Quindi l'eccezione iniziale al livello più basso potrebbe essere qualcosa di simile a un servizio esterno non disponibile. Il codice che parla di questa API genera un'eccezione. Un'eccezione specifica che dice solo che l'API esterna non è raggiungibile.

Quell'eccezione viene catturata più in alto da ciò che iniziava la chiamata al servizio API esterno. Il blocco catch-throw genera la sua eccezione, ma all'interno di tale eccezione è l'eccezione originale.

Ancora più in alto il codice che ha dato il via all'azione che cattura e lancia ecc.

Ogni livello dovrebbe avere un catch-throw implementato, che cattura eccezioni da sotto, ma non fa nulla con loro se non per comprimerle nella propria eccezione e lanciare più in alto.

Finirai con un'eccezione che contiene tutte le altre eccezioni, qualcosa del genere (ad esempio stai reimplementando Google Translate)

TranslationError("Translation could not be completed")
  LanguageIdentificationError("Unable to determine the initial language")
    LanguageServiceError("The Language Service is unavailable")
      HTTPError("Call to service failed, error 500")

Alcuni dei quali nella parte superiore della tua applicazione, questa eccezione verrà catturata. Ora ovviamente non vuoi che questo venga mostrato all'utente. Un semplice messaggio "Translation failed" va bene.

Ma se ora accedi gli sviluppatori di questa catena di eccezioni mantengono e eseguono il debug del tuo sistema, ti daranno un grande abbraccio.

Possono guardare quella catena di eccezioni e puoi vedere cosa è successo, la traduzione fallita perché il sistema non è stato in grado di determinare la lingua della richiesta perché il servizio linguistico non è disponibile perché quando il sistema ha provato ad accedervi ne è stato restituito un 500.

Questo è molto meglio che ottenere un errore di HTTPError("Call to service failed, error 500") nella parte superiore del sistema e quindi dover calcolare la catena di eventi che portano a quella chiamata.

Ed è anche molto meglio che dover passare i contesti in ogni livello solo così l'eccezione di basso livello conosce il contesto di tutto il sistema di ciò che sta tentando di fare. L'eccezione HTTPError non dovrebbe mai dire qualcosa come "Chiamata al servizio fallita, errore 500, e stavi cercando di determinare la lingua del sistema usando il servizio di lingua"

    
risposta data 28.07.2016 - 17:42
fonte

Leggi altre domande sui tag