Cosa restituire se qualcosa non funziona, piuttosto che fare qualcosa di "casuale"? [duplicare]

10

Dire che riattivo un metodo per trovare la posizione di una stringa all'interno di una stringa. Quindi ottengo sia la posizione che è un numero intero, sia un "numero magico" come -1. Vedo questo pattern in così tanti linguaggi di programmazione, dove alcuni restituiscono un valore come null , alcuni restituiscono un valore casuale "fuori limite" come - ', alcuni generano un errore.

Esiste una "best practice" su questo o almeno qualcosa che è un po 'più esplicito in altri linguaggi di programmazione di cui non sono a conoscenza?

    
posta anemaria20 31.01.2017 - 14:17
fonte

6 risposte

21

Segui il principio di sorpresa minima per qualsiasi lingua tu stia codificando. Le persone stanno andando, a un certo livello, aspettati che la tua funzione segua i paradigmi e gli standard della tua lingua. Quindi, se la tua lingua utilizza in genere codici di errore come -1 sulle funzioni di ricerca (come C, C ++, ecc.), Fallo. Se sei in una lingua funzionale in cui un tipo di opzione è comune, fallo. Se la tua lingua usa in genere null per quel genere di cose, fallo. Ecc, ecc. Rendi la tua funzione facile da usare per le persone che la useranno. Sono molto più propensi a farlo bene quando funziona come altre cose con cui hanno familiarità.

    
risposta data 31.01.2017 - 16:10
fonte
15

Un modo popolare, almeno tra le lingue funzionali, è di usare un tipo Maybe (o Option in alcune lingue funzionali).

Maybe<int> FindPosition(string stringToSearch, char charToFind)
    // Return Some(int) if found or none if not.

La funzione restituirà quindi un valore int della posizione se trovato e none se non è stato trovato nulla.

Questo evita i problemi inerenti all'uso di struct o tupla per restituire un flag che indica il successo, e un valore int non definito in dipendenza da quello stato di flag; lanciare un'eccezione; usando un numero magico ecc.

    
risposta data 31.01.2017 - 15:19
fonte
3

A volte un pattern TryGet può essere utile nello scenario che descrivi.

Esempio:

public bool TryGetValue(string input, string toFind, out int value)

Nota: questo ti dice anche che non dovrebbero uscire eccezioni da questo metodo anche per le lingue che supportano le eccezioni.

    
risposta data 31.01.2017 - 15:49
fonte
2

Ci sono molti approcci a questo e mentre sono d'accordo con Becuzz in una certa misura che di solito dovresti seguire le convenzioni della lingua / squadra, non sempre è completamente tagliato e asciutto. In Java, ci sono idee in competizione sul modo migliore per affrontare questo genere di cose e quale sia la risposta giusta dipende dal contesto del metodo.

Una cosa che vorrei prima provare a disattenderti è che il ritorno -1 è un valore "casuale" o un numero magico. Davvero non dovresti essere codificato per il valore specifico. In tal caso, è necessario verificare se non sono stati trovati valori inferiori a 0. Ho visto che supposizioni del genere portano a bug. Ad esempio, in Java Integer.compare viene implementato utilizzando la sottrazione. Ciò significa che praticamente qualsiasi int (positivo o negativo) può essere restituito, ma ho visto codice che presuppone che le chiamate di confronto restituiscano solo -1, 0 o 1. Un altro caso in cui è il punto è Arrays.binarySearch che, quando un elemento non è found restituisce un numero negativo che indica dove si troverebbe l'elemento nell'ordine se fosse nell'array.

Questi tipi di approcci sono utili perché restituiscono più informazioni semplicemente "non trovate". Ci sono altri casi anche se approcci diversi sono comuni. Ad esempio, un metodo pensato per recuperare una raccolta di elementi che soddisfano un determinato criterio potrebbe restituire un null . Un'altra opzione è quella di restituire una collezione vuota. Nella maggior parte dei casi, quest'ultimo è preferibile perché non ci si deve preoccupare dei controlli del puntatore nullo e di solito non sono richiesti controlli se tutto ciò che si vuole fare è iterare sui risultati. Il ritorno di null è comune e previsto in Java, ma è anche problematico. Un'altra opzione potrebbe essere quella di lanciare un'eccezione, ma che è generalmente scoraggiata a causa del sovraccarico di creare una traccia di stack che di solito è sopravvalutata ma reale.

Il punto è che non hai bisogno di seguire ciecamente le convenzioni se riesci a ottenere risultati superiori. Ma al posto di ciò, fai ciò che le persone si aspettano.

    
risposta data 31.01.2017 - 18:00
fonte
1

Un modo è di restituire una struttura a due campi per valore, in C ++ questo di solito è simile a questo:

struct find_result
{
    bool found;
    size_t index;
};

Quindi il callee può impostare found su true o false , solo impostare index quando found è true e documentare che index può essere utilizzato solo se found è% % co_de.

La libreria standard C ++ usa questo con true , dove std::pair<> è a first e bool trasporta il contesto (come second fa sopra).

    
risposta data 31.01.2017 - 14:29
fonte
1

In questo caso specifico un valore di ritorno valido (indicante che è stata trovata una corrispondenza) sarà da zero in su, mentre -1 indica che non è stato trovato nulla. Ti rimangono tutti gli altri valori negativi per indicare che c'era un problema. Quindi in questo caso vorrei solo tornare -2 per indicare che c'era un errore.

Come Johann ha detto in precedenza, è possibile utilizzare strutture complesse per restituire valori di tipo "stato", ma lo userei solo per le API in cui sono richiesti valori di ritorno complessi ed è necessario indicare se il risultato effettivo restituito è "reale". Quindi nel tuo caso specifico se fosse possibile restituire valori negativi validi, allora non hai la possibilità di usare i numeri negativi per indicare lo stato e quindi restituire una coppia di valori sarebbe utile.

    
risposta data 31.01.2017 - 15:16
fonte

Leggi altre domande sui tag