Domanda

Lasciatemi iniziare dicendo che io non sostengo questo approccio, ma l'ho visto di recente e mi chiedevo se c'era un nome che ho potuto usare per indicare il colpevole per.Così qui va.

Ora avete un metodo, e si desidera restituire un valore.Si anche desidera restituire un codice di errore.Naturalmente, le eccezioni sono una scelta molto migliore, ma per qualsiasi motivo si desidera un codice di errore, invece.Ricordate, sto giocando l'avvocato del diavolo qui.Così si crea una classe generica, come questo:

class FunctionResult<T>
{
    public T payload;
    public int result;
}

E poi dichiarare le funzioni di simile a questo:

FunctionResult<string> MyFunction()
{
    FunctionResult<string> result;
    //...

    return result;
}

Una variante di questo modello è quello di utilizzare un enum per il codice di errore invece di una stringa.Ora, torniamo alla mia domanda:c'è un nome per questo, e se sì qual è?

È stato utile?

Soluzione

Io sono d'accordo che questo non è specificamente un antipattern.Potrebbe essere un odore a seconda dell'utilizzo.Ci sono ragioni per cui una persona sarebbe in realtà non desidera utilizzare eccezioni (ad es.gli errori restituiti non e 'eccezionale', tanto per cominciare).

Ci sono casi in cui si desidera disporre di un servizio di restituire un modello comune per i suoi risultati, tra errori e di buoni valori.Questo potrebbe essere avvolto da un basso livello di servizio di interazione che converte il risultato in un'eccezione o un altro errore di struttura, ma a livello di servizio, che consente la restituzione di un risultato e di un codice di stato senza dover definire alcune eccezioni struttura che potrebbe essere tradotto attraverso un remoto confine.

Questo codice potrebbe non necessariamente essere un errore:considerare una risposta HTTP, che consiste di un sacco di diversi dati, tra cui un codice di stato, insieme con il corpo della risposta.

Altri suggerimenti

Beh, è non un antipattern.La libreria standard del C++ fa uso di questa funzione e .NET offre anche una speciale FunctionResult classe .NET framework.Si chiama Nullable.Sì, questo non è limitato alla funzione di risultati, ma può essere utilizzato per tali casi e in realtà è molto utile qui.Se .NET 1.0 aveva già avuto Nullable classe, sarebbe stato certamente utilizzato per la NumberType.TryParse metodi, invece di out parametro.

Io di solito passano il payload come (non costante) di riferimento e il codice di errore come valore di ritorno.

Io sono uno sviluppatore del gioco, abbiamo bandire eccezioni

Konrad è giusto, C# utilizza una coppia di valori di ritorno per tutto il tempo.Ma mi piace il TryParse, Dizionario.TryGetValue, etc.i metodi in C#.

int value;
if (int.TryParse("123", out value)) {
    // use value
}

invece di

int? value = int.TryParse("123");
if (value != null) {
    // use value
}

...soprattutto perché il Nullable motivo non è adatta per il non-Valore di ritorno tipi (cioè, le istanze di classe).Questo non funziona con il Dizionario.TryGetValue().E TryGetValue sia più bello di un KeyNotFoundException (non "prima le eccezioni possibilità di" costantemente nel debugger, probabilmente più efficiente), più bello di Java pratica di get() restituisce null (se i valori null sono ancora in attesa), e più efficiente di dover chiamare ContainsKey() prima.

Ma questo è ancora un po ' strano, dal momento che questo sembra come C#, quindi dovrebbe essere utilizzando un parametro out.Tutti i guadagni di efficienza sono probabilmente perso di creare un'istanza della classe.

(Potrebbe essere Java, tranne per la "stringa" tipo di essere in minuscolo.In Java, naturalmente, è necessario utilizzare una classe di emulare il doppio dei valori di ritorno.)

Io non sono sicuro che questo è un anti-pattern.Ho visto comunemente utilizzato invece di eccezioni per motivi di prestazioni, o forse per il fatto che il metodo può non riuscire più esplicito.A me, sembra essere una preferenza personale, piuttosto che un anti-pattern.

Sono d'accordo con quelli che dicono che questo non è un anti-pattern.Il suo perfettamente valido motivo in determinati contesti.Le eccezioni sono per eccezionale situazioni, valori di ritorno (come nel tuo esempio) dovrebbero essere utilizzati in situazioni previste.Alcuni domini di aspettare validi e non validi risultati, dalle classi, e nessuno di quelli che dovrebbero essere modellato come eccezioni.

Per esempio, dato un numero X di gas, di un auto ottenere da a a B, e se sì di quanto gas è rimasto?Che tipo di domanda è ideale per la struttura di dati che hai fornito.Non essere in grado di fare il viaggio da a a B è previsto, quindi, un'eccezione non deve essere utilizzato.

Questo approccio è in realtà molto meglio di alcuni altri che ho visto.Alcune funzioni in C, per esempio, quando si verifica un errore ritorna e sembra di riuscire.L'unico modo per dire che non sono riusciti è quello di chiamare una funzione che consente di ottenere il più recente di errore.

Ho passato ore a cercare di debug semaforo codice sul mio MacBook prima ho finalmente scoperto che sem_init non funziona su OSX!È compilato senza errori e corse senza causare errori - ma il semaforo non funzionava e non riuscivo a capire perché.Ho pietà per la gente che la porta di un'applicazione che utilizza Semafori POSIX per OSX e deve fare i conti con problemi di contesa di risorse che sono già state debug.

Come circa la "non Può decidere se questo è un errore o non" modello.Sembra come se hai avuto veramente un'eccezione, ma ha voluto restituire un risultato parziale, devi avvolgere il risultato eccezione.

Se non si desidera utilizzare le eccezioni, il modo più pulito per farlo è di avere la funzione di restituire il successo o di errore codice e prendere un riferimento o puntatore argomento che viene riempito con il risultato.

Non lo chiamerei un anti-pattern.Si tratta di un ben dimostrata metodo efficace che spesso è preferibile all'uso di eccezioni.

Se si prevede che il metodo non tanto in tanto, ma non ritengo eccezionale, preferisco questo modello, come quello utilizzato nel .NET Framework:

bool TryMyFunction(out FunctionResult result){    

     //...    
     result = new FunctionResult();
}

Dibattiti su odori e anti-patterns mi ricordano il "Sopravvissuto" spettacoli TV, dove si hanno diversi costrutti di programmazione cercando di voto di ogni altra al largo dell'isola.Io preferisco vedere "costruire X è tale-e-in modo pro e i contro", piuttosto che una continua evoluzione elenco di editti di ciò che dovrebbe e non dovrebbe essere fatto.

In difesa di anti-pattern denominazione, il codice si presta ad essere utilizzato in diversi modi:

  1. Oggetto: x = Miafunzione().carico utile; (ignorando il risultato restituito - molto male)
  2. int codice = Miafunzione().risultato; (getta il carico utile può essere giusto se la destinazione d'uso.)
  3. FunctionResult x = Miafunzione();//... (un sacco di extra FunctionResult oggetti extra e il codice di controllo in tutto il luogo)

Se è necessario utilizzare i codici di ritorno, va bene.Ma quindi utilizzare i codici di ritorno.Non cercare di confezionare un extra di carico in con esso.Che è quello che rif e fuori parametri (C#) sono per.Tipi Nullable potrebbe essere un'eccezione, ma solo perché c'è un extra di zucchero cotto in lingua per il supporto.

Se è ancora d'accordo con questa valutazione, DOWNVOTE questa risposta (non tutta la questione).Se si credo che sia un anti-pattern, poi votarlo.Useremo questa risposta per vedere ciò che la comunità pensa.

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top