[Estratto dal capitolo 5 del libro di Shneiderman]
E' sensato stendere un progetto completo dell'interfaccia prima di iniziare ad implementarla, anche se e' certo che durante l'implementazione si dovra' cambiare qualcosa.
Quali informazioni descrivono lo stato corrente:
Che valore hanno queste variabili all'inizio.
Quali operazioni l'utente deve poter compiere attraverso l'interfaccia:
Di che parametri hanno bisogno queste operazioni.
Pensare in che modo l'utente invochera' queste operazioni tramite l'interfaccia (tramite bottone, menu'...) e in che modo immettera' i parametri. Questo determina quali dispositivi dovranno essere presenti nell'interfaccia.
L'esecuzione di queste operazioni come modifica lo stato dell'applicazione? e lo stato dell'interfaccia?
Le operazioni hanno sempre senso o ci sono stati in cui certe operazioni non hanno senso?
Ci sono vincoli sui parametri?
Pensare quali controlli sono necessari su operazioni invocate e parametri immessi.
Considerare se opportuno disabilitare i dispositivi corrispondenti a certe operazioni quando nello stato attuale non sono sensate.
Considerare quando e' necessario mostrare messaggi di errore o avvertimento e in che modo.
Quali azioni di ricovero bisogna prevedere? (es. in quali casi offrire possibilita' di tornare indietro con "undo")
Stabilito quali dispositivi servono nell'interfaccia, decidere come organizzarli sullo schermo.
Decidere quali finestre comporranno l'interfaccia, che cosa
conterra' ciascuna finestra e come sara' collocato nello spazio della
finestra.
Strutturare lo spazio della finestra modularmente secondo una gerarchia
di zone e sotto-zone, fino ai singoli dispositivi.
Individuare un insieme di attivita' applicative di interesse, chiamate anche task.
Ogni attivita' per essere portata a termine richiede una serie di operazioni (azioni dell'utente, che provocano reazione dell'interfaccia / applicazione).
La complessita' della serie di operazioni necessaria a compiere un'attivita' e' un indicatore per valutare l'interfaccia relativamente ai fattori umani (facilita' di apprendimento, comodita' d'uso, incidenza di errori).
Bisogna che le attivita' scelte per valutare l'interfaccia siano significative!
Sono stati elaborati vari formalismi, per lo piu' grafici, per descrivere un'interfaccia progettata.
Schizzi di come appaiono le finestre dell'interfaccia, quali
dispositivi contengono e come dislocati.
Utili a fornire descrizione statica dell'apparenza dell'interfaccia.
Uno schizzo per ogni finestra (finestra principale, finestre di dialogo...). Gli elementi di interfaccia non permanentemente visibili (es. menu') sono descritti a parte.
Indicare anche, per ogni elemento attivo di interfaccia, l'operazione o la serie di operazioni compiute nella sua callback.
Descrivono la struttura di menu' a cascata (menu' e sotto-menu').
Analoghi gli alberi per finestre di dialogo a cascata. In pratica descrivono la relazione di dipendenza funzionale tra finestre.
Rappresentazione a grafo dove:
Un'altra variante etichetta gli archi con la frequenza (in percentuale) con cui l'utente compie quell'azione.
Esiste anche versione modulare dei diagrammi di transizione di stato (statecharts).
Un grafo ad alto livello considera uno stato semplificato, dove non si tiene conto di certe variabili.
Un nodo del grafo ad alto livello si puo' espandere in un sottografo che fornisce descrizione piu' dettagliata dello stato, tenendo conto anche delle variabili che non erano state considerate al livello piu' alto.
Adatto a descrivere il comportamento di interfacce che usano manipolazione diretta.
Descrive le attivita' (task) in termini di sequenza di azioni dell'utente e relativo feedback fornito dall'applicazione.
Per ogni task si compila una tabella a tre colonne (azione dell'utente, feedback dell'interfaccia, cambiamento di stato del sistema). Nella tabella si elencano le azioni (con relative reazioni e cambiamenti di stato) che compongono il task, in ordine di tempo.
Per esprimere le azioni e i feedback sono stati proposti linguaggi formali. Noi qui usiamo linguaggio naturale (piu' facile da capire e da ricordare, anche se meno veloce da scrivere).
Importante pero' che il linguaggio usato sia non ambiguo e preciso.
Specificare bene in che cosa consiste l'azione compiuta dall'utente
/ il feedback reso dall'interfaccia e quali sono
gli oggetti sui quali l'azione / il feedback vengono applicati.
Esempi di oggetti sui quali si compie l'azione o il feedback:
Esempi di azioni dell'utente: muovere puntatore su un oggetto, premere / rilasciare tasto del mouse...
Esempi di feedback: evidenziare un oggetto, spostarlo, cancellarlo...
Esempio: task per cancellare un file F tramite manipolazione diretta.
Azioni dell'utente | Feedback dell'interfaccia | Stato interno |
---|---|---|
muovere mouse su icona del file F; premere mouse; |
evidenziare icona del file F; dis-evidenziare ogni altra icona di file evidenziata; |
selected_file = F |
muovere mouse su posizione (x,y); | spostare icona del file F alla posizione (x,y); | |
muovere mouse sul cestino; | spostare icona del file F su icona del cestino; evidenziare icona del cestino; |
|
rilasciare mouse; | cancellare icona del file F; | delete F; selected_file = null; |
Descriviamo un'interfaccia per un'applicazione "calcolatrice" con le operazioni binarie di addizione, sottrazione, moltiplicazione, divisione.
Una sola finestra.
In alto un campo di testo (non editabile) che mostra il valore corrente.
In basso, sistemati secondo uno schema a griglia 4 x 4:
Dagli schizzi del layout poi si ricavera' la gerarchia di contenitori necessaria per realizzare le finestre l'interfaccia.
Variabili dell'applicazione:
Variabili dell'interfaccia:
Stato iniziale: Non esitono ne' i due operandi ne' l'operazione. Non visualizza nulla.
Dai vincoli imposti sono possibili solo 4 stati:
Task "operazione isolata": l'utente immette il primo operando, poi l'operazione, il secondo operando ed infine il comando di esecuzione.
Task "operazioni successive": essendo gia' presente il primo operando (dato dal risultato dell'operazione precedente), l'utente immette solo l'operazione e il secondo operando, e cosi' via...
Task "azzeramento": in qualsiasi momento l'utente puo' cancellare tutto e tornare allo stato iniziale, come se non avesse ancora eseguito nessuna operazione.
Se consideriamo la calcolatrice nella sua realizzazione "tradizionale"
(10 bottoni per le 10 cifre e gli operandi immessi cifra per cifra),
abbiamo le seguenti azioni dell'utente:
immettere una cifra (0..9),
immettere un'operatore (+-*/),
immettere comando di azzeramento (C),
immettere comando di esecuzione (=).
A un piu' alto livello di astrazione, possiamo considerare l'immissione di un numero come un'azione unica (anche se di fatto realizzata con una sequenza di azioni): l'immissione di un numero e' un sotto-task.
Il sotto-task per immissione di un numero inizia quando l'utente preme la prima cifra, continua finche' l'utente preme cifre, termina quando l'utente preme un bottone diverso da una cifra.
Descriviamo le transizioni di stato in modo modulare:
Diagramma di transizione a livello superiore:
Per non appesantire la notazione, le frecce dell'azione di azzeramento
(che da ogni stato portano in s0) sono state omesse.
Diagramma di transizione a livello inferiore che descrive
l'immissione di un numero cifra per cifra.
Di fatto dettaglia il funzionamento interno degli stati s1 ed
s3. Facciamo un solo diagramma "parametrico" sullo stato
di riferimento:
s e' uno stato fra s1 ed s3,
a e' il numero che sto costruendo
(a1 se sono in s1 e a2 se sono in s3).
In ogni stato le azioni corrispondenti a transizioni non previste (es. immettere l'operazione negli stati s0 e s2) sono impedite all'utente disabilitando i relativi bottoni.
Sugli archi del grafo posso annotare anche le abilitazioni / disabilitazioni eseguite.
Quanto scritto sugli archi del grafo confluira' poi nel corpo delle callback per i vari dispositivi.
Esempio: la callback di un bottone operazione prima determina in che stato siamo (sono possibili solo s1 ed s3 in quanto negli altri stati il bottone e' disabilitato). Poi secondo il caso esegue quanto riportato sull'arco s1 --> s2 o s3 --> s2.
Ovviamente in un progetto piu' grosso non si dovra' scendere a questo livello di dettaglio nella descrizione.