Svantaggi di un gestore di errori master?

4

Penso che potrei semplificare la mia vita facendo una classe di gestione delle eccezioni che posso solo spedire tutte le eccezioni e che gestirà in modo appropriato.

Idealmente:

def dostuff():
  try:
    dothis()
  except Exception e:
    Handler.handle(e)

Per evitare

def dostuff():
  try:
    dothis()
  except ValueError e:
    #handle ValueError
  except IndexError e:
    #handle IndexError

La classe Handler avrebbe tutta la logica per gestire l'eccezione in modo appropriato e potresti passare alcuni argomenti per specificare come gestire l'errore, ma ci sarebbero valori predefiniti ragionevoli per rendere la cosa facile.

Questa sembra una grande idea o una terribile. E 'possibile che trovo che manca l'utilità che sto cercando. Ma sento che potrebbero esserci alcuni seri inconvenienti che non vedo. Non penso di aver visto questo approccio spesso. C'è una ragione?

In questo momento sto lavorando in Python, ma penso che non sia una domanda specifica per la lingua.

    
posta dan08 22.12.2015 - 01:08
fonte

3 risposte

4

La mia congettura è che se senti il bisogno di un tale aiuto, probabilmente stai ricevendo troppe eccezioni in primo luogo. Quale azione utile puoi intraprendere su un'eccezione? O conosci la causa dell'errore dal contesto (ovvero, ti aspetti l'eccezione) e puoi fornire una ragionevole strategia di fallback, quindi il tuo gestore generico non sarà di aiuto. O non sai cosa fare con l'eccezione, quindi dovresti semplicemente lasciarlo sgonfiare fino a quando qualcuno alla fine sarà in grado di agire su di esso in modo ragionevole. Come ultima risorsa, potresti avere un gestore "catch all" nella tua funzione principale che dice "sorry", registra l'eccezione e termina il programma. Per molti errori imprevisti, questa è la reazione appropriata.

Python è un po 'diverso dalla maggior parte delle altre lingue che conosco, nel senso che ti incoraggia ad usare le eccezioni molto più come una forma di flusso di controllo ordinario, ma non vedo come ciò cambierebbe l'immagine complessiva. Proprio come non hai una funzione di supporto generica per gestire i valori di ritorno, probabilmente non vuoi un gestore di eccezioni generico.

Lascia che ti illustri con alcuni esempi.

Questo è un uso ragionevole del rilevamento di un'eccezione che non può essere automatizzata.

def get_foo_factor(fallback=10):
    try:
        return int(os.getenv('FOO_FACTOR'))
    except TypeError | ValueError:
        # Environment variable not set or not an integer.
        return fallback

Questo è completamente ridicolo.

def append_to_file(filename, message):
    try:
        with open(filename, 'a') as ostr:
            print(message, file=ostr)
    except TypeError:
        print("Not a string?", file=sys.stderr)
    except AttributeError:
        print("This should never happen!", file=sys.stderr)

Se il tuo codice ha un sacco di tali except cascate, il miglior refactoring potrebbe essere semplicemente cancellarle. Per quei pochi che rimangono, probabilmente troverai che il tuo gestore automatico non sarà di grande utilità. La lingua ha già una sintassi specializzata per rendere la gestione delle eccezioni il più comoda possibile, dopotutto.

L'unico caso d'uso per un gestore che riesco a vedere è se stai interagendo con una libreria che genera varie eccezioni e vuoi tradurle nel tuo schema. In questo caso, potrebbe essere appropriato qualcosa come il seguente:

def translate_libfoo_exception(exception):
    try:
        raise exception
    except FooErrorOne as e:
        return MyError(e)
    except FooErrorTwo as e:
        return MyOtherError(e)
    except FooErrorThree as e:
        return MyOtherError(e)
    except FooError as e:
        return MyGenericError(e)
    except Exception as e:
        return e

Potrebbe quindi essere usato in questo modo.

try:
    foo.bar()
except FooErrorThree:
    # Needs special handling
    pass
except Exception as e:
    # Cannot be handled, translate and re-raise
    raise translate_libfoo_exception(e)
    
risposta data 22.12.2015 - 04:17
fonte
6

Ciò che perdi è contesto. Stai passando l'oggetto di eccezione e , ma Handle.handle non ha idea se (per esempio) IndexError sia successo a un disinfettante di input, nel qual caso potrebbe innescare un qualche tipo di meccanismo difensivo; o se è accaduto in profondità in un algoritmo dopo la sanificazione, nel qual caso potrebbe segnalare un problema allo sviluppatore. Poiché non ha il contesto in cui è stata sollevata l'eccezione, Handle.handle non saprebbe quale azione intraprendere.

    
risposta data 22.12.2015 - 01:40
fonte
2

Un gestore di errori master è simile a una classe di dio , un modello anti nel design modulare.

D'altra parte, c'è un modello di progettazione denominato Error Handler che consente di centralizzare il controllo degli errori che sono lo stesso.

    
risposta data 25.12.2015 - 18:03
fonte

Leggi altre domande sui tag