2010-08-03 10 views
9

He estado programando durante mucho tiempo. Generalmente programo en algunos lenguajes como PHP, ASP.net, Java, JavaScript y otros. En todos los idiomas, tengo que usar una gran cantidad de declaraciones if else. Al igual que si el valor = 10, entonces ... si reviso mi código, entonces encontraré un montón de condiciones. Entonces me gustaría minimizarlos pero no estoy seguro.Cómo evitar si ... else y cajas de conmutadores

un momento estaba usando clases tanto minimizadas pero aún así son más ...

como tarea, gato, sec y tipo:

if task = 'add' then 
    if cat = "animal" then 
     if sec = "man" then 
      if type = "male" then 
       'do the following stuffs 
      else 
       'do the following stuffs 
      end if 
     elseif sec = "horse" then 
      if type = "run" 
       'do the following stuffs 
      else 
       'do the following stuffs 
      end if 
     elseif.... 
     end if 
    elseif cat = "plant" then 
    if sec = "land" then 
      if type="tree" then 
       'do the following stuffs 
      elseif type = "grass" then.. 
       'do the following stuffs 
      elseif... 
      end if 
    elseif sec = "water" then 
    ... 
... 

...

más n más los que siguen n continuar

así que me pregunto cómo puedo minimizarlos y escribir algunos códigos eficientes?

Lo sentimos informar de que últimamente hay muchos valores para task, cat, sec y type. Mis sentencias if van anidadas n anidadas.

Más explicativo mi código también se parece a la misma como:

http://thedailywtf.com/Articles/Coding-Like-the-Tour-de-France.aspx

+0

agregué un código a mi respuesta – Mchl

+2

Una nota al margen: intente codificar con la intención de que una función/sub nunca sea mayor que puede ver toda la función/sub en una pantalla (pantallas giratorias no incluidas:]). De esta manera se verá obligado a dividir este código en fragmentos más pequeños y esto, a su vez, hará que sea más fácil ver y entender – Default

Respuesta

14

Muchos if..else afirmaciones es a menudo un síntoma de la Polymorphism no está siendo utilizado.

+0

leyendo las cosas tal vez sea la que estoy buscando ... publicaré comentarios más adelante ... si algunas enlace de explicación visual por favor publíquelo – KoolKabin

+0

No creo que el polimorfismo resuelva todos los problemas de demasiados if-else. ¿Qué sucede si se debe interpretar la información de la consola? – Default

+0

¿Podría el infractor por favor dejar un comentario. Gracias. –

4

Se llama 'Flecha antipatrón' Algunos de los métodos de tratar con ella se describen a continuación: http://c2.com/cgi/wiki?ArrowAntiPattern

Una de las formas en las que migt tener en cuenta, es que refactorizar código en niveles anidados para separar las funciones como

if cat = "animal" then 
    functionForAnimal(); 
elseif cat = "plant" then 
functionForPlant(); 
elseif... 


function functionForAnimal() 
    if sec = "man" then 
    functionForMan(); 
    elseif sec = "horse" then 
    functionForHorse(); 
    elseif... 

etc... 

Esto divide el código en fragmentos más pequeños que son más fáciles de mantener y posiblemente reutilizables.

+0

disculpa por aclarar la pregunta últimamente ... pero los casos pueden ser muy parecidos a la pregunta editada – KoolKabin

+0

sí, más explicativo, mi código también se ve igual: http://thedailywtf.com/Articles/Coding-Like-the-Tour -de-France.aspx – KoolKabin

+0

+1, esta fue mi idea también, dividirlo, hacerlo más fácilmente visible y reutilizar las piezas que se pueden reutilizar. – Default

0

Si las opciones para cada una de esas variables son finitas, entonces puede incluso usar trucos como campos de bit con operación OR.

Ejemplo:

// give each field a byte so that each can have 256 possible values 
#define TASK_ADD 0x01 
#define TASK_SUB 0x02 
... 
#define CAT_ANIMAL 0x01 
... 
#define SEC_BOY 0x03 
#define SEC_MAN 0x04 
... 
#define TYPE_FEMALE 0x01 
#define TYPE_MALE 0x02 
... 

if ((task << 24 | cat << 16 | sec << 8 | type) == 0x01010402) { 
    // do stuff 
} 
+0

disculpa por aclarar dudas últimamente ... pero los casos pueden ser muy similares a la pregunta editada – KoolKabin

2

Polymorphism podría ser útil cuando se tienen diferentes implementaciones pero la tarea es conceptualmente el mismo. A veces es difícil encontrar una estructura de clase natural, y enfoques como el state pattern o el strategy pattern podrían ser más apropiados.

+0

sí, el polimorfismo es definitivamente útil, pero antes de usar el polimorfismo debemos crear un objeto y antes de crear el objeto debemos saber cuáles son las opciones establecidas por el usuario. p.ej. si mantiene todas esas opciones en un formulario y luego el usuario hace clic en un botón para comenzar el trabajo, entonces, ¿cuál clase debería crearse y llamarse según polymorphisim? – KoolKabin

0

En algún lugar deberá verificar las condiciones con if-elses, para asegurarse de que hace lo correcto. Se puede crear nuevos submarinos si no quiere meter un sub

Sub AddAnimalManMale() 
    If task = 'add' And cat = 'animal' And sec = 'man' And type = 'male' Then 
     'perform the add animal man male action' 
    End If 
End Sub 
Sub AddAnimalHorseRun() 
    If task = 'add' And cat = 'animal' And sec = 'horse' And type = 'run' Then 
     'perform the add animal horse run action' 
    End If 
End Sub 

después en su sub principal

... 
Call AddAnimalManMale() 
Call AddAnimalHorseRun() 
... 
+0

Sus cosas también son buenas y similares a las anteriores. Si hacemos una llamada a la función mediante la concatenación de todas las opciones, entonces tenemos que verificar las variables una vez más dentro de la función – KoolKabin

2

Describiste una matriz con 4 parámetros de entrada - task, cat, sec, type y un saliente - stuff. Entonces debes codificarlo de alguna manera.

Por ejemplo, mapa XML y una consulta XPath, es decir, String.Format("task[@value={0}]/cat[@value={1}]/sec[@value={2}]/type[@value={3}]", "add", "animal", "man", "male") pero este enfoque apunta a un dato, no a un delegado de método.

Otra forma:

void DoStuffA() { } 
void DoStuffB() { } 

var arr = new[] 
{ 
    new { Task = "Add", Cat = "Animal", Sec = "Man", Type = "Male", Method = (Action)DoStuffA }, 
    new { Task = "Add", Cat = "Plant", Sec = "Land", Type = "Tree", Method = (Action)DoStuffB }, 
    // etc.. 
}; 

var action = arr.FirstOrDefault(i => 
    i.Task == "Add" && 
    i.Cat == "Animal" && 
    i.Type == "Male").Method; 
action(); 

También se puede utilizar miembros no anónimos, sino declarar una clase, describir sus variantes en XML y deserializar desde XML a un número de sus instancias de la clase.

+0

buen enfoque usando una matriz ... también es interesante ... lo espero también – KoolKabin

1

Creo que hay algunos defectos fundamentales en su diseño. No sé qué problema está tratando de resolver con este código, pero dicho código debería ser muy raro en un lenguaje orientado a objetos. Tu código también me parece un poco ilógico, porque, por ejemplo, el tipo de variable significa género la primera vez que se usa (masculino) y luego significa una acción (ejecutar). ¿Has notado esto?

De todos modos, si de hecho está utilizando Java (o cualquier cosa con clases), lo que necesita es abstracción. Luego, mueva toda la lógica que pueda a sus objetos; no la maneje en una rutina monstruosa. Piensa de esta manera: mis objetos saben cómo hacer su parte.

En realidad es un poco difícil dar un buen consejo en esta situación, sospecho que sus problemas tienen una fuente de alto nivel en su aplicación y este código de caso es solo un síntoma. Trate de rediseñar su programa para utilizar un enfoque orientado a objetos y tal vez se le ocurra una mejor solución sobre la marcha.

Si no está seguro de qué significa polimorfismo, abstracción y otros términos OO, tendrá que leer sobre esto.

4

Suponiendo que siempre está haciendo comparaciones de igualdad y comparando los cuatro campos, un enfoque simple basado en datos es bastante práctico. Todo lo que necesita hacer es construir un mapa a partir de (tarea, gato, sec, tipo) a una función para llamar:

handlers = { 
    ('add', 'animal', 'man', 'male'): add_man_func, 
    ('add', 'animal', 'horse', 'run'): run_horse_func, 
    # ... 
} 

handler = handlers[(task, cat, sec, type)] 
handler(some_args) 
+0

Probablemente rompería esto en diferentes niveles (par de tecla simple -> función). La razón principal es que es probable que haya código compartido para todos los _add_s y todos los _animal_s, etc. – Dolphin

0

Rompiendo el código de arriba es todo lo que el juego se trata.

Históricamente que haría (y no habían sido buenas, o al menos el código estable, y todavía existe en todos ellos)

  • como lo está haciendo ahora, monolítica en grandes funciones, con un montón de comentarios

  • dividirlo en pequeñas funciones con nombre bien definidos y bien

  • funciones de nomenclatura era difícil para la materia compleja y también si se mantiene al pasar referencias a estructuras grandes y luego los objetos eran una natura l que hay que inventar (sin embargo, una vez que vaya forma de objeto, entonces tiene sentido hacer todo y a través de la reutilización de código objeto patrones orientados emergen ...)

Reconociendo los patrones es de una manera similar a dar buena nombres a funciones (además de que obtienes métodos naturalmente útiles, lo que puede ser una gran victoria).

Cuestiones relacionadas