Di seguito è riportato un case study sull'utilizzo di JSL Debugger per risolvere un problema. Questo è basato su uno script reale con il problema specificato. Se vuoi vedere il problema nel contesto, ho creato uno script, molto semplificato dall'originale, che mostra il problema. Se desideri "giocare insieme", puoi scaricare DebuggerDemo-SolvingProblems.jsl da JMP File Exchange (profilo SAS gratuito richiesto per il download).
Anche se sto descrivendo lo script originale, i frammenti di codice e le immagini provengono tutti da questo script di esempio. Segui!
Il problema
L'altro giorno, uno script JSL che ha avuto un problema con una sceneggiatura è stato indirizzato a me per chiedere aiuto. La sua sceneggiatura funzionava bene in inglese, ma un tester che eseguiva il suo script in cinese semplificato ha avuto degli errori.
Il problema sembrava essere il modo in cui le stringhe venivano gestite in inglese contro cinese: in particolare, le citazioni sfuggite ( \!" ) erano stati esclusi.
In inglese, ecco una stringa di esempio che è stata costruita:
"dt << Seleziona dove (dt: Numbers == 45 & dt: Pick Strings == \!" South \! ")"
In cinese, la stringa sembrava così:
"dt << Seleziona dove (dt: Numbers == 45 & dt: Pick Strings == South)"
Nota il mancante \ "... \!" in giro Sud , che ha causato errori quando la stringa è stata analizzata e il valore non quotato non può essere risolto.
C'è stato un bug in JMP quando si gestiscono le virgolette all'interno di stringhe in lingue diverse dall'inglese?
Primo sguardo
Mi ha mandato la sceneggiatura e i dati necessari per eseguirla. La sceneggiatura era poco meno di 900 righe e ha prodotto un rapporto interattivo. Le prime 130 linee sono state impostate, le linee 131-886 hanno definito le espressioni, e quindi il resto dello script ha usato quelle espressioni.
La prima cosa che ho fatto è stata eseguire la sceneggiatura in inglese e poi in cinese, per vedere se avessi lo stesso problema. L'ho fatto. Poi l'ho eseguito in francese, che ha confermato che il problema era con qualsiasi lingua non inglese, non solo cinese. Ho eseguito il resto dei miei test in inglese e francese, perché il francese è più facile da leggere rispetto al cinese.
MANCIA: È facile cambiare la lingua su cui esegui JMP su Windows. Seleziona File> Preferenze e seleziona la categoria specifica di Windows. In alto, seleziona una lingua in Visualizza lingua. Su Macintosh, prima chiudi JMP, quindi apri Preferenze di Sistema (nel menu Apple) e seleziona la categoria Lingua e testo. Trascina una nuova lingua in cima alla lista. Non chiudere questa finestra! Imposta la lingua per il tuo computer. Avvia JMP e verrà eseguito nella prima lingua nell'elenco. Al termine, esci da JMP e trascina verso l'alto l'inglese (o qualsiasi altra lingua in genere utilizzi sul tuo computer). Ora è sicuro chiudere la finestra delle Preferenze di Sistema.
C'erano diverse linee che costruivano la stringa sopra, e tutte facevano affidamento su una codifica abbastanza complessa che sarebbe stata dura e dispendiosa in termini di tempo per eseguire riga per riga, entrare e uscire da più espressioni e capire cosa stavo guardando.
Eseguendo solo le linee di costruzione delle stringhe appropriate (dopo che lo script era stato eseguito una volta per inizializzare tutte quelle variabili) ha dato gli stessi risultati in tutte le lingue, con le virgolette di escape utilizzate correttamente. Tuttavia, le righe che formavano la stringa utilizzavano valori da due tabelle di dati più un terzo che era stato costruito dai primi due, ed era molto difficile capire a colpo d'occhio dove venivano create e popolate tutte le variabili utilizzate.
In altre parole, questo era un lavoro per il debugger JSL!
Inserisci il debugger JSL
Eseguendo JMP in inglese, ho aperto lo script e ho fatto clic su Debug. Dato che ho già eseguito lo script, tutte le sue variabili sono state elencate in Globals. E ce n'erano molti, troppi da tracciare mentre mi muovevo attraverso la sceneggiatura. (Potrei anche averlo scoperto correndo Mostra i Globali () e guardando il log crescere molto a lungo.)
Questo era tutto ciò che avevo bisogno di sapere in quel momento, quindi ho lasciato il debugger JSL e chiuso e riavviato JMP in modo che il mio ambiente fosse ora completamente pulito. Ho aperto lo script e riavviato il debugger.
Mi interessava solo la stringa che si stava costruendo, quindi ho aggiunto quella variabile alla mia lista di controllo. Per fare ciò, ho selezionato la variabile nello script come mostrato nel debugger JSL, facendo clic con il pulsante destro del mouse e selezionando Aggiungi orologio.

Ho aggiunto un punto di interruzione sulla prima riga dopo che la parte di configurazione è stata completata (riga 131 nell'originale, riga 34 nel mio esempio) e un'altra nella prima riga di istruzioni "reale" dopo che tutte le espressioni sono state create (riga 887 nel originale, questo non esiste nel mio esempio). Per fare ciò, ho cliccato accanto al numero di riga nello script mostrato nel debugger.

MANCIA: Un punto di interruzione funzionerà solo se lo si posiziona su una linea che esegue un'azione. Un punto di interruzione su una riga vuota, una riga che contiene solo una parentesi chiusa o una linea che viene commentata verrà ignorata.
Ho eseguito la prima parte di "setup" e ho visto che la mia variabile di stringa non era ancora stata creata. L'ho imparato con un clic, molto più rapidamente di quanto avrei dovuto eseguire manualmente lo script riga per riga!
Ho eseguito la seconda parte, che ha semplicemente creato tutte le espressioni.
Ora era tempo di agire.
La "carne" della sceneggiatura era contenuta nella parte inferiore della sceneggiatura originale, in sole 10 righe. La prima parte era un ciclo che chiamava un paio di espressioni (che chiamavano espressioni, che chiamavano espressioni, ecc.). Ho usato il pulsante Step Into per entrare in ogni espressione, per scoprire cosa stava succedendo.
MANCIA: Utilizzo di Passaggio quando un'espressione, funzione definita dall'utente o Includere () vengono chiamati, esegue il codice nella sua interezza, restituisce il risultato e posiziona il punto di esecuzione nella riga successiva. Se non è necessario passare da una riga all'altra, questo è un modo rapido per ignorare ciò che non è necessario. D'altra parte, a volte è necessario vedere esattamente cosa sta facendo quell'espressione, la funzione o lo script incluso. Usa invece Step-in e potrai passare attraverso quel pezzo di codice riga per riga.
risultati
Quello che ho scoperto è che ogni parte della stringa è stata costruita all'interno di un Se () espressione: se la colonna con le informazioni era carattere, allora il valore è stato quotato con le virgolette di escape; in caso contrario, il valore non è stato quotato.
Ciò significava anche che, su quasi 900 righe di codice, mi interessava davvero solo una piccola porzione di 19 righe (che dipendeva comunque dagli altri 800+). Queste linee vengono ricreate (e semplificate) nelle righe 38 - 54 nel mio esempio.
Ho cambiato JMP per girare in francese, chiudere e riavviare, e ho ripreso il debugger.
All'improvviso tutto fu chiaro ...
JMP è localizzato! (Chi lo sapeva?)
Il problema non era con i compiti che hanno costruito la stringa. Il problema che ho visto immediatamente con il debugger è che in francese, la condizione all'interno di Se () espressione che determinava se la colonna era il carattere determinato che la colonna era non personaggio. Per le colonne di caratteri, lo script ha eseguito un punto di codice diverso in francese rispetto a quello in inglese.
In effetti, la condizione in francese sarebbe sempre tornata 0 . La condizione pezzo del Se () espressione è questa (Linee 40 e 48 nel mio esempio):
analizzare ( "DT:" || ColumnNames [ thisCol ] ) << Ottieni il tipo di dati () == "Personaggio"
In inglese, col << Ottieni il tipo di dati () ritorna "Personaggio" per una colonna di caratteri. In francese, ritorna "Caractère" , che non valuterà mai di essere uguale a "Personaggio" .
col << Ottieni il tipo di dati () restituisce sempre una risposta localizzata.
Dal momento che la colonna in questione non è mai stata determinata per essere uguale a "Personaggio" quando viene eseguito in cinese (o in francese o in una lingua diversa dall'inglese supportata da JMP), la stringa è stata costruita come se il valore della cella fosse numerico. E questo era il motivo per cui la stringa in inglese era sfuggita alle citazioni e la stringa in cinese no.
Nota: Sebbene JSL Debugger non mostri i risultati di << Ottieni il tipo di dati () messaggio - solo il risultato del confronto - potrei facilmente uscire dal debugger e selezionare ed eseguire analizzare ( "DT:" || ColumnNames [ thisCol ] ) << Ottieni il tipo di dati () per vedere cosa è stato effettivamente restituito. Il debugger mi ha permesso di trovare il problema in modo rapido e indolore.
Chiamare all'azione
Non c'è alcun bug in JMP: funziona come progettato. Lo script necessita solo di una piccola modifica per funzionare in qualsiasi lingua.
C'è più di un approccio per rendere lo script amichevole tra le lingue. Cosa faresti? Aggiungerò l'approccio che abbiamo adottato per i commenti in una settimana o due.