Domanda

Dati i seguenti frammenti di codice, c'è qualche differenza apprezzabile?

public boolean foo(int input) {
   if(input > 10) {
       doStuff();
       return true;
   }
   if(input == 0) {
       doOtherStuff();
       return true;
   }

   return false;
}

vs.

public boolean foo(int input) {
   if(input > 10) {
      doStuff();
      return true;
   } else if(input == 0) {
      doOtherStuff();
      return true;
   } else {
      return false;
   }
}

O sarebbe il principio di uscita singolo essere meglio qui con questo pezzo di codice ...

public boolean foo(int input) {
   boolean toBeReturned = false;
   if(input > 10) {
      doStuff();
      toBeReturned = true;
   } else if(input == 0) {
      doOtherStuff();
      toBeReturned = true;
   }

   return toBeReturned;
}

C'è qualche differenza di prestazioni percepibile? Ti senti uno è più o meno gestibile / leggibile rispetto agli altri?

È stato utile?

Soluzione

Con il secondo esempio si stato molto chiaramente che entrambe le condizioni si escludono a vicenda.
Con la prima, non è così chiaro, e nel (improbabile) caso in cui si aggiunge l'incarico di input tra i due IFS, la logica sarebbe cambiato.
Supponiamo che qualcuno in futuro aggiunge input = 0 prima del secondo caso.
Naturalmente questo è improbabile che ciò accada, ma se stiamo parlando di manutenibilità qui, if-else dice chiaramente che ci sono mutuamente esclusive condizioni, mentre un gruppo di IFS non lo fanno, e non sono così dipendenti tra loro come lo sono se blocchi -else.

modifica:. Ora che vedo, in questo particolare esempio, la clausola di ritorno forze l'esclusività reciproca, ma ancora una volta, stiamo parlando di manutenibilità e la leggibilità

In ogni caso, per le prestazioni, se questo è codificato in Java non si deve la cura per le prestazioni di un paio di blocchi, se, se fosse incorporato C in un hardware molto lento, forse, ma certamente non con Java.

Altri suggerimenti

Usare qualsiasi forma meglio descrive il vostro intento.

Non seguire il principio di uscita singolo, se le cose sono così semplici, anche se - rende solo più confuso

.
  • Nel primo:

    qualcuno alla fine, per qualche strana ragione, e quando non siete in cerca aggiungerà qualche dichiarazione aggiuntivo che renderà questo metodo di fallire in certe situazioni strane, tutti (o peggiore, una persona singola) trascorreranno 4 ore. guardare il codice sorgente e il debug dell'applicazione per finalmente trovato c'era qualcosa nel mezzo.

  • Il secondo è decisamente migliore, non solo impedisce questo scenario, ma aiuta anche a indicare chiaramente, è questo o questo altro non di più.

    Se tutto il codice che scriviamo in un if cui 10 linee lungo al massimo, questo non importa molto, ma purtroppo questo non è il caso, ci esiste altri programmatori che per qualche ragione pensare che una se il corpo deve essere> 200 le linee lungo ... in ogni caso.

  • Non mi piace il terzo, mi costringe a cercare la variabile di ritorno, ed è più facile trovare il return parola chiave

A proposito di prestazioni di velocità, sono (quasi) identici. Non ti preoccupare di questo.

Nel tuo ultimo esempio, non fare questo:

public boolean foo(int input) {
   boolean toBeReturned = false;
   if(input > 10) {
      doStuff();
      toBeReturned = true;
   } else if(input == 0) {
      doOtherStuff();
      toBeReturned = true;
   }

   return toBeReturned;
}

, ma questa (si noti l'uso di Java finale ):

public boolean foo(int input) {
   final boolean toBeReturned;    // no init here
   if(input > 10) {
      doStuff();
      toBeReturned = true;
   } else if(input == 0) {
      doOtherStuff();
      toBeReturned = true;
   } else {
      toBeReturned = false;
   }
   return toBeReturned;
}

In questo modo si effettua la intenzione chiara e questo è una manna dal cielo per gli IDE supportano "la programmazione per intenzione" (non c'è bisogno di "compilazione" per vedere i potenziali errori, anche su un AST parziale, un buon IDE può esaminare fonte incompleta in tempo reale e darvi avvisi istantanei).

In questo modo si è che non dimenticare di inizializzare il valore di ritorno. Questo è grande se in seguito si decide che, dopo tutto ciò che serve un'altra condizione.

Lo faccio tutto il tempo e anche dà fastidio solo da quando ho iniziato ad usare IntelliJ IDEA (versione 4 o giù di lì, molto tempo fa) e questo mi ha salvato tanti errori di distrazione stupido ...

Alcune persone sostengono che questo è troppo codice per un caso così semplice, ma questo è del tutto assente il punto: il punto è quello di rendere il modo chiaro intento che il codice legge facilmente e può essere facilmente esteso in seguito, senza accidentalmente dimenticare per assegnare toBeReturned e senza accidentalmente dimenticare di ritorno da una clausola in seguito è possibile aggiungere.

In caso contrario, se "concisione" era il nome del gioco, quindi mi piacerebbe scrivere:

public boolean foo(int a) {
  return a > 10 ? doStuff() : a == 0 ? doOtherStuff() : false; 
}

Dove sia doStuff e doOtherStuff sarebbe restituire true.

semanticamente - no. Performance-saggio questo dipende compilatore, vale a dire se si può posto che entrambe le condizioni non può essere vero in una sola volta. Scommetto standard di Sun compilatore può. Se utilizzare principio uscita singola dipende da gusti. Io personalmente odio.

Version # 1 e # 2 possono essere più veloce di # 3, ma suppongo che la differenza di prestazioni è minimo. Avrei preferito concentrarsi su leggibilità .

Personalmente, non avrei mai utilizzare la versione # 2. Tra il 1 e il # 3 #, sceglierei quello che produce il codice più leggibile per il caso in questione. Non mi piace molti punti di uscita nei miei metodi, perché rende il codice difficile da analizzare. Tuttavia, ci sono casi in cui il flusso diventa più chiaro quando usciamo subito per alcuni casi particolari, e continuiamo con i casi principali.

Pensate a questo caso, quando i due esempi non saranno simili:

    public boolean foo(int input) {
        if (input > 10) {
            // doStuff();
            return true;
        }
        System.out.println("do some other intermediary stuff");
        if (input == 0) {
            // doOtherStuff();
            return true;
        }

        return false;
    }

vs.

    public boolean foo(int input) {
        if (input > 10) {
            // doStuff();
            return true;
        } 
        //System.out.println("doing some intermediary stuff... doesn't work");
        else if (input == 0) {
            // doOtherStuff();
            return true;
        } else {
            return false;
        }
        return false;
    }

Il primo approccio è probabilmente più flessibile , ma entrambi formule hanno il loro utilizzo in circostanze diverse.

Per quanto riguarda le prestazioni, credo che le differenze sono di piccole dimensioni da prendere in considerazione, per qualsiasi applicazione Java regolare, codificato dai programmatori sani:)

.

Nel tuo caso il secondo se sarebbe ottenere chiamato solo se la prima, se non è riuscita quindi è meno importante qui, ma se il primo, se ha fatto qualcosa e non ha restituito, il secondo caso (che sarebbe poi essere sempre false) sarebbe ancora testato a meno che non era in un altro, se.

In altre parole, ci sono casi in cui la differenza tra if-else-if e if-se le cose, ma questo non è uno di loro.

Esempio: Prova questo e poi provare dopo aver rimosso il resto. È possibile ottenere due diverse uscite:

int someNumber = 1;
if(someNumber < 5)
{
    someNumber += 5;
    Console.WriteLine("First call.");
}
else if(someNumber >= 5)
{
    Console.WriteLine("Second call.");
}

Tra il primo e il secondo snippet, non c'è davvero nessuna differenza. Tuttavia il terzo frammento è abbastanza inefficiente. Perché aspettare per restituire il controllo del programma al chiamante fino a quando l'ultima riga di codice nel metodo, si spreca potenza di elaborazione / memoria, mentre i primi due frammenti di codice restituire il controllo non appena determina una delle condizioni per essere vero.

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