Come implementare la gestione degli errori [chiuso]

11

Anche se ho programmato a livello professionale per alcuni anni, ancora non capisco perfettamente la gestione degli errori. Sebbene le mie applicazioni funzionino bene, la gestione degli errori non è implementata a livello professionale ed è un mix and match di una serie di tecniche.

Non c'è alcuna struttura dietro la gestione degli errori. Mi piacerebbe imparare e capire come è implementato a livello professionale. Questo è un settore in cui mi manca la conoscenza.

Quando dovrei usare delle eccezioni e quando dovrei restituire uno stato di successo, per essere controllato nel flusso logico? È corretto mescolare l'eccezione e restituire uno stato?

I codice in C # principalmente.

    
posta James Jeffery 09.09.2013 - 14:42
fonte

2 risposte

23
  1. Utilizza le eccezioni per cose eccezionali, le cose che non puoi ragionevolmente aspettarti di incontrare troppo spesso, cose che indicano che qualcosa va storto. Ad esempio, se la rete non funziona, è una cosa eccezionale per un server web. Se il database non è disponibile, significa che qualcosa non va. Se il file di configurazione è mancante, probabilmente significa che l'utente lo ha incasinato.

  2. Non utilizzare eccezioni per gestire codice errato. Per verificare la correttezza del codice, è necessario utilizzare le asserzioni o, in .NET Framework 4 e versioni successive, i contratti di codice (che sostituiscono le asserzioni e hanno caratteristiche aggiuntive particolarmente preziose).

  3. Non utilizzare le eccezioni in casi non eccezionali. Il fatto che l'utente, quando è stato chiesto di inserire un numero, abbia inserito "cane" non è così eccezionale da meritare un'eccezione.

  4. Fai attenzione quando scegli i tipi di eccezioni. Crea i tuoi tipi quando necessario. Scegli con cura l'eredità, tenendo presente che i genitori che catturano cattureranno anche i bambini. Mai throw Exception .

  5. Non utilizzare i codici di ritorno per errori. I codici di errore sono facilmente mascherati, ignorati, dimenticati. Se c'è un errore, gestiscilo o propagalo nello stack superiore.

  6. Nei casi in cui è previsto che un metodo restituisca un errore e l'errore non sia eccezionale, utilizzare le enumerazioni, mai numeri di errore. Esempio:

    // Note that the operation fails pretty often, since it deals with the servers which are
    // frequently unavailable, and the ones which send garbage instead of the actual data.
    private LoadOperationResult LoadProductsFromWeb()
    {
        ...
    }
    

    Il significato di LoadOperationResult.ServerUnavailable , LoadOperationResult.ParsingError , ecc. è molto più esplicito di, ad esempio, ricordando che il codice 12 significa che il server è inattivo e il codice 13 che i dati non possono essere analizzati.

  7. Usa i codici di errore quando si riferiscono a quelli comuni, conosciuti da ogni sviluppatore che lavora nel dominio specifico. Ad esempio, non reinventare un valore enum per HTTP 404 Not Found o HTTP 500 Internal Server Error.

  8. Attenzione ai booleani. Prima o poi, vorrai sapere non solo se un metodo specifico è riuscito o meno, ma perché. Le eccezioni e le enumerazioni sono molto più potenti per questo.

  9. Non catturare tutte le eccezioni (a meno che tu non sia in cima alla pila). Se noti un'eccezione, dovresti essere pronto a gestirlo. La cattura di tutto sta dimostrando che non ti interessa se il tuo codice funziona correttamente. Questo potrebbe risolvere il problema "Non voglio cercare subito come risolvere questo problema", ma prima o poi ti farò male.

  10. In C #, mai rilanciare eccezioni come questa:

    catch (SomeException ex)
    {
        ...
        throw ex;
    }
    

    perché stai rompendo lo stack. Fatelo invece:

    catch (SomeException)
    {
        ...
        throw;
    }
    
  11. Fai uno sforzo durante la scrittura di messaggi di eccezione. Quante volte ho visto qualcosa come throw Exception("wrong data") o throw Exception("shouldn't call this method in this context") . Altri sviluppatori, incluso te stesso sei mesi dopo, non avrebbero idea di quali dati siano sbagliati e perché o perché non dovremmo chiamare qualche metodo in un contesto, né quale contesto preciso.

  12. Non mostrare messaggi di eccezione all'utente. Non sono previsti per le persone comuni e spesso sono illeggibili anche per gli sviluppatori stessi.

  13. Non localizzare messaggi di eccezione. Cercare la documentazione per un messaggio localizzato è estenuante e inutile: ogni messaggio dovrebbe essere solo in inglese e inglese.

  14. Non concentrarti esclusivamente su eccezioni ed errori: anche i log sono estremamente importanti.

  15. In .NET, non dimenticare di includere le eccezioni nella documentazione XML del metodo:

    /// <exception cref="MyException">Description of the exception</exception>
    

    Includere le eccezioni nella documentazione XML rende le cose molto più semplici per la persona che usa la libreria. Non c'è niente di più fastidioso di cercare di indovinare quale eccezione potrebbe essere generata da un metodo e perché.

    In questo senso¹, gestione delle eccezioni Java offre un approccio più rigoroso e migliore . Ti costringe a gestire le eccezioni potenzialmente generate dai metodi chiamati, o dichiara nel tuo metodo che può lanciare le eccezioni che non gestisci, rendendo le cose particolarmente trasparenti.

¹ Detto questo, trovo la distinzione Java tra eccezioni ed errori piuttosto inutile e confusa, dato che la lingua ha le eccezioni controllate e deselezionate. Fortunatamente, .NET Framework ha solo eccezioni e nessun errore.

    
risposta data 10.09.2013 - 20:41
fonte
1

Penso che la lista di MainMa sia completa. Aggiungerò solo alcuni dei miei:

  1. Leggi l' articolo di Eric Lippert su come classifica le eccezioni . Particolarmente importante è il suo punto di non cogliere eccezioni sono in realtà bug nel tuo codice. Risolvi il codice invece!
  2. Se sai che può verificarsi un'eccezione E puoi fare qualcosa a riguardo, gestiscilo, ma limita l'ambito del tuo tentativo di catturare e catturare il eccezione specifica che ti aspetti. Cioè, non farlo:
public void Foo() {
    try {
        //get input from use
        //do calculations
        //open file
    }
    catch (Exception ex) {
       //handle exception
    }
}

Invece fai questo:

public void Foo() {
    //get input from use
    //do calculations
    try {
        //open file
    }
    catch (FileOpenException ex) {
       //handle exception
    }
}
  • Non utilizzare le eccezioni per il controllo del flusso. Ad esempio, non lanciare ClientNotFoundException in una finestra di dialogo di ricerca (un client non trovato non è eccezionale in questa situazione) e si aspetta che il codice chiamante mostri un messaggio "Nessun risultato trovato" quando ciò accade.

  • Non ingoiare le eccezioni!

  • Ricorda che gestire veramente un'eccezione può significare solo 3 cose:

    1. Riprovare l'operazione. Valido solo se il problema è transitorio.
    2. Prova un'alternativa.
    3. Segnala a qualcuno il problema. Valido solo se la notifica è perseguibile, il che significa che l'utente può fare qualcosa al riguardo.

    Se nessuna di queste opzioni è applicabile, probabilmente non dovresti rilevare tale eccezione. È necessario registrarlo, quindi annullare l'operazione o arrestare. Ovviamente questo dipende da quali sono le tue esigenze in merito alla correttezza e alla robustezza.

risposta data 10.09.2013 - 16:50
fonte

Leggi altre domande sui tag