Implementazione della funzionalità di annullamento / ripristino basata sul contesto

2

Attualmente sto implementando un meccanismo di annullamento / ripetizione usando il Command Pattern. Tutto funziona così lontano. Il mio problema ora è implementare la funzionalità di annullamento / ripristino in modo che sia associata a un determinato contesto.

Assumi la seguente situazione:
Hai win1 e win2 . In win1 esegui action1 ; poi si passa a win2 e si esegue action2 e action3 . "Annulla stack" apparirebbe come segue

  • Action3
  • azione2
  • azione1

Ora cosa succede se win1 viene chiuso / rimosso e inizi a eseguire annullamenti. In action1 il programma probabilmente si arresterà in modo anomalo poiché il contesto è stato eseguito in precedenza (cioè win1 ) non esiste più. Pertanto, quando win1 viene chiuso, tutte le azioni corrispondenti devono essere rimosse dallo "stack di annullamento".

La mia domanda è se esistono già implementazioni / migliori pratiche per implementare correttamente tale scenario? O hai qualche idea?

    
posta Juri 08.03.2013 - 18:04
fonte

3 risposte

2

Cosa succede se win1 viene chiuso / rimosso? Per rispondere a questa domanda, chiedi a un altro: l'azione è reversibile?

1. Caso in cui l'azione di chiusura / rimozione è reversibile:

L'evento di chiusura / rimozione viene registrato nello stack di annullamento e quando l'utente esegue il annullamento, annulla la chiusura / rimozione.

Ad esempio, quando un utente rimuove, tramite l'applicazione, un file win1 , l'app non deve rimuovere il file, ma contrassegnarlo solo come candidato per la rimozione; quindi, un potenziale annullamento deselezionerà il file.

2. Caso di azioni irreversibili:

Se stai parlando di azioni irreversibili, dato che la reversibilità non dipende dalla tua applicazione, quindi affrontala, ad esempio disabilitando i corrispondenti elementi di annullamento.

Ad esempio, stai scrivendo uno strumento che gestisce le server farm e, in un determinato momento, il server win1 è materialmente scollegato dalla rete. In questo caso, l'applicazione non può sostituire il server, poiché richiede l'intervento umano.

L'applicazione dovrebbe quindi adattare il suo comportamento in un modo più intuitivo: annullare o annullare anteriore a quello irreversibile, saltare l'azione irreversibile o qualcosa di radicalmente diverso e innovativo. Spetta al tuo interaction designer venire con il modo più intuitivo.

Questo non è molto diverso da un caso come quando l'applicazione tenta di accedere a un database, ma il database è offline: non puoi fare nulla al riguardo e il modo in cui ti comporti dipende dal contesto preciso.

Esempio:

Facciamo un esempio dal tuo commento: la rimozione di un foglio Excel. Le azioni successive sono:

  1. Cambia la cella A1 nel foglio 1,
  2. Cambia la cella A1 nel foglio 2,
  3. Rimuovi il foglio 1.

Due possibili comportamenti sarebbero:

  1. La reversibilità della rimozione dei fogli. Stranamente, il team di Excel ha scelto di non renderlo reversibile. Mentre questo è probabilmente motivato da alcuni aspetti tecnici che ignoro, questo comportamento è totalmente sbagliato UX-saggio. Come utente, quando per errore distruggo un foglio, mi aspetto di riuscire a recuperarlo premendo Ctrl + Z.

    Non essere in grado di farlo rende rischioso utilizzare Excel, poiché non posso mai sapere cosa potrebbe essere ripristinato e cosa potrebbe comportare una perdita di lavoro. Non è affatto carino.

  2. L'impossibilità di rimuovere il foglio con la perdita del passaggio "Cambia la cella A1 nel foglio 1" nella pila di annullamenti dopo la rimozione. Tecnicamente, non è così difficile. Immagina la seguente struttura:

    class undoEntry
    {
        string text; // Text which is displayed to the user in the undo history.
        sheet? correspondingSheet; // The sheet where the action happened, or null.
        undoAction action; // The action to undo.
    }
    

    Con la proprietà correspondingSheet , puoi passare allo stack degli annullamenti una volta rimosso un foglio ed eliminare le voci che non dovresti più visualizzare.

risposta data 08.03.2013 - 18:18
fonte
2

Chiedo scusa per la negromanzia, ma in realtà ho incontrato squadre che si sono grattate parecchio su questo. Di solito trovo la soluzione molto semplice che usa solo più di una pila: fatta, spedita, riscuota denaro.

Era un po 'scadente, ma di solito è sufficiente e ha senso da una prospettiva UX. Prendi questo esempio da me usando StackExchange adesso. Supponiamo che contemporaneamente stia rispondendo a una domanda SE separata e al multitasking in una scheda separata nel mio browser.

Non voglio annullare Ctrl-Z e iniziare a annullare in modo invisibile le modifiche apportate alle altre mie schede (non vorrei tornare all'altra scheda e rendermi conto che ho invertito per errore tutto il mio lavoro mentre lavoravo in questo) , oppure fare in modo che il mio browser accenda le schede su Ctrl-Z senza che io lo dica esplicitamente per rendere visibili tali modifiche. La mia scheda attuale è il mio "universo corrente" e ha i propri dati locali che vengono invalidati quando chiudo la scheda. Quindi, quando annullo, voglio solo annullare le modifiche nella mia scheda attuale e non nelle altre schede. E la semplice risposta al permettere di avere uno stack di annullamento separato per ogni scheda (o anche un contesto più granulare, in questo caso sospetto che il controllo del testo stesso abbia il proprio contesto e stack di annullamento locale) nel browser, non uno stack di annullamento per domarli tutti con voci che vengono invalidate. Ciò mantiene anche la gestione della memoria stretta e pulita e così via senza questi problemi di invalidazione.

Dovrai perdonarmi se sono un po 'appassionato di questo in quanto il team con cui ho lavorato prima ha iniziato a essere tentato di fare tutte queste cose fantasiose per rilevare l'invalidazione delle voci di annullamento e quando ho sottolineato la UX le preoccupazioni di cui sopra, stavano pensando di avere più "stack pointers" nello stack che possono essere spostati separatamente in base a quale tab / window ci trovavamo. Mi piaceva, "Nooooo! Basta usare più di uno stack di annullamento! Geeeeeeez! !!" :-D Penso di aver preso qualche capello grigio proprio da quello.

Avere uno stack di annullamento separato per ogni finestra dovrebbe essere sufficiente nel tuo caso, visto quello che hai detto qui:

At action1 the program would probably crash as the context is has been executed against previously (i.e. win1) doesn't exist any more. As such, when win1 gets closed, all the corresponding actions should be removed from the "undo-stack".

Se i dati vengono invalidati quando win1 viene chiuso, ciò implica che i dati appartengono alla finestra e non ha senso al di fuori di esso, proprio come con l'analogia della scheda del browser. In questo modo dovresti andare in un altro comando di annullamento / comando come lo vedo io - non confonderli tutti in una pila.

Se queste finestre condividono lo stato e ci sono modifiche al lato della logica di business condiviso sottostante ai dati insieme ai dati locali e specifici solo a una particolare finestra che viene modificata simultaneamente con un'azione di input dell'utente, allora diventa molto più difficile e dobbiamo ripensare molto di più. Ma dato quello che di solito incontro e il problema specifico che stai affrontando ora, ho il sospetto che usare solo più stack di annullamento dovrebbe essere sufficiente, e lo stack di annullamento locale a win1 verrebbe buttato via quando chiudi quella finestra.

    
risposta data 06.12.2018 - 12:58
fonte
0

Il contesto è importante dal punto di vista della programmazione / tecnica, oltre che dall'usabilità. Il tuo commento Excel è un buon esempio. Diversi documenti e quindi fogli di lavoro potrebbero trovarsi nella stessa istanza di Excel e il tuo annullamento li attraverserebbe (supponendo che tu abbia effettuato azioni recenti su diversi), ma ciò non accadrebbe in un'altra istanza di Excel o da Excel a Word.

Gli utenti potrebbero essere in grado di fornire il contesto in cui vedono la linea tracciata con questa funzionalità. Microsoft avrebbe potuto creare questa funzionalità nel contesto di tutte le applicazioni di Office aperte. Non mi piacerebbe che fosse un utente, anche se tecnicamente possibile.

    
risposta data 08.03.2013 - 18:55
fonte

Leggi altre domande sui tag