2011-01-12 12 views
8

Aquí hay una pregunta de detalles de implementación para los gurús de JavaScript.Implementación de una tabla de decisiones complicadas en JavaScript

Tengo una IU con una serie de campos en los que los valores de los campos dependen de manera complicada de los valores de siete bits de entradas. Exactamente qué se debe mostrar para cualquiera de los posibles 128 valores que cambian regularmente a medida que los usuarios ven más de la aplicación.

En este momento, he implementado esto como un árbol de decisiones a través de un peine if-then-else, pero es frágil en virtud de los cambios de requisitos y algo difícil de conseguir.

enfoque Una aplicación que he pensado es hacer una matriz de valores de 0x0 a 0x7F y luego almacenar un cierre en cada lugar -

var tbl; // initialize it with the values 
    ... 
tbl[0x42] = function(){ doAThing(); doAnotherThing(); } 

y después invocarlos con

tbl[bitsIn](); 

Esto, al menos, hace que la lógica de decisión se convierta en un conjunto de tareas.

Pregunta: ¿hay una manera mejor?

(Actualización:? Santa mierda, ¿cómo esa línea sobre 'Etiquetas Protectores ajax' entra ahí No es de extrañar que era un poco desconcertante.)

actualización

Entonces, ¿qué sucedió ? Básicamente tomé una cuarta opción, aunque similar a la que he comprobado. La lógica era lo suficientemente compleja como para que finalmente construyera un programa Python para generar una tabla de verdad en el servidor (generando el código Groovy, de hecho, el host es una aplicación Grails) y mover la lógica de decisión al servidor por completo. Ahora el lado de JavaScript simplemente interpreta un objeto JSON que contiene los valores para los diversos campos.

Eventualmente, esto probablemente pasará por una iteración más y se convertirá en datos en una tabla de base de datos, indexada por el vector de bits.

La parte accionada por mesa definitivamente resultó ser el camino a seguir; ya ha habido una media docena de nuevos cambios en los requisitos específicos para la pantalla.

+2

por lo que entiendo de su problema, sus pensamientos son de refactorización sonido, pero TBH i No estoy seguro de su descripción, qué es lo que necesita: P –

+0

¿Cada bit determina una acción específica? Si es así, ¿por qué no realizar un Y a nivel de bit en su valor contra [0x01, 0x02, 0x04, 0x08, 0x10, 0x20, 0x40] – draeton

+0

@Martin, el punto es si hay otra manera más flexible de hacer esto que mi tabla de lambdas –

Respuesta

1

¿Ha considerado generar su árbol de decisión en el servidor en lugar de escribirlo a mano? Use cualquier representación que esté limpia, sea fácil de trabajar y modifique y luego compile eso en javascript feo pero eficiente para el lado del cliente.

Un árbol de decisión es bastante fácil de representar como datos y es fácil de entender y trabajar como una estructura de datos de árbol tradicional. Puedes almacenar dicho árbol en cualquier forma que tenga sentido para ti. Validarlo y modificarlo como datos también debería ser sencillo.

Luego, cuando necesite usar el árbol de decisiones, simplemente compile/serialice en JavaScript como un gran if-the-else, switch o hash mess. Esto también debería ser bastante directo y probablemente mucho más fácil que tratar de mantener un switch con un par de cientos de elementos.

2

Dado que la situación (como usted ha descrito) es tan irregular, no parece haber una manera mejor. Aunque, puedo sugerir una mejora para tu tabla de saltos. Mencionaste que tienes errores y duplicados. Por lo tanto, en lugar de asignarlos explícitamente a un cierre, puede asignarlos a funciones con nombre para que no tenga que duplicar el cierre explícito.

var doAThingAndAnother = function(){ doAThing(); doAnotherThing(); } 

var tbl; // initialize it with the values 
    ... 
tbl[0x42] = doAThingAndAnother; 
tbl[0x43] = doAThingAndAnother; 

No es una gran mejora, ¡pero es lo único que se me ocurre! Parece que cubriste la mayoría de los otros problemas. Dado que parece que los requisitos cambian tanto, creo que es posible que tenga que renunciar a la elegancia y tener un diseño que no sea tan elegante, pero que sea fácil de cambiar.

5

Veo dos opciones ...

común a ambas soluciones son las siguientes funciones con nombre:

function aThing() {} 
function anotherThing() {} 
function aThirdThing() {} 

La forma interruptor

function exec(bits) { 
switch(bits) { 
    case 0x00: aThing(); anotherThing(); break; 
    case 0x01: aThing(); anotherThing(); aThirdThing(); break; 
    case 0x02: aThing(); aThirdThing(); break; 
    case 0x03: anotherThing(); aThirdThing(); break; 
    ... 
    case 0x42: aThirdThing(); break; 
    ... 
    case 0x7f: ... break; 
    default: throw 'There is only 128 options :P'; 
    } 
} 

El mapa manera

function exec(bits) { 
    var actions = map[bits]; 
    for(var i=0, action; action=actions[i]; i++) 
     action(); 
} 

var map = { 
0x00: [aThing, anotherThing], 
0x01: [aThing, anotherThing, aThirdThing], 
0x02: [aThing, aThirdThing], 
0x03: [anotherThing, aThirdThing], 
    ... 
0x42: [aThirdThing], 
    ... 
}; 

en ambos casos que se dice

exec(0x42); 
+0

no pudo ese bucle ser 'para (var action in actions) action();'? –

+0

Podría pero tendría poco sentido. Las acciones en este caso son una matriz de referencias de función, y no desea bucles sobre las matrices con for (var i in array) porque es mucho más lenta y porque le brindará resultados desiguales en todos los navegadores. Algunos navegadores tratarán la propiedad "longitud" en la matriz como solo otro miembro del objeto y le proporcionarán esa información, así como las referencias de función. –

+0

[] .propertyIsEnumerable ('length') === false – draeton

Cuestiones relacionadas