È buono lo stile Python per scrivere una funzione che non ha alcun effetto se non potenzialmente generare eccezioni?

5

A volte mi trovo a scrivere codice Python che assomiglia a questo:

def check_stuff(param):
    if condition1(param):
        return "condition1" # These might be enum values, etc., instead of strings
    if condition2(param):
        return "condition2"

def func(param):
    cs = check_stuff(param)
    if "condition1" == cs:
        raise Exception1(param)
    if "condition2" == cs:
        raise Exception2(param)      
    #...

Qui, il valore di ritorno di check_stuff viene usato solo per decidere quale eccezione sollevare. Immaginiamo che questo sia vero ogni volta che chiamo check_stuff , probabilmente perché lo chiamo solo una volta. Sarebbe meglio che lo stile aumentasse le eccezioni in check_stuff stesso?

def check_stuff2(param):
    if condition1(param):
        raise Exception1(param)
    if condition2(param):
        raise Exception2(param)

def func2(param):
    check_stuff(param)
    #...
    
posta kuzzooroo 02.03.2015 - 16:01
fonte

3 risposte

9

Sì, una funzione che solleva solo un'eccezione è OK.

Puoi facilmente avere funzioni come ensureWellFormed(email_address) o http_request.ensureUserLoggedIn() che generano eccezioni ben documentate. Questo codice di de-clutter e molti progetti di alto profilo, ad es. Django, usa questo stile qua e là.

Se si utilizza questo approccio, assicurarsi che gli oggetti di eccezione contengano dati di contesto sufficienti per comprendere e segnalare ciò che è accaduto in un gestore di eccezioni. 'L'utente non ha accesso all'URL richiesto' è praticamente inutile; 'L'utente joerandom non ha accesso a URL / foo / bar' è abbastanza utile.

No, una funzione senza parametri che funziona con lo stato globale è una cattiva idea. Il codice di esempio mostra le funzioni che controllano lo stato globale. Il riferimento allo stato globale implicitamente è solitamente una cattiva idea molto . Crea dipendenze difficili da rilevare. Se ti capita di alterare lo stato globale, soprattutto implicitamente, crea bug più strani e difficili da rilevare. Il codice che si riferisce allo stato globale è difficile da testare e difficile da refactoring. L'approccio dello stato globale può sembrare più facile ora, ma in un tempo leggermente più lungo morde dolorosamente. Nota come nei miei esempi sopra o un parametro viene passato ad una funzione per il controllo, o viene usata un'istanza dell'oggetto (che viene anche passata ad un metodo come parametro self ).

    
risposta data 02.03.2015 - 17:06
fonte
1

No, sarebbe peggio

  • Le funzioni dovrebbero dire quello che fanno. Con una buona denominazione, la tua funzione check_stuff indica cosa fa. Dovrebbe quindi essere chiamato per es. checkConditionsValid a seconda di ciò che effettivamente fa. Suppongo che la tua funzione func restituisca qualcosa o abbia qualche effetto collaterale nel caso in cui le condizioni lo siano. In caso contrario, che sarebbe un difetto di progettazione, non la funzione check_stuff .

  • Utilizza l'iniezione delle dipendenze. Invece di sollevare check_stuff basarsi su alcune variabili globali, passa le condizioni ad esso come argomenti. Non solo rende più facile ragionare il tuo codice, ma rende anche più leggibile.

risposta data 02.03.2015 - 16:28
fonte
1

Forse

Può funzionare per esternalizzare la logica di validazione fintanto che non è esternamente visibile e viene utilizzata per far rispettare le precondizioni.

Supponiamo che tu abbia un oggetto che opera su una connessione al database e che molte delle sue funzioni richiedono che la connessione sia impostata e inizializzata. Anziché controllare la connessione e lanciare in modo condizionale un'eccezione in ogni funzione, è necessario utilizzare una funzione che controlli la connessione che viene chiamata da ciascun metodo che utilizza la connessione prima che venga utilizzata. Questo realizza DRY e aiuta a garantire la coerenza.

Affinché funzioni correttamente, il metodo di convalida e lo stato che controlla dovrebbero essere privati dell'oggetto. Ciò impedisce ad altri oggetti (incluse le sottoclassi) di causare la violazione delle precondizioni.

    
risposta data 02.03.2015 - 16:46
fonte

Leggi altre domande sui tag