Si avvicina al controllo di più condizioni? [duplicare]

28

Qual è la migliore pratica per verificare più condizioni, in nessun ordine particolare?

L'esempio in questione deve verificare quattro condizioni distinte, in qualsiasi ordine, e non mostrare il messaggio di errore corretto.

Gli esempi seguenti usano una sintassi simile a C..

Opzione 1: controlla tutto in una volta

Questo metodo non è preferito perché i motivi per cui la condizione non è riuscita non sono facili da distinguere.

if (A && B && C && D) {
    // continue here...
} else {
    return "A, B, C, or D failed";
}

Opzione 2: Condizioni nidificate

In passato, usavo le istruzioni condizionali annidate, in questo modo. Questo può diventare davvero confuso.

if (A) {
    if (B) {
        if (C) {
            if (D) {
                // continue here...
            } else {
                return "D failed"
            }
        } else {
            return "C failed";
        }
    } else {
        return "B failed";
    }
} else {
    return "A failed";
}

Opzione 3: Fail-early

Questo è il metodo corrente che uso, che mi piace chiamare fail-early . Non appena viene colpita una condizione "cattiva", ritorna.

if (!A) {
    return "A failed";
}

if (!B) {
    return "B failed";
}

if (!B) {
    return "C failed";
}

if (!D) {
    return "D failed";
}

// continue here...

Opzione 4: raccolta errori

Un ultimo approccio che riesco a pensare è una sorta di collezione di errori. Se le condizioni per testare sono completamente separate, si potrebbe voler usare questo approccio.

String errors = "";
if (!A) {
     errors += "A failed\n";
}

if (!B) {
    errors += "B failed\n";
}

if (!C) {
    errors += "C failed\n";
}

if (!D) {
    errors += "D failed\n";
}

if (errors.isEmpty()) {
    // continue here...
} else {
    return errors;
}

Quali sono le migliori pratiche per verificare più condizioni? In termini di aspettative, si comporta idealmente come l'esempio 4, in cui vengono restituiti i dettagli di tutti gli errori.

    
posta Redandwhite 19.03.2013 - 20:58
fonte

3 risposte

21

La risposta è ... dipende.

Qualcuno di A, B, C o D non funziona? Il controllo per A e il mancato controllo rendono B, C o D poco pratico o ridondante? È utile segnalare la raccolta di errori che sono stati segnalati o solo il primo rilevato?

Ciascuna delle opzioni presentate ha il suo uso nella situazione corretta. Non esiste un unico approccio di gestione degli errori per dominarli tutti.

    
risposta data 19.03.2013 - 21:07
fonte
14

Dipende davvero dal tipo di informazioni che vuoi tornare dalla funzione. Analizziamo ciò che ogni opzione ti offre:

  1. Non ti interessa quale condizione fallisca, vuoi solo sapere se tutti hanno o meno successo.

  2. Chiaramente fuori mano. Ottima formattazione e leggibilità a causa del nidificazione del codice. Fa la stessa cosa del 3 ma più brutto.

  3. Conosci la prima condizione che ha fallito.

  4. Conosci tutte le condizioni che non hanno funzionato.

Ora sta a te decidere quale opzione è la migliore, a seconda del contesto e di quali informazioni hai realmente bisogno.

    
risposta data 19.03.2013 - 21:09
fonte
2

La risposta dipende enormemente da quale lingua stai utilizzando e da cosa farai in seguito agli errori.

Ad esempio, in Scala, e assumendo che voglio segnalare ogni errore in modo che possano essere risolti tutti contemporaneamente, probabilmente farei qualcosa di simile

val (yes, no) = List(
  (A, "A failed"),
  (B, "B failed"),
  (C, "C failed"),
  (D, "D failed")
).partition(_._1)
if (!no.isEmpty) Some(no.map(_._2)) else None

dove prima raggruppo le mie condizioni e i messaggi di errore, quindi li divido in due gruppi - i successi e gli errori - e restituisco quei messaggi di errore se c'era qualcosa, e in caso contrario restituisco un valore sentinella dicendo - in questo caso - che tutto va bene.

Ma ciò dipende in modo critico dalla capacità di Scala di raggruppare, mappare e manipolare rapidamente raccolte e contenitori. In Java, scriverei lo stesso identico codice nel più dettagliato (e meno comodo da controllare, poiché ora ho bisogno di interrogare errors.size() per sapere se ho fallito qualcosa):

ArrayList<String> errors = new ArrayList<String>();
if (!A) errors.add("A failed");
if (!B) errors.add("B failed");
if (!C) errors.add("C failed");
if (!D) errors.add("D failed");
return errors;

Se abbiamo solo bisogno del primo errore, in Java farei fail-fast mentre in Scala potrei

List(A,B,C,D).zipWithIndex.find(!_._1).foreach{ x => return x._2 }

supponendo che stavo bene con il numero dell'articolo che è andato male come codice di ritorno.

Quindi la risposta è davvero: hai gli stili diversi importanti, ma quanto esattamente implementarli in modo più efficiente o meno doloroso dipenderà molto dai tuoi strumenti.

    
risposta data 19.03.2013 - 22:34
fonte

Leggi altre domande sui tag