Domanda

Ho spesso scritto questa sorta di funzione in entrambi i formati, e mi chiedevo se un formato è preferito rispetto ad un altro, e perché.

public void SomeFunction(bool someCondition)
{
    if (someCondition)
    {
        // Do Something
    }
}

o

public void SomeFunction(bool someCondition)
{
    if (!someCondition)
        return;

    // Do Something
}

Io di solito codice con il primo dato che questo è il modo in cui il mio cervello funziona durante la codifica, anche se penso che io preferisco il 2 ° dal momento che si prende cura di gestire qualsiasi errore subito e trovo più facile da leggere

È stato utile?

Soluzione

Io preferisco il secondo stile. Ottenere i casi non validi di mezzo prima, o semplicemente uscendo o sollevando eccezioni a seconda dei casi, mettere una riga vuota in là, quindi aggiungere il corpo "reale" del metodo. Trovo più facile da leggere.

Altri suggerimenti

Sicuramente quest'ultimo. Il primo non sembra male in questo momento, ma quando si arriva codice più complesso, non riesco a immaginare qualcuno pensi questo:

public int SomeFunction(bool cond1, string name, int value, AuthInfo perms)
{
    int retval = SUCCESS;
    if (someCondition)
    {
        if (name != null && name != "")
        {
            if (value != 0)
            {
                if (perms.allow(name)
                {
                    // Do Something
                }
                else
                {
                    reval = PERM_DENY;
                }
            }
            else
            {
                retval = BAD_VALUE;
            }
        }
        else
        {
            retval = BAD_NAME;
        }
    }
    else
    {
        retval = BAD_COND;
    }
    return retval;
}

è più leggibile di

public int SomeFunction(bool cond1, string name, int value, AuthInfo perms)
{
    if (!someCondition)
        return BAD_COND;

    if (name == null || name == "")
        return BAD_NAME;

    if (value == 0)
        return BAD_VALUE;

    if (!perms.allow(name))
        return PERM_DENY;

    // Do something
    return SUCCESS;
}

Sono pienamente d'ammettere che non ho mai capito il vantaggio di punti di uscita singoli.

Dipende - In generale non ho intenzione di andare fuori dal mio modo per cercare di spostare un mucchio di codice in giro a rompere la funzione di inizio - il compilatore generalmente prendersi cura di questo per me. Detto questo, però, se ci sono alcuni parametri di base in alto che ho bisogno e non può continuare in caso contrario, sarò Breakout presto. Allo stesso modo, se una condizione genera un blocco if gigante in funzione avrò breakout presto a causa di quello.

Detto questo, però, se una funzione richiede alcuni dati quando viene chiamato, ho di solito intenzione di essere un'eccezione (vedi esempio) in contrasto con appena il ritorno.

public int myFunction(string parameterOne, string parameterTwo) {
  // Can't work without a value
  if (string.IsNullOrEmpty(parameterOne)) {
    throw new ArgumentNullException("parameterOne");
  } 
  if (string.IsNullOrEmpty(parameterTwo)) {
    throw new ArgumentNullException("parameterTwo");
  }

  // ...      
  // Do some work
  // ...

  return value;
}

Io preferisco il rientro anticipato.

Se si dispone di un punto di ingresso e un punto di uscita, allora devi sempre monitorare l'intero codice in testa tutta la strada fino al punto di uscita (non si sa mai se qualche altro pezzo di codice soffietto fa qualcos'altro per il risultato , quindi bisogna seguirlo fino alla esistere). Fate che nessun mater quale ramo determina il risultato finale. Questo è difficile da seguire.

Con una voce e molteplice esiste, è tornare quando si ha il risultato e non si preoccupano di monitoraggio tutta la strada verso il basso per vedere che nessuno fa niente altro da esso (perché non ci sarà altro da quando sei tornato) . E 'come avere il metodo corpo diviso in più fasi, che ogni passo con la possibilità di restituire il risultato o lasciare che il passo successivo tentare la sua fortuna.

programmazione

In C in cui devi manualmente clean-up c'è molto da dire per un solo punto di ritorno. Anche se non c'è bisogno in questo momento di qualcosa di pulito, qualcuno potrebbe modificare la vostra funzione, allocare qualcosa e necessità per ripulirlo prima di ritorno. Se ciò accade, sarà un lavoro incubo guardando attraverso tutte le istruzioni di ritorno.

In C ++ la programmazione avete distruttori e anche ora guardie ambito-uscita. Tutte queste necessità di essere qui per garantire il codice è sicuro rispetto alle eccezioni, in primo luogo, quindi il codice è ben custodito contro l'uscita anticipata e quindi così facendo non ha alcun aspetto negativo logico ed è puramente una questione di stile.

Non sono abbastanza informato circa Java, se "finalmente" codice di blocco verrà chiamato e se finalizzatori in grado di gestire la situazione di aver bisogno per garantire succede qualcosa.

C # Io di certo non può rispondere via.

D-lingua dà adeguata built-in guardie scope-uscita e quindi è ben preparato per l'uscita anticipata e quindi non dovrebbe presentare un problema diverso da quello stile.

Le funzioni dovrebbe, naturalmente, non essere così a lungo, in primo luogo, e se si dispone di un enorme istruzione switch il codice è probabilmente anche male scomposto.

torna presto per-la-vittoria. Possono sembrare brutto, ma molto meno brutta di quanto grandi involucri if, soprattutto se c'è più condizioni per controllare.

Io uso sia.

Se DoSomething è di 3-5 righe di codice quindi il codice basta guardare bella con il metodo prima formattazione.

Ma se ha molte più linee di quello, allora io preferisco il secondo formato. Non mi piace quando le staffe di apertura e chiusura non sono sullo stesso schermo.

Un motivo classico per single-entry-single-uscita è che altrimenti i semantica formale diventano indicibilmente brutto altrimenti (stesso motivo GOTO è stato considerato nocivo).

In altre parole, è più facile ragionare su quando il software uscirà dalla routine di se hai solo 1 ritorno. Che è anche un argomento contro eccezioni.

In genere ho minimizzare l'approccio precoce ritorno.

Personalmente, preferisco fare pass / fail controlli condizione all'inizio. Questo mi permette di raggruppare la maggior parte dei più comuni errori nella parte superiore della funzione con il resto della logica da seguire.

Dipende.

Rientro anticipato se c'è qualche evidente condizione di vicolo cieco per verificare la via giusta che avrebbe fatto correre il resto della funzione inutile. *

Set Retval + ritorno singolo, se la funzione è più complesso e potrebbe avere più punti di uscita in caso contrario (emettere la leggibilità).

* Questo spesso può indicare un problema di progettazione. Se si scopre che un sacco di vostri metodi bisogno di controllare uno stato / paramater esterno o come prima di eseguire il resto del codice, che è probabilmente qualcosa che dovrebbe essere gestita dal chiamante.

Usa un caso

Nel libro di Don Knuth in merito a GOTO ho letto dargli un motivo per avere sempre la condizione più probabile venire prima in un'istruzione if. Partendo dal presupposto che questo è ancora un idea ragionevole (e non uno di considerazione puro per la velocità dell'era). Direi che i rendimenti prime non sono buona pratica di programmazione, soprattutto in considerazione del fatto che sono più spesso di quanto non utilizzato per la gestione degli errori, a meno che il codice è più probabilità di fallire rispetto non manca :-)

Se si seguono i consigli di cui sopra, avresti bisogno di mettere che il ritorno alla parte inferiore della funzione, e quindi si potrebbe anche non chiamarlo anche un ritorno lì, è sufficiente impostare il codice di errore e tornare due linee da qui . In tal modo il raggiungimento del 1 ingresso 1 uscita ideale.

Delphi specifico ...

Sono della mente che si tratta di una buona pratica di programmazione per i programmatori Delphi, anche se non ho alcuna prova. Pre-D2009, non abbiamo un modo atomica per restituire un valore, abbiamo exit; e result := foo; o potremmo semplicemente generare eccezioni.

Se si dovesse sostituire

if (true) {
 return foo;
} 

per

if true then 
begin
  result := foo; 
  exit; 
end;

si potrebbe ottenere solo stufo di vedere che nella parte superiore di ogni uno dei vostri funzioni e preferiscono

if false then 
begin
  result := bar;

   ... 
end
else
   result := foo;

e solo evitare exit del tutto.

Sono d'accordo con la seguente affermazione:

Sono personalmente un fan di clausole di guardia (Il secondo esempio) in quanto riduce la rientro della funzione. Alcune persone non come loro, perché si traduce in più punti di ritorno dalla funzione, ma penso che sia più chiaro con loro.

questa domanda StackOverflow .

Io uso rendimenti primi quasi esclusivamente in questi giorni, ad un estremo. Scrivo questo

self = [super init];

if (self != nil)
{
    // your code here
}

return self;

come

self = [super init];
if (!self)
    return;

// your code here

return self;

ma in realtà non importa. Se si dispone di più di uno o due livelli di nidificazione nelle funzioni, hanno bisogno di essere arrestato in su.

Io preferirei scrivere:

if(someCondition)
{
    SomeFunction();
}

Come te, io di solito scrivo il primo, ma preferisco l'ultimo. Se ho un sacco di controlli nidificati io di solito refactoring al secondo metodo.

Non mi piace come la gestione degli errori viene allontanato dal controllo.

if not error A
  if not error B
    if not error C
      // do something
    else handle error C
  else handle error B
else handle error A

Io preferisco questo:

if error A
  handle error A; return
if error B
  handle error B; return
if error C
  handle error C; return

// do something

Le condizioni sulla parte superiore sono chiamati "precondizioni". Mettendo if(!precond) return;, si sta visivamente che elenca tutti i presupposti.

Con il blocco di grandi dimensioni "if-else" può aumentare in testa trattino (ho dimenticato la citazione circa i rientri a 3 livelli).

Io preferisco mantenere se le dichiarazioni di piccole dimensioni.

Quindi, scegliendo tra:

if condition:
   line1
   line2
    ...
   line-n

e

if not condition: return

line1
line2
 ...
line-n

sceglierei quello che hai descritto come "rientro anticipato".

Intendiamoci, non mi importa di rendimenti prime o qualsiasi altra cosa, ho appena piace molto per semplificare il codice, può abbreviare i corpi di istruzioni if, ecc.

nidificati se di e per di e mentre di orribile , evitarli a tutti i costi.

Come altri dire, dipende. Per piccole funzioni che restituiscono valori, posso codice restituisce primi. Ma per le funzioni consistenti, mi piace sempre un posto nel codice in cui so di poter mettere qualcosa che andranno eseguiti prima che ritorni.

I pratica fail-veloce al livello di funzione. Mantiene il codice coerente e pulito (a me e quelli con cui ho lavorato). A causa di questo torno sempre in anticipo.

Per alcune condizioni spesso controllato, è possibile implementare gli aspetti di tali controlli, se si utilizza AOP.

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