2010-07-22 12 views
5

Esiste un modo migliore per scrivere una condizione con un numero elevato di verifiche AND rispetto a un'istruzione IF di grandi dimensioni in termini di chiarezza del codice?Come rendere più leggibile l'if-statement di grandi dimensioni

Ad esempio, attualmente è necessario rendere obbligatorio un campo sullo schermo se altri campi non soddisfano determinati requisiti. Al momento ho una dichiarazione IF che funziona su 30 LOC, e questo non sembra giusto.

if(!(field1 == field2 && 
    field3 == field4 && 
    field5 == field6 && 
    . 
    . 
    . 
    field100 == field101)) 
{ 
    // Perform operations 
} 

La soluzione è sufficiente per suddividerle in blocchi più piccoli e assegnare i risultati a un numero inferiore di variabili booleane? Qual è il modo migliore per rendere il codice più leggibile?

Grazie

+0

Che tipo di valori vengono memorizzati in questi campi? L'utente può modificarli? Sono statici, cioè, cadono scatole con valori fissi? –

+0

Sono tutti valori di stringa, alcuni sono di sola lettura ma non statici – Longball27

risposta

9

vorrei prendere in considerazione la costruzione di regole, in forma predicato:

bool FieldIsValid() { // condition } 
bool SomethingElseHappened() { // condition } 
// etc 

Poi, vorrei creare io stesso un elenco di questi predicati:

IList<Func<bool>> validConditions = new List<Func<bool>> { 
    FieldIsValid, 
    SomethingElseHappend, 
    // etc 
}; 

Infine, vorrei scrivere la condizione per portare inoltra le condizioni:

if(validConditions.All(c => c()) 
{ 
    // Perform operations 
} 
+1

Questo è quello che stavo per suggerire. I predicati sono un ottimo modo per rendere il codice più espressivo e mantiene tutte le condizioni in un unico posto. – drharris

1

Personalmente, ritengo che rompere questo in pezzi sarà solo fare la dichiarazione complessiva meno chiaro. Renderà il codice più lungo, non più conciso.

Probabilmente refactoring questo controllo in un metodo sulla classe, in modo da poterlo riutilizzare, se necessario, e testarlo in un unico luogo. Tuttavia, molto probabilmente lascerò l'assegno scritto come tu lo hai - uno se l'affermazione con molte condizioni, una per riga.

1

È possibile eseguire il refactoring del condizionale in una funzione separata e utilizzare anche De Morgan's Laws per semplificare leggermente la logica.

Inoltre, le vostre variabili sono tutte tutte chiamate fieldN?

+0

No, non lo sono, ho pensato di semplificare le cose per la mia domanda! – Longball27

0

C'è qualche altra relazione tra tutte le variabili che si stanno confrontando e che è possibile sfruttare?

Ad esempio, sono tutti membri di due classi?

In tal caso e se i requisiti delle prestazioni non lo precludono, è possibile racchiudere i riferimenti a tutti in un elenco o matrice e quindi confrontarli in un ciclo. A volte puoi farlo a costruzione di oggetti, piuttosto che per ogni confronto.

Mi sembra che il vero problema sia da qualche altra parte nell'architettura piuttosto che nella dichiarazione if() - ovviamente, ciò non significa che possa essere facilmente risolto, lo apprezzo.

1

La prima cosa che vorrei cambiare per la leggibilità è quello di rimuovere la negazione quasi nascosto invertendo la dichiarazione (utilizzando De Morgan's Laws):

if (field1 != field2 || field3 != field4 .... etc) 
{ 
    // Perform operations 
} 

Sebbene l'utilizzo di una serie di & & piuttosto che || ha qualche lieve miglioramento delle prestazioni, ritengo che la mancanza di leggibilità con il codice originale valga il cambiamento.

Se le prestazioni rappresentavano un problema, è possibile suddividere le dichiarazioni in una serie di istruzioni if, ma a quel punto sarà un disastro!

+0

Non sono sicuro che la tua logica sia corretta - non hai appena usato le leggi di De Morgan per semplificare la logica, piuttosto che invertirla? –

+0

Sì, assolutamente .. bel posto! Fisso. –

1

Parte del problema è che si mescolano metadati e logica.

QUALI Le domande sono obbligatorie (/ deve essere uguale/min lunghezza/ecc.) Sono meta dati.

Verificare che ogni campo soddisfi i propri requisiti è la logica del programma.

L'elenco dei requisiti (e anche i campi che si applicano) dovrebbero essere memorizzati altrove, non all'interno di una dichiarazione di grandi dimensioni.

Quindi la logica di verifica legge l'elenco, lo scorre e mantiene un totale parziale. Se QUALSIASI campo fallisce, è necessario avvisare l'utente.

0

Non è questo il motivo per cui lo sono arrays?

Invece di avere 100 variables nome fieldn, creare un array di 100 values.

Quindi è possibile avere una funzione per le combinazioni loop nell'array e return true or false se la condizione corrisponde.

1

Potrebbe essere utile iniziare a utilizzare il motore del flusso di lavoro per C#. È stato specificamente progettato per aiutare a disegnare graficamente questo tipo di complessi algoritmi decisionali.

Windows WorkFlow Foundation

2

L'approccio giusto varierà a seconda dettagli che non hanno fornito. Se gli elementi da confrontare possono essere selezionati da una sorta di indice (un contatore numerico, un elenco di identificatori di campo, ecc.) Probabilmente stai meglio facendo così. Ad esempio, qualcosa come:

 
Ok = True 
For Each fld as KeyValuePair(Of Control, String) in CheckFields 
    If fld.FormField.Text fld.RequiredValue Then 
    OK = False 
    Exit For 
    End If 
Next 

Costruire l'elenco dei comandi e stringhe può essere una leggera fastidio, ma ci sono modi ragionevoli per farlo.

Problemi correlati