2015-01-28 9 views
7

Contesto: I percorsi Flask sono definiti per diversi endpoint API e ciascun endpoint chiama una classe controller con determinati parametri (uid, id_progetto, ecc.).È un buon modello per aumentare le eccezioni in un decoratore python?

@app.route('/sample/route', methods=['POST']) 
@require_json_payload 
@require_fields({ 
    'pid', 
    'params' 
}) 
def route_handler(arg1, arg2): 
    #input filtering 
    ... 

    try: 
     proj_cntr.sample_method(
      pid   = pid, 
      ...   = ... 
     ) 
    except ProjCntrException: 
     #handle error 

    #response generation 
    ... 

Il controller (proj_cntr) è responsabile per determinare, ad esempio, se la data del PID è valido, castrato dato utente è autorizzato a eseguire l'azione, e di altre convalida logica di business.

ho notato che sono c/incollando un sacco di codice come questo in diversi controller:

if not project_object: 
    sys_logger.info('...') 
    raise ProjCntrException('PID %d does not exist' % pid) 

Mettendo questi controlli (convalide) in decoratori sembra la cosa migliore da fare. Ma non sono sicuro quale modello di gestione degli errori sia la migliore pratica nel caso in cui la validazione non passi.

1) Devo creare eccezioni personalizzate specifiche (InvalidProjException, PermissionsException, ecc.) Per ogni decoratore da sollevare?

Preoccupazioni: il blocco catch del metodo del chiamante apparirà gonfio. Inoltre, è bene fare l'ipotesi che il chiamante sappia quali eccezioni sollevano i decoratori del callee?

2) Il decoratore passa un argomento di errore aggiuntivo al metodo e il metodo decide quale eccezione generare. In questo modo il metodo del chiamante è consapevole del tipo di eccezione da prevedere e gestire.

Preoccupazioni: L'approccio sembra un po 'eccessivo e disordinato.

Ci scusiamo per la domanda prolissa. Ogni pensiero/idea è molto apprezzato.

risposta

3

Ho finito per usare decoratori e lanciando eccezioni specifiche al loro interno.Ad esempio:

@validate_pid decoratore raises InvalidPidException() che vengono catturati nel blocco eccetto di qualsiasi consumatore che chiama il metodo decorato.

Vantaggi finora:

  • controllori sono molto più pulito e c'è molto meno replica codice.
  • Soluzione discretamente versatile, poiché utilizzo questi decoratori di "convalida della logica aziendale" su tutto il mio codice.

Svantaggi finora:

  • Il decoratore deduce alcuni parametri Keyname da passare quando il metodo viene chiamato decorato, ma alcuni di questi parametri non sono utilizzati all'interno del metodo stesso. Questo può portare ad alcuni strani parametri "penzolanti" nella firma del metodo.
  • Ho alcuni problemi di prestazioni minori. Ad esempio: il decoratore di validazione del progetto inizializza una sessione e carica un oggetto (Progetto) solo per essere nuovamente caricato nel metodo decorato stesso. Sembra solo un po 'janky.
0

Opzione 1: Sembra logico creare uno specifico Exception per il decoratore poiché ciò aiuterà l'utente a sapere quale eccezione viene sollevata, se presente, e perché. Il tipo di eccezione dovrebbe, ovviamente, apparire nella docstring del decoratore affinché il chiamante sia in grado di sapere cosa aspettarsi. In questo modo non stai facendo l'ipotesi che l'utente sappia quale eccezione viene sollevata ma che ha letto il documento - che è più probabile che sia l'ipotesi. Tuttavia, se il metodo viene chiamato spesso, il chiamante dovrà gestirlo ogni volta. Questo è parte dell'accordo quando si utilizza una libreria, un'API o il codice di qualcun altro.

Opzione 2: non appartiene all'utente per determinare quale eccezione verrà aumentata. L'utente dovrebbe esserne a conoscenza tramite la documentazione, ad esempio. È disordinato e contro-intuitivo in termini di design dell'API.

Pensando alla tua domanda mi ha fatto pensare al modo in cui funziona Java, soprattutto se si utilizza un IDE, quando si chiama un metodo si verrà avvisati - dall'IDE e tramite il meccanismo di battitura - che si dovrebbe try/catch un determinato tipo di eccezione.

Ma nel tuo caso non sarebbe possibile sollevare un opportuno HTTPException con un messaggio specifico?

+2

Sicuramente, ho finito per mettere quante più informazioni possibile nelle docstring di entrambi i decoratori e i metodi decorati. –

Problemi correlati