Dovremmo convalidare una transizione di stato prima di tentare nel modello di stato?

4

Quando si applicano le Pattern di stato le transizioni illegali dovrebbero comportare un'eccezione (o almeno questo è ciò che ho capito da il modello)

So che le eccezioni sono per "comportamento imprevisto" in cui non si suppone che si verifichi un'azione. Gli errori sarebbero più appropriati se l'azione richiesta è comune (es: l'utente immette una password errata)

Ora immaginiamo questo, ho un pannello di amministrazione dove viene mostrato un elenco di ordini e ogni ordine ha 3 pulsanti (Rimborso, Annulla, Riordina) dove ognuno di essi cambia lo stato dell'ordine se l'operazione è consentita.

I 3 pulsanti sono abilitati di default (sto semplificando il mio caso qui perché il mio sistema reale è molto più complesso di quello). Ora un utente può ad esempio premere il pulsante Annulla per un ordine con stato (Annullato) che è una transizione di stato non valida.

  1. Dal momento che mi aspettavo che questa azione di transizione illegale si verificasse sarebbe una convalida prima di tentare di Annulla la linea sia più appropriata?
  2. Se convalido prima della transizione ho ancora bisogno di eccezioni nel modello?
  3. Esiste un approccio migliore all'intero problema (ignorando la disabilitazione dei pulsanti e la convalida del lato client)
posta Songo 07.02.2013 - 12:44
fonte

4 risposte

3

Le misure sul lato client non possono mai risolvere un problema del genere. Anche se si disabilita smth e / o si effettua la convalida, è ancora possibile inviare richieste non valide.

In questo caso disabiliterei il pulsante Cancel nell'interfaccia utente. Quando il server riceve una richiesta di modifica dello stato, la convaliderei sul lato server, ignorare la richiesta se lo stato non è valido e inviare uno stato di errore al client. a seconda della situazione, vorrei anche mostrare un messaggio di errore come The order has already been canceled .

    
risposta data 07.02.2013 - 13:07
fonte
2

Sembra che tu possa convalidare se una transizione è valida prima di tentarla. Penso che dovresti convalidare tutte le transizioni possibili quando mostri l'interfaccia utente e disabilitare i pulsanti che corrispondono alle transizioni non valide. Lasciare che l'utente sappia cosa può e cosa non può fare è una buona cosa.

Ora, se non puoi o non vuoi farlo, e quindi ti aspetti che le transizioni non valide avvengano spesso, allora penso che non dovresti usare eccezioni. Invece, potresti voler usare pattern simile ai vari metodi TryParse() in .Net, dove il valore restituito indica successo o fallimento.

Se decidi di avere metodi separati per la validazione e di eseguire effettivamente la transizione (questo è chiamato pattern di Tester-Doer), allora dovresti comunque usare le eccezioni se si tenta una transizione non valida, perché non puoi garantire che il programmatore che usa questo codice chiama il metodo Tester. Questo modello è anche pericoloso negli ambienti multi-thread, perché la situazione può effettivamente cambiare dopo la chiamata al metodo Tester, ma prima della chiamata al metodo Doer.

    
risposta data 07.02.2013 - 13:24
fonte
0

Se ti trovi in uno scenario client / server, il server deve sempre aggiornare eventuali richieste (in questo caso, richieste di transizione dello stato) che riceve dal client.

L'implementazione lato server deve essere sufficientemente robusta per gestire richieste non valide senza entrare in uno stato non valido o danneggiare i dati. Ci sono vari modi per gestirlo - ad es. il schema del ricordo .

Sebbene le conseguenze delle transizioni non valide siano meno gravi, l'implementazione lato client dovrebbe impedire agli utenti di provare transizioni non valide. La disattivazione dei pulsanti per le transizioni non valide è tipica o potresti addirittura volerli rimuovere completamente.

Mostrare un messaggio di errore è l'opzione di fallback finale quando qualcosa va storto. In questo caso, lo stato client / server non è sincronizzato o un bug nel codice client dove pensa che una transizione sia valida quando non lo è.

Per quanto riguarda l'elaborazione delle transizioni valide sul lato client, puoi semplicemente fare in modo che ogni stato tenga un elenco degli stati a cui può passare.

    
risposta data 07.02.2013 - 15:22
fonte
0

Is there a better approach to the whole problem (ignoring disabling the buttons and client side validation)

Sì. Il pattern non viene implementato correttamente da quello che sto leggendo.

La schermata "elenco degli ordini" deve avere il proprio oggetto di gestione dello stato.

Questa è una classe / oggetto context come si vede nel diagramma delle classi del modello di stato.

Il OrdersList imposta il suo stato generale in base alle selezioni dell'utente, ai clic sui pulsanti e così via. Ogni interazione dell'interfaccia utente dell'utente attiva l'oggetto stato OrdersList da convalidare - perché dopo tutto lo stato dell'interfaccia utente appena modificato - e imposta i booleani interni che indicano noi quali stati sono OK ora. Ogni booleano specifico è cablato nell'interfaccia utente tramite l'oggetto context , quindi la selezione di un ordine (annullato) attiva la convalida di context che sa cancel non è uno stato successivo valido e imposta "cancel boolean" su false. Questo valore booleano imposta direttamente il pulsante Annulla e voilà.

Gli Stati non sanno come o se consentire altri Stati

Questo fa parte del punto del modello di stato.

Un determinato stato sa come convalidare se stesso. Ma come può sapere quali sono i prossimi stati validi senza un contesto? Quel contesto è la schermata "lista degli ordini". Altre schermate nella tua app sono anche "contestuali" di un altro tipo. In che modo nel mondo ogni oggetto / classe di stato può conoscere ogni pulsante e ogni possibilità di interazione dell'utente per l'intera applicazione? Loro non possono! Ogni contesto può avere regole diverse su quali stati sono consentiti. Ecco di cosa tratta la classe context .

If I validate before transition do I still need exceptions in the model?

Nel modello / oggetto contesto sì. In ogni stato, no.

Since I expected that this illegal transition action to occur would a validation before attempting to Cancel the line be more appropriate?

La questione è discutibile ora che vediamo ogni schermo come se avesse il proprio stato. Quindi: l'utente che esegue qualsiasi cosa nelle modifiche dell'interfaccia utente, allora deve convalidare il suo nuovo stato - questo è l'oggetto context in azione qui. Tale convalida dell'oggetto contestuale imposta i controlli dell'interfaccia utente in modo che siano consentite solo le cose valide.

Una chiave è che tutta la convalida, il tutto, è nel tuo modello

L'interfaccia utente, lato client, può avere un minimo di convalida, ma tutta la logica necessaria per determinare lo stato deve essere nel modello "dietro l'interfaccia utente". Il tuo oggetto context guarda ciò che è stato cliccato, selezionato, ecc. E il context decide cosa fare.

Se stai pensando che context potrebbe essere anche Controller nel modello MVC , sospetto che tu abbia ragione

    
risposta data 07.03.2013 - 15:56
fonte

Leggi altre domande sui tag