Come denominare un metodo che esegue un'attività e restituisce un valore booleano come stato?

33

Se esiste un metodo

bool DoStuff() {
    try {
        // doing stuff...
        return true;
    }
    catch (SomeSpecificException ex) {
        return false;
    }
}

dovrebbe invece essere chiamato IsStuffDone() ?

Entrambi i nomi potrebbero essere interpretati erroneamente dall'utente: Se il nome è DoStuff() perché restituisce un valore booleano? Se il nome è IsStuffDone() , non è chiaro se il metodo esegue un'attività o ne controlla solo il risultato.

Esiste una convenzione per questo caso? O un approccio alternativo, visto che questo è considerato difettoso? Ad esempio, in linguaggi con parametri di output, come C #, una variabile di stato booleana può essere passata al metodo come uno e il tipo di ritorno del metodo sarà void .

EDIT: nel mio particolare problema, la gestione delle eccezioni non può essere delegata direttamente al chiamante, perché il metodo è una parte di un'implementazione dell'interfaccia. Pertanto, al chiamante non può essere addebitato il trattamento di tutte le eccezioni di diverse implementazioni. Non ha familiarità con quelle eccezioni. Tuttavia, il chiamante può gestire un'eccezione personalizzata come StuffHasNotBeenDoneForSomeReasonException come suggerito nella risposta e commento di npinti .

    
posta Limbo Exile 11.06.2014 - 11:41
fonte

9 risposte

67

In .NET, spesso ci sono coppie di metodi in cui uno di loro potrebbe lanciare un'eccezione ( DoStuff ), l'altro restituisce uno stato booleano e, in caso di successo, il risultato effettivo tramite un parametro out ( TryDoStuff ).

(Microsoft lo chiama "Pattern di prova-analisi" , poiché forse il più importante Ad esempio, sono i metodi TryParse di vari tipi primitivi.)

Se il prefisso Try è raro nella tua lingua, probabilmente non dovresti usarlo.

    
risposta data 11.06.2014 - 12:03
fonte
18

Cosa succede se hai semplicemente lanciato l'eccezione al codice chiamante?

In questo modo si sta delegando la gestione delle eccezioni a chi usa il proprio codice. Che cosa succede se, in futuro, ti piacerebbe fare quanto segue:

  • Se non vengono generate eccezioni, prendi l'azione A
  • Se (per esempio) viene lanciato un FileNotFoundException , prendi l'azione B
  • Se viene lanciata un'altra eccezione, prendi l'azione C

Se si restituisce l'eccezione, la modifica sopra riportata semplicemente comporta l'aggiunta di un ulteriore blocco catch . Se lo lasci così com'è, dovresti cambiare il metodo e il luogo da cui viene chiamato il metodo, il quale, a seconda della complessità del progetto, può trovarsi in più posizioni.

    
risposta data 11.06.2014 - 11:47
fonte
7

DoStuff() è sufficiente e il valore restituito della funzione dovrebbe essere documentato, e non è necessario menzionarlo nel nome della funzione, cercando molte API disponibili:

PHP

// this method update and return the number affected rows 
// called update instead of updateAndGetAffectedCount
$affected = $query->update(/* values */);

C-Sharp

// Remove item from the List
// returns true if item is successfully removed; otherwise, false.
public bool Remove( T item )
    
risposta data 11.06.2014 - 14:18
fonte
6

In Java, la raccolta API definisce un metodo di aggiunta che restituisce un valore booleano. In pratica restituisce se l'aggiunta ha modificato la raccolta. Quindi per List di solito restituisce true, poiché l'elemento è stato aggiunto, mentre per Set potrebbe restituire false, se l'elemento era già lì, poiché Set s consente ogni elemento unico al massimo una volta.

Detto questo, se aggiungi un elemento non consentito dalla raccolta, ad esempio un valore nullo, l'add genererà un NullPointerException anziché restituire false.

Quando si applica la stessa logica al caso, perché è necessario restituire un valore booleano? Se si tratta di nascondere un'eccezione, non farlo. Basta lanciare l'eccezione. In questo modo puoi vedere cosa è andato storto. Se hai bisogno di un valore booleano, perché potrebbe non essere stato eseguito, per qualche altro motivo oltre a un'eccezione, dai un nome al metodo DoStuff() , poiché ciò rappresenta il comportamento. Funziona.

    
risposta data 11.06.2014 - 11:59
fonte
1

Potrebbero fallire per motivi diversi, eccezione, condizioni normali, quindi userei questo:

boolean doStuff() - returns true when successful

Importante è documentare cosa significa il booleano.

    
risposta data 11.06.2014 - 23:41
fonte
1

Di solito ho metodi che restituiscono un OperationResult (o OperationResult<T> ) e impostiamo la proprietà IsSuccess su OperationResult appropriatamente. Se il metodo "solito" è vuoto, restituisce OperationResult , se il metodo "solito" restituisce un oggetto, quindi restituisce OperationResult<T> e imposta la proprietà Item su OperationResult in modo appropriato. Suggerirei anche di avere metodi su OperationResult come .Failed(string reason) e .Succeeded(T item) . OperationResult diventa rapidamente un tipo familiare nei tuoi sistemi e gli sviluppatori imparano a gestirli.

    
risposta data 12.06.2014 - 15:37
fonte
0

Dipende molto dalla lingua che stai usando. Come per alcune lingue ci sono convenzioni e protocolli che in realtà non esistono in molte lingue o affatto.

Ad esempio, nel linguaggio Objective-C e i nomi dei metodi di iOS / Mac OS X SDK solitamente si va sulla falsariga di:

- (returndatatype) viewDidLoad {
- (returndatatype) isVisible {
- (returndatatype) appendMessage:datatype variablename with:datatype variablename {

Come puoi vedere, c'è un metodo chiamato viewDidLoad. Preferisco usare questo tipo di denominazione ogni volta che creo le mie applicazioni. Questo potrebbe essere usato per verificare se qualcosa doveva accadere come hai detto tu. Credo che tu stia pensando troppo a quello che è il nome dei tuoi metodi. La maggior parte dei metodi restituisce lo stato di ciò che essi fanno a prescindere, ad esempio:

In PHP, mysql_connect () restituirà false se la connessione fallisce. Non dice che lo farà, ma lo fa e la documentazione dice che fa così non può essere male interpretato dal programmatore.

    
risposta data 11.06.2014 - 21:14
fonte
0

Vorrei suggerire di utilizzare il prefisso "Prova". Questo è un modello ben noto per situazioni in cui il metodo può avere successo o meno. Questo modello di denominazione è stato utilizzato da Microsoft in .NET Framework (ad esempio, TryParseInt).

Ma forse non si tratta di nominare. Riguarda come si progettano i parametri di input / output del metodo.

La mia idea è che se un metodo ha un valore di ritorno, allora lo scopo di chiamare quel metodo dovrebbe essere quello di ottenere quel valore di ritorno. Pertanto, dovresti evitare di utilizzare il tipo restituito per indicare lo stato di un'operazione.

In C #, preferisco usare un parametro out. Usando un out sto marcando il parametro come parametro laterale. In particolare, C # 6 supporterà la dichiarazione delle variabili inline.

DoStuff(out var isStuffDone); // The out parameter name clearly states its purpose.
DoStuff(out var _); // I use _ for naming parameters that I am ignoring.
    
risposta data 12.06.2014 - 02:18
fonte
0

Prenderò un nome basato sul ruolo principale del metodo. Il fatto che quel metodo restituisca il valore booleano non impone il prefisso 'Is'. Diamo un po 'di codice Java, che usa il prefisso' Is 'abbastanza estensivo. Dai un'occhiata a java.io.File.delete() . Restituisce boolean , ma non è chiamato isFileDeleted() . Il motivo è che il ruolo principale del metodo è quello di eliminare un file. Qualcuno chiama questo metodo con l'intenzione di eliminare un file.

Il booleano è lì solo per restituire il risultato del lavoro. D'altra parte vediamo java.util.Map.isEmpty() . Ovviamente, chiami un tale metodo per scoprire se la collezione è vuota. Non vuoi fare niente. Vuoi solo scoprire qual è lo stato attuale.

Quindi personalmente, sarei sicuramente d'accordo con DoStuff() .

Questo è in qualche modo un aspetto molto importante per me. Molte volte quando mantengo il codice legacy, mi imbatto in qualcosa che chiamo personalmente "metodo menzognero". Il nome suggerisce l'azione A, ma il corpo fa l'azione B. L'esempio più bizzarro è un metodo getter che modifica i dati nel database.

    
risposta data 12.06.2014 - 12:42
fonte

Leggi altre domande sui tag