Domanda

Gli errori che si verificano in profondità in un livello di accesso ai dati o anche più in alto (ad esempio nelle operazioni di ADO.net) raramente hanno molto senso per un utente finale. Il semplice bubbling di questi errori fino a un'interfaccia utente e la loro visualizzazione di solito non produrranno nulla tranne la frustrazione per un utente finale.

Di recente ho utilizzato una tecnica di base per la segnalazione di errori come questa, per cui rilevo l'errore e almeno aggiungo del testo intuitivo in modo che almeno l'utente finale capisca cosa non è riuscito.

Per fare ciò sto rilevando un'eccezione all'interno di ciascuna funzione specifica (ad esempio una funzione di recupero in un livello di accesso ai dati), quindi sollevando un nuovo errore con un testo intuitivo sulla funzione che è fallita e probabilmente causa, ma poi incorporando l'eccezione originale nella nuova eccezione come "eccezione interna" di quella nuova eccezione.

Questo può quindi verificarsi su ogni livello, se necessario, ogni utente della funzione di livello inferiore aggiunge il proprio contesto al messaggio di errore, in modo che ciò che raggiunge l'interfaccia utente sia un messaggio di errore sempre più intuitivo.

Una volta che l'errore raggiunge l'interfaccia utente - se necessario - può quindi scorrere le eccezioni nidificate al fine di visualizzare un messaggio di errore che in primo luogo indica all'utente quale operazione non è riuscita, ma fornisce anche un po 'di informazioni tecniche su ciò che è effettivamente andato storto .

es.

  

" L'elenco dei nomi dei clienti è tuo   non è stato possibile visualizzare. "

     

" Ottenere l'elenco dei clienti   hai richiesto non riuscito a causa di un errore nel database. "

     

" Si è verificato un errore durante la connessione a   database quando si recupera un elenco di   clienti "

     

" Accesso non riuscito per l'utente xx "

La mia domanda è questa: è orribilmente inefficiente (tutte quelle eccezioni nidificate)? Sospetto che non sia la migliore pratica, quindi cosa dovrei fare per ottenere la stessa cosa - o dovrei effettivamente cercare di ottenere qualcosa di meglio?

È stato utile?

Soluzione

È solo un po 'orribile.

Se stai mostrando un errore all'utente finale, l'utente dovrebbe essere in grado di agire al riguardo. In " L'elenco dei nomi dei clienti che hai richiesto non è stato visualizzato. & Quot; caso, il tuo utente penserà semplicemente " quindi cosa? " In tutti questi casi, mostra semplicemente un messaggio "qualcosa è successo". Messaggio. Non hai nemmeno bisogno di cogliere queste eccezioni, quando qualcosa va storto, lascia che un metodo globale (come application_error) lo gestisca e mostri un messaggio generico. Quando tu o il tuo utente potete fare qualcosa per l'errore, rilevatelo e fate la cosa o avvisate l'utente.

Ma vorrai registrare ogni errore che non gestisci.

A proposito, la visualizzazione di informazioni sugli errori che si verificano può comportare vulnerabilità della sicurezza. Meno gli aggressori conoscono il tuo sistema, meno è probabile che troveranno modi per hackerarlo (ricorda quei messaggi come " Errore di sintassi nell'istruzione sql: Seleziona * Da utenti dove username = 'a'; database drp; - '. .. " previsto: "drop" anziché "drp". Non creano più siti come questi).

Altri suggerimenti

È tecnicamente costoso gettare nuove eccezioni, tuttavia non ne discuterò molto poiché "costoso" è relativo: se stai generando 100 di tali eccezioni al minuto, probabilmente non vedrai il costo; se stai lanciando 1000 di tali eccezioni al secondo, potresti benissimo vedere un colpo di prestazione (quindi, non vale la pena discutere qui - la prestazione è la tua chiamata).

Suppongo di dover chiedere perché questo approccio viene utilizzato. È vero che puoi aggiungere informazioni significative sulle eccezioni a ogni livello in cui potrebbe essere generata un'eccezione e, in tal caso, è anche vero che le informazioni saranno:

  • Qualcosa che in realtà vuoi condividere con il tuo utente?
  • Qualcosa che il tuo utente sarà in grado di interpretare, comprendere e utilizzare ?
  • Scritto in modo tale da non interferire con il successivo riutilizzo di componenti di basso livello, la cui utilità potrebbe non essere nota quando sono stati scritti?

Chiedo informazioni sulla condivisione delle informazioni con il tuo utente perché, nel tuo esempio, lo stack artificiale inizia informando l'utente che si è verificato un problema con l'autenticazione nel database. Per un potenziale hacker, questa è una buona informazione che espone qualcosa su ciò che l'operazione stava facendo.

Per quanto riguarda la restituzione di un intero stack di eccezioni personalizzato, non penso che sia qualcosa che sarà utile alla maggior parte degli utenti (onesti). Se ho problemi a ottenere un elenco di nomi di clienti, ad esempio, mi aiuterà (come utente) a sapere che si è verificato un problema con l'autenticazione con il database? A meno che tu non stia utilizzando l'autenticazione integrata e ciascuno dei tuoi utenti abbia un account e la possibilità di contattare un amministratore di sistema per scoprire perché il loro account non ha privilegi, probabilmente no.

Innanzitutto decido se esiste davvero una differenza semantica tra l'eccezione Framework generata e il messaggio di eccezione che desideri fornire all'utente. In tal caso, vai avanti e utilizza un'eccezione personalizzata al livello più basso ("accesso non riuscito" nel tuo esempio). I passaggi che seguono, fino alla presentazione effettiva dell'eccezione, non richiedono realmente eccezioni personalizzate. L'eccezione a cui sei interessato è già stata generata (l'accesso non è riuscito): continuare a racchiudere quel messaggio ad ogni livello dello stack di chiamate non ha altro scopo se non quello di esporre lo stack di chiamate ai tuoi utenti. Per quelli "medi" passaggi, supponendo che siano presenti eventuali blocchi try / catch, una semplice strategia di "log and throw" funzionerebbe correttamente.

In realtà, tuttavia, questa strategia ha un altro potenziale difetto: impone allo sviluppatore la responsabilità di mantenere lo standard di eccezione personalizzato che è stato implementato. Dato che non è possibile conoscere ogni permutazione della gerarchia di chiamate quando si scrivono tipi di basso livello (i loro "client" potrebbero non essere stati ancora scritti), sembra improbabile che tutti gli sviluppatori - o anche un solo sviluppatore - ricordino di concludere personalizzare qualsiasi condizione di errore in ogni blocco di codice.

Invece di lavorare dal basso verso l'alto, in genere mi preoccupo della visualizzazione delle eccezioni generate il più tardi possibile nel processo (vale a dire il più vicino possibile al "top" dello stack di chiamate). Normalmente, non provo a sostituire alcun messaggio in eccezioni generate a bassi livelli delle mie applicazioni, in particolare dal momento che l'utilizzo di quei membri di basso livello tende a diventare sempre più astratto quanto più profonda è la chiamata. Tendo a rilevare e registrare le eccezioni a livello aziendale e inferiore, quindi mi occupo di visualizzarle in modo comprensibile a livello di presentazione.

Ecco un paio di articoli decenti sulle migliori pratiche di gestione delle eccezioni:

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

http://aspalliance.com/1119

Accidenti, questo è diventato prolisso ... ci scusiamo in anticipo.

Sì, le eccezioni sono costose, quindi vi è un costo in termini di cattura, ri-lancio o lancio di un'eccezione più utile.

Ma aspetta un minuto! Se il codice framework o la libreria che stai utilizzando genera un'eccezione, le cose stanno già andando in blocco. Esistono requisiti non funzionali per la velocità di propagazione di un messaggio di errore a seguito di un'eccezione? Ne dubito. È davvero un grosso problema? È successo qualcosa di imprevisto ed "eccezionale". La cosa principale è presentare all'utente informazioni utili e sensate.

Penso che tu sia sulla strada giusta per quello che stai facendo.

Naturalmente è terribilmente inefficiente. Ma nel momento in cui si verifica un'eccezione che è abbastanza importante da mostrare all'utente finale, non dovresti preoccupartene.

Dove lavoro, abbiamo solo alcuni motivi per cogliere le eccezioni. Lo facciamo solo quando ...

  1. Possiamo fare qualcosa al riguardo - ad esempio, sappiamo che ciò può accadere a volte e possiamo correggerlo nel codice in tempo reale (molto raro).

  2. Vogliamo sapere che succede e dove (quindi ridisegniamo l'eccezione).

  3. Vogliamo aggiungere un messaggio descrittivo, nel qual caso racchiudiamo l'eccezione originale in una nuova eccezione derivata dall'eccezione dell'applicazione e aggiungiamo un messaggio descrittivo a quello e poi lasciamo rimbalzare invariato da quel punto.

Nel tuo esempio probabilmente visualizzeremmo " Errore di accesso. " anbd lo lascia a questo mentre registra il vero errore e fornisce un motivo per cui l'utente deve esaminare l'eccezione se lo desidera. (Forse un pulsante sul modulo di errore).

  1. Vogliamo eliminare completamente l'eccezione e continuare. Inutile dire che lo facciamo solo per i tipi di eccezione previsti e solo quando non c'è altro modo per rilevare la condizione che genera l'eccezione.

Generalmente quando si ha a che fare con eccezioni, prestazioni ed efficienza sono le preoccupazioni meno importanti. Dovresti essere più preoccupato di fare qualcosa per aiutare l'utente a riprendersi dal problema. Se si è verificato un problema durante la scrittura di un determinato record nel database, ripristinare le modifiche o almeno scaricare le informazioni sulla riga in modo che l'utente non le perda.

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top