2011-01-12 12 views
8

Ecco una domanda di dettagli di implementazione per i guru JavaScript.Implementazione di una tabella di decisioni complicata in JavaScript

Ho un'interfaccia utente con un numero di campi in cui i valori dei campi dipendono in modo complicato dai valori di sette bit di input. Esattamente ciò che dovrebbe essere visualizzato per uno qualsiasi dei 128 valori che sta cambiando regolarmente man mano che gli utenti vedono più applicazioni?

In questo momento, ho per questo essere implementato come un albero di decisione attraverso un pettine if-then-else, ma è fragile, secondo le norme e modifiche sorta di difficile da ottenere.

approccio Un'implementazione Ci ho pensato è quello di rendere un array di valori da 0x0 a 0x7F e quindi memorizzare una chiusura in ogni sede -

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

e poi richiamare con

tbl[bitsIn](); 

Questo, almeno, rende la logica decisionale un insieme di compiti.

Domanda: c'è un modo migliore?

(Update:? Holy crap, com'è andata quella linea di 'tag iphone ajax' arrivare lì Non c'è da stupirsi che fosse un po 'sconcertante.)

Aggiornamento

Allora cosa è successo ? Fondamentalmente ho preso una quarta opzione, anche se simile a quella che ho controllato. La logica era sufficientemente complessa che alla fine ho creato un programma Python per generare una tabella di verità nel server (generazione del codice Groovy, infatti, l'host è un'applicazione Grails) e spostare completamente la logica decisionale nel server. Ora il lato JavaScript interpreta semplicemente un oggetto JSON che contiene i valori per i vari campi.

Alla fine, questo sarà probabilmente passare attraverso un'altra iterazione, e diventare dati in una tabella di database, indicizzati dal vettore di bit.

La parte trainata da tavolo è sicuramente stata la strada da percorrere; ci sono già state una mezza dozzina di nuove modifiche nei requisiti specifici per la visualizzazione.

+2

Da quello che ho capito del problema, i vostri pensieri sono refactoring del suono, ma TBH ho Non sono sicuro della tua descrizione, di cosa hai bisogno: P –

+0

Ogni bit determina un'azione specifica? Se è così, perché non eseguire un AND bit sul valore rispetto a [0x01, 0x02, 0x04, 0x08, 0x10, 0x20, 0x40] – draeton

+0

@Martin, il punto è se c'è un altro, più flessibile, modo di farlo rispetto alla mia tabella di lambda. –

risposta

1

Hai considerato di generare il tuo albero decisionale sul server invece di scriverlo a mano? Usa qualunque rappresentazione sia pulita, facile da lavorare, e modificala e poi compila quella per javascript brutto ma efficiente per il lato client.

Un albero delle decisioni è abbastanza semplice da rappresentare come dati ed è facile da comprendere e utilizzare come una struttura di dati ad albero tradizionale. È possibile memorizzare detto albero in qualsiasi forma abbia senso per te. Validare e modificare come dati dovrebbe anche essere semplice.

Quindi, quando è necessario utilizzare l'albero decisionale, è sufficiente compilarlo/serializzarlo su JavaScript come un grande errore if-the-else, switch o hash. Questo dovrebbe anche essere abbastanza semplice e probabilmente molto più facile che provare a mantenere uno switch con un paio di centinaia di elementi.

2

Dal momento che la situazione (come avete descritto) è così irregolare, non sembra essere un modo migliore. Anche se, posso suggerire un miglioramento al tuo tavolo da salto. Hai detto che hai errori e duplicati. Quindi, invece di assegnarli esplicitamente a una chiusura, è possibile assegnarli a funzioni con nome in modo da non dover duplicare la chiusura esplicita.

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

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

Non si tratta di un miglioramento, ma è l'unica cosa che mi viene in mente! Sembra che tu abbia coperto la maggior parte degli altri problemi. Dal momento che sembra che i requisiti cambino così tanto, penso che potresti dover rinunciare all'eleganza e avere un design che non è elegante, ma è ancora facile da cambiare.

5

Vedo due opzioni ...

Comune a entrambe le soluzioni sono le seguenti funzioni denominate:

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

Il modo interruttore

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'; 
    } 
} 

La mappa modo

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], 
    ... 
}; 

in entrambi i casi si chiamerebbe

exec(0x42); 
+0

non è possibile che il ciclo sia 'for (var action in actions) action();'? –

+0

Potrebbe non avere molto senso. Le azioni in questo caso sono una serie di riferimenti alle funzioni e non si desidera eseguire il ciclo su array con for (var i in array) sia perché è molto più lento sia perché fornisce risultati non uniformi tra i vari browser. Alcuni browser tratteranno la proprietà "length" sull'array solo come un altro membro dell'oggetto e vi forniranno sia i riferimenti alle funzioni. –

+0

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

Problemi correlati