2010-07-22 35 views
5

¿Existe una forma mejor de escribir una condición con una gran cantidad de comprobaciones AND que una declaración IF grande en términos de claridad del código?Cómo hacer que la declaración if grande sea más legible

Por ejemplo, actualmente necesito hacer que un campo en la pantalla sea obligatorio si otros campos no cumplen con ciertos requisitos. Por el momento tengo una declaración IF que ejecuta más de 30 LOC, y esto simplemente no parece correcto.

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

¿La solución es simplemente descomponerlos en trozos más pequeños y asignar los resultados a un número menor de variables booleanas? ¿Cuál es la mejor manera de hacer que el código sea más legible?

Gracias

+0

¿Qué tipo de valores se almacenan en estos campos? ¿Puede el usuario modificarlos? ¿Están estáticos, es decir, son cuadros desplegables con valores fijos? –

+0

Son todos valores de cadena, algunos son de solo lectura pero no estánticos – Longball27

Respuesta

9

yo consideraría la creación de reglas, en forma de predicado:

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

Entonces, me gustaría crear mi mismo una lista de estos predicados:

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

Por último, me gustaría escribir la condición para llevar reenvía las condiciones:

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

Esto es lo que estaba a punto de sugerir. Los predicados son una excelente forma de hacer que el código sea más expresivo y mantiene todas las condiciones en un solo lugar. – drharris

1

Personalmente, siento que esta rompiendo en trozos se acaba de hacer la declaración general menos claro. Hará que el código sea más largo, no más conciso.

Probablemente refacturaría esta verificación en un método en la clase, para que pueda reutilizarlo según sea necesario y probarlo en un solo lugar. Sin embargo, lo más probable es que deje el cheque escrito como lo tienes, una declaración con muchas condiciones, una por línea.

1

Puede refactorizar su condicional en una función separada, y también usar De Morgan's Laws para simplificar su lógica un poco.

Además, ¿son sus variables realmente todas llamadas fieldN?

+0

No, no lo son, ¡pensé que simplificaría las cosas para mi pregunta! – Longball27

0

¿Existe alguna otra relación entre todas las variables que comparas y que puedes explotar?

Por ejemplo, ¿son todos los miembros de dos clases?

Si es así, y siempre que sus requisitos de rendimiento no lo impidan, puede raspar las referencias a todos ellos en una lista o matriz, y luego compararlos en un bucle. A veces puedes hacer esto en la construcción de objetos, en lugar de en cada comparación.

Me parece que el problema real está en otra parte de la arquitectura en lugar de en la declaración if(), por supuesto, eso no significa que pueda repararse fácilmente, lo valoro.

1

La primera cosa que cambiaría la legibilidad es eliminar la negación casi oculta por inversión de la declaración (mediante el uso de De Morgan's Laws):

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

Aunque el uso de una serie de & & en lugar de || tiene alguna ligera mejora en el rendimiento, creo que vale la pena la falta de legibilidad con el código original.

Si el rendimiento fuera un problema, podría dividir las declaraciones en una serie de sentencias if, ¡pero para entonces eso ya será un desastre!

+0

No estoy seguro de que tu lógica sea correcta. ¿Acaso no acabas de utilizar las Leyes de De Morgan para simplificar la lógica, en lugar de invertirla? –

+0

Sí, absolutamente ... ¡buen lugar! Fijo. –

1

Parte del problema es que está mezclando metadatos y lógica.

QUE SE REQUIEREN preguntas (/ debe ser igual/duración min/etc) son metadatos.

La verificación de que cada campo cumple sus requisitos es lógica de programa.

La lista de requisitos (y los campos que se aplican también) deben almacenarse en otro lugar, no dentro de una declaración if grande.

Luego su lógica de verificación lee la lista, la recorre y mantiene un total acumulado. Si CUALQUIER campo falla, debe alertar al usuario.

0

¿No es esto para lo que son básicamente arrays?

En lugar de tener 100 variables llamado fieldn, cree un array de 100 values.

Luego puede tener una función para combinaciones de loop en la matriz y return true or false si la condición coincide.

1

Puede ser útil comenzar a utilizar el motor de flujo de trabajo para C#. Fue diseñado específicamente para ayudar a diseñar gráficamente este tipo de algoritmos de decisión complejos.

Windows WorkFlow Foundation

2

El enfoque correcto variará dependiendo de los detalles no se ha proporcionado. Si los elementos que se van a comparar se pueden seleccionar mediante algún tipo de índice (un contador numérico, una lista de identificadores de campo, etc.), probablemente sea mejor que lo haga. Por ejemplo, algo como:

 
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 

La construcción de la lista de controles y cadenas puede haber una ligera molestia, pero hay formas razonables de hacerlo.

Cuestiones relacionadas