Nel codice critico, devono essere gestite eccezioni che descrivono una condizione senza senso?

3

Consideriamo il seguente codice C # come esempio:

    public static string GetCurentExecutableDirectory()
    {
        return System.IO.Path.GetFullPath(
            System.Reflection.Assembly.GetExecutingAssembly().GetName().CodeBase);
    }

Secondo la documentazione, System.Reflection.Assembly.GetExecutingAssembly().GetName().CodeBase non può generare eccezioni, quindi possiamo supporre che questa parte sia affidabile. Ma la parte System.IO.Path.GetFullPath può generare alcune eccezioni in base alla documentazione .

So che il codice funziona bene il 99,99% delle volte, ma se l'esecuzione è critica, sono un po 'confuso. Da un lato, non voglio andare in crash anche se in qualche modo System.Reflection.Assembly.GetExecutingAssembly().GetName().CodeBase restituisce qualcosa che forzerebbe System.IO.Path.GetFullPath ad aumentare un'eccezione. D'altra parte, non sono sicuro che controllare le cose che dovrebbero essere evidenti ha molto senso. (E dato che questa situazione di esempio non ha senso, la gestione è piuttosto delicata).

Quanto sopra è solo un esempio e la mia domanda dovrebbe essere considerata in senso generale

In poche parole

In una parte critica del codice, dovrebbero essere gestite eccezioni che descrivono una situazione che non ha senso?

    
posta Marsya Kaustentein 15.07.2016 - 00:29
fonte

3 risposte

4

Dal punto di vista della tua applicazione, fai vuoi "crash". Se si verifica un'eccezione "senza senso" (le tue parole). In modo controllato: tramite UnhandledExceptionFilter o toplevel catch(Exception) .

È anche l'opzione più semplice: non devi fare nulla qui. Lascia che l'eccezione si propaghi.

Dal commento:

The point is that the code should only crash if the error (whatever nonsense it may describe) compromises the entire code execution.

Ma sì. Dal punto di vista della funzione quella , se non puoi restituire una directory valida, intero catena di chiamata è compromessa. È compito del chiamante decidere se gestire il fallimento di (ad es.) GetCurentExecutableDirectory con garbo.

Per esempio (C # 6):

        // Example where the caller decides to handle it: /e.g. a "show exec dir operation"
        try
        {
            string execDir = GetCurentExecutableDirectory();
            Console.WriteLine($"Executable directory is: {execDir}");
        }
        catch(Exception ex) when (AppRules.IsNonCritical(ex))
        {
            Console.WriteLine("Sorry, couldn't determine the executable directory. (You may wish to inspect the logs for further details.)");
            Log(ex);
        }
        // Execution can continue / return normally here

        // ------------------
        // ------------------

        // Example where the caller decides *not* to handle it:
        string execDir = GetCurentExecutableDirectory();
        // Note, we really need this here, 
        // otherwise the rest of the code doesn't make sense ...

Noterai che al chiamante non interessa l'eccezione quale ha causato l'errore. L'operazione che ha cercato di eseguire è fallita, e il gioco è fatto. Registra l'eccezione per l'analisi possibile e riporta in un modo user / caller friendly.

C # 6 è bello in questo modo, in quanto puoi filtrare per es. NullReferenceException in il tuo IsNonCritical filtro se tu lo consideri come un bug. ( CSE non vengono catturati comunque oggigiorno.)

Nota a margine: Le eccezioni generiche stanno davvero male?

    
risposta data 15.07.2016 - 10:34
fonte
2

Definisci "critico".

Se il tuo software alimenta un pacemaker o Google.com, avvolgi il codice per rilevare le eccezioni e registrarle in dettaglio. E spero che qualcuno legga i log e tu risolva prontamente il problema.

Altrimenti, preferisco semplicemente andare in crash e lanciare un'eccezione. Registrare in modo silenzioso un errore fatale inatteso è inferiore in quanto verosimilmente verrà ignorato e l'utente si sentirà frustrato dal fatto che il loro comando, ad esempio Salva, sembra funzionare, ehi, non c'era alcun messaggio di errore, giusto? Ma ha davvero fallito e quel memorandum importante che pensavano di avere il controllo ortografico e il salvataggio è ancora pieno di errori di battitura che il boss vedrà.

Come nota Robert Harvey, racchiude l'intera app in un try / catch che fornisce un buon feedback all'utente, come "oops, abbiamo avuto un errore grave", quindi registra l'errore e l'arresto anomalo. Possono chiamare il supporto tecnico che può leggere la traccia dello stack, chiedere cosa è successo, ecc.

Come nota Eric Eidt, quando opportuno, strutturare il programma in modo che si blocchi solo per quell'utente, non tutti. E questa è davvero una decisione architetturale di alto livello.

    
risposta data 15.07.2016 - 01:48
fonte
2

"Gestione delle eccezioni". Due piccole parole ma che è più importante ? Direi che è il ultimo .

In a critical piece of code, should exceptions describing a situation which does not makes sense be handled?

Contro-domanda: se si verifica una situazione che "non ha senso", cosa puoi [codice r] fare su di esso?

  • Se la risposta è "qualcosa di utile", allora codifica in ogni modo un gestore di eccezioni, gestisci l'eccezione e poi permetti al codice chiamante di andare su come se nulla fosse successo .
  • Se, tuttavia, la risposta è "non molto", allora non prenderla; lascia che sia il chiamante del tuo codice a occuparsene. Se nulla lo gestisce, il programma si blocca e si brucia, grazie al gestore "globale" incorporato nel run-time che avvia il programma.
risposta data 18.07.2016 - 13:30
fonte

Leggi altre domande sui tag