Ordinare se le condizioni di efficienza e codice pulito [chiuso]

4

Questa è una domanda puramente di design e l'esempio è semplice per illustrare ciò che sto chiedendo e ci sono troppe permutazioni di codice più complesso per fornire esempi che possano coprire l'argomento. Non mi sto riferendo specificamente a questo esempio, solo usando l'esempio per illustrare a cosa mi riferisco.

In una dichiarazione if, c'è un modo preferito per ordinare le condizioni, in termini di convenzione di codifica e, cosa più importante, di efficienza?

Per un esempio così semplice, l'efficienza non sarà un problema, ma non sto chiedendo una revisione del codice di per sé, ma una comprensione del concetto.

Due alternative:
1.

public double myStuff(int i)
{
    // check for an invalid number of tourists
    if (i > 0)
    {
        // do something here

        return doubleSomething;
    } else
    {
        return Double.NaN;
    }
}

2.

public double myStuff(int i)
{

    if (i <= 0)
    {
        return Double.NaN;

    } else
    {

        {
            // do something here

            return doubleSomething;
        }

Se l'istruzione if dovesse diventare più complessa e possibilmente annidata, in quale ordine devono essere risolte le condizioni?

    
posta Yvette Colomb 16.11.2013 - 01:26
fonte

3 risposte

14

Quando si parla di blocchi di if , l'ottimizzazione non è davvero un problema. Il compilatore genererà praticamente lo stesso risultato indipendentemente da come li organizzi, supponendo che le condizioni siano ugualmente facili da calcolare.

Una tecnica che mi piace usare è usare "istruzioni di guardia" per verificare immediatamente l'input non valido, nella parte superiore del corpo del metodo. In questo modo, il resto del metodo può essere formattato supponendo che gli argomenti siano già validi.

public double myStuff(int i, SomeOtherArgument widget) {
    // Perform any simple checks for invalid data right away and
    // fail fast if something smells bad.
    if (i <= 0)
        return Double.NaN;
    if (widget == null)
        throw new IllegalArgumentException();

    // If the stuff you've done above this line is trivial, there's no reason
    // to wrap the rest of the method body in a big else block. It's just noise.

    return doABunchOfWork();
}
    
risposta data 16.11.2013 - 01:53
fonte
3

L'efficienza non è di solito una preoccupazione reale per strutturare le if-statement, anche se sono complesse o annidate. Esistono modi per nidificare le if-statement che potrebbero essere meno efficienti di altre, ma se il codice viene eseguito una volta sola e impiega 5 nanosecondi per troppo tempo, non si sarà nemmeno in grado di notare che c'è una differenza.

È possibile che questo tipo di cose faccia davvero la differenza nel tempo di esecuzione di un programma, specialmente se si trova nel ciclo più interno di alcuni cicli annidati. Tuttavia, il modo migliore per gestire un programma lento è misurarlo e scoprire dove sta spendendo la maggior parte del suo tempo, in modo che tu possa rendere quel punto più efficiente - indipendentemente dal fatto che quel punto abbia o meno qualcosa a che fare con le if-statement annidate .

Quale dovrebbe essere la preoccupazione per le dichiarazioni if (specialmente quelle nidificate o complesse) è la leggibilità. È molto facile creare un miscuglio illeggibile di complesse istruzioni if annidate, e il codice più difficile da leggere, più difficile è assicurarsi che sia corretto o eseguirne il debug.

Per semplici dichiarazioni if, cerca di evitare che la condizione sia troppo pazza. Se non è possibile evitare una condizione complessa, provare a utilizzare la formattazione per chiarirla oppure utilizzare una funzione di supporto per valutare la condizione.

Mess:

if(a <= 5 && b > 10 && c < 4 && b <= 100
   && a > 2 && c > 1)

Migliore formattazione:

if( (a > 2)  && (a <= 5)   &&
    (b > 10) && (b <= 100) &&
    (c > 1)  && (c < 4) )

Funzione di supporto:

if( withinLimits(a, b, c) )

Inoltre, cerca di evitare i doppi negativi. "Non direi che non è un'affermazione errata" è difficile da leggere. "È sbagliato" è facile da leggere e significa la stessa cosa. I singoli negativi non sono poi così male, ma a volte puoi rendere le cose un po 'più chiare affermando invece qualcosa di positivo.

Per le if if annidate, dipende da come sono nidificate.

Per qualcosa di simile:

if(a) {
  if(b) {
    if(c) {
      something;
    }
  }
}

Potresti sostituirlo con qualcosa di simile:

if(a && b && c) {
  something;
}

Se hai una nidificazione complessa di istruzioni if, probabilmente è un casino. Come risolverlo dipende esattamente da cosa è esattamente. Potrebbe essere possibile creare una tabella decisionale, una matrice con indici che rappresentano ciò su cui basiamo la decisione e le voci che costituiscono la decisione risultante. Se è così, possiamo semplicemente cercare la risposta senza usare alcuna dichiarazione if.

    
risposta data 16.11.2013 - 23:49
fonte
1

Per condizioni composite, si potrebbe prendere in considerazione il fatto che, in Java, la valutazione delle condizioni è pigra. Ciò significa che il programma valuterà solo le (sotto) condizioni finché non potrà decidere se le istruzioni condizionali debbano essere eseguite o meno.

Quindi, ad esempio, se hai due condizioni c1 e c2 e se c1 può essere valutato rapidamente poiché c2 richiede un po 'di tempo per essere valutato, preferisci if(c1 and/or c2) a if(c2 and/or c1) , in modo da poter determinare più rapidamente se la condizione globale è rispettata o no. Allo stesso modo, preferisci

if(c1){
   if(c2){
      (...)
   }
}

a

if(c2){
   if(c1){
      (...)
   }
}

Nel peggiore dei casi non cambia nulla, e nel migliore dei casi risparmi un test.

Questo è un principio generale, puoi anche considerare il fatto che una delle condizioni sarà vera praticamente tutte le volte. In tal caso, potrebbe essere interessante inserirlo prima in una composizione OR, in modo da non testare virtualmente la seconda condizione. Diventa più difficile decidere come ordinare le condizioni quando devi considerare contemporaneamente il consumo di tempo e la probabilità di valore.

Tieni presente che prima di modificare l'ordine delle tue condizioni, devi essere sicuro che non implichino alcun effetto collaterale, altrimenti un riordino potrebbe cambiare il comportamento del tuo programma.

    
risposta data 16.11.2013 - 16:46
fonte