Una macchina a stati finiti è una soluzione appropriata per questa situazione?

7

Stavo scrivendo un codice di prova come esempio in cui avevo una lezione di lavabiancheria. Ha uno stato di porta che deve essere aperto o chiuso e anche uno stato di funzionamento, acceso o spento. Voglio impedire che lo stato di funzionamento cambi da 'spento' a 'acceso' quando la porta è 'aperta', e impedisce anche che la porta sia impostata su 'aperto' mentre la macchina è 'accesa'.

Ho questa funzionalità con una serie di istruzioni if. Sembra poco elegante e potrebbe trasformarsi rapidamente in codice spaghetti se voglio aggiungere un altro stato che aggiunge condizioni aggiuntive ai cambiamenti di altri stati. Mi chiedo, una macchina a stati finiti è una soluzione per questa situazione? Semplificherebbe aggiungere stati e definire transizioni valide?

    
posta user1936 01.07.2013 - 20:00
fonte

4 risposte

17

Quello che stai vivendo si chiama 'Code Smell' ed è un buon indicatore del fatto che potresti fare qualcosa di sbagliato. Fortunatamente, hai visto il problema e hai già trovato una soluzione eccezionale, quindi non c'è molto da dire qui. Una macchina a stati funziona perfettamente per quello che stai facendo qui.

Disegnarlo potrebbe anche aiutare a cercare e trovare altri stati a cui potresti non pensare (Running, spin cycle, cool down, filling), oltre a permetterti di definire i requisiti di transizione tra stati (probabilmente non vuoi lasciare la porta aperta durante la centrifuga, ma forse lo stato di riempimento consente di aprire la porta per aggiungere indumenti).

Ovviamente puoi essere il più dettagliato o ambiguo che vuoi, fare tutto ciò che si adatta alle tue esigenze!

    
risposta data 01.07.2013 - 20:08
fonte
8

Potresti implementare la tua lavatrice come macchina a stati, ma c'è tanto potenziale per la proliferazione dello stato quanto per le dichiarazioni di if se non fai le cose con attenzione.

Lavorare negli stati richiede una mentalità diversa in cui si pensa in termini di stati (dove ci si trova), stimoli (ciò che si ottiene dall'esterno) e azioni (ciò che si fa). In questo contesto, diamo un'occhiata ad alcune cose nel tuo modello:

A running state, either on or off.

Questi sono i tuoi due stati, che chiamerò WASHING e STOPPED . Aggiungerò un terzo chiamato READY_TO_WASH , che è uno stato arrestato ma pronto per l'esecuzione che vedrai in seguito.

It has a door state that should be open or closed

Questo non è realmente uno stato, ma due stimoli che ottieni da un sensore sulla macchina, che chiamerò door_opened e door_closed . Supponiamo che quando viene applicata la potenza per la prima volta, la lavatrice rileverà lo stato in cui si trova la porta e invierà uno di quegli stiumuli.

Prevent the door from being set to 'open' while the machine is 'on'.

Ciò implicherebbe che oltre al sensore che genera stimoli quando la porta viene aperta o chiusa, c'è anche un fermo che puoi programmare per impedire fisicamente l'apertura della porta. Chiamiamo le azioni che lo controllano door_lock() e door_unlock() .

Prevent the running state from changing from 'off' to 'on' when the door is 'open'

Il passaggio da off a on è basato su uno stimolo proveniente dall'esterno, forse quando l'utente preme i pulsanti corrispondenti sul pannello frontale. Chiamiamo gli stimoli ottenuti da quei pulsanti wash_start e wash_stop .

Per completezza, diciamo anche che c'è un motore nella macchina che esegue il lavaggio effettivo ed è controllabile usando azioni chiamate motor_start() e motor_stop() .

Tutto qui sopra ci fornisce un set completo di informazioni su quali sono gli stati della lavatrice, su quali parti della lavatrice può essere detta e quali stimoli possiamo ottenere dall'esterno. Questo è sufficiente per costruire una macchina a stati, che fai guardando a ciascuno stato e capendo cosa fare in risposta a ogni stimolo.

Lo stato di STOPPED (questo è lo stato "ground", o lo stato che l'FSM immette quando inizializzato):

  • Entrando in questo stato: fai azioni motor_stop() e door_unlock() . Questo mette la lavatrice in uno stato conosciuto, sano di mente.
  • On door_open : non fare nulla. Non ci interessa se la porta è aperta quando è ferma.
  • On door_closed : transizione allo stato READY_TO_WASH .
  • On wash_start : non fare nulla. La porta potrebbe essere aperta. Se è chiuso, non saremo comunque in questo stato.
  • On wash_stop : non fare nulla. Siamo già fermati.

Lo stato READY_TO_WASH :

  • Entrando in questo stato: fai azioni motor_stop() e door_unlock() . Di nuovo, questo assicura che la lavatrice sia in uno stato normale.
  • On door_open : transizione allo stato STOPPED . Se la porta è aperta, non siamo pronti per il lavaggio.
  • On door_closed : non fare nulla. Siamo già pronti e dovremmo essere già inseriti in questo stato.
  • On wash_start : transizione allo stato WASHING .
  • On wash_stop : non fare nulla. Siamo già fermati.

Lo stato WASHING :

  • Entrando in questo stato: fai azioni door_lock() e motor_start() .
  • On door_open : transizione allo stato STOPPED . Non dovremmo ricevere stimoli per le porte in questo stato perché il fermo lo impedisce. Se il latch fallisce e qualcuno apre la porta, ciò fornisce un po 'di sicurezza.
  • On door_closed : come door_open .
  • On wash_start : non fare nulla. Stiamo già lavando.
  • On wash_stop : transizione allo stato READY_TO_WASH . La porta sarà ancora chiusa, quindi siamo tecnicamente pronti a lavarne ancora.
risposta data 03.06.2014 - 20:09
fonte
2

Una macchina a stati finiti, implementata con il schema di progettazione dello stato , è un'ottima soluzione per ciò che stai cercando di fare - per due motivi:

  1. Le transizioni tra stati sono codificate all'interno degli stati stessi. (Possono anche essere codificati nella classe della lavatrice stessa, ma ciò rende più difficile aggiungere nuovi stati e transizioni e può comportare condizionali lunghi e brutti). Quindi è facile tenere traccia delle possibili transizioni da e verso uno stato. Ad esempio se ad es. vuoi impedire una transizione dallo stato "off" allo stato "on" quando la porta è "aperta", tutto ciò che devi fare è nello stato "off", avere la logica di transizione sullo stato "on" avvolto con un condizionale che controlla se la porta è aperta. Nessuna brutta lunga dichiarazione if per fare questo.

  2. L'aggiunta di nuovi stati è semplice e non genera crescenti dichiarazioni di if . Tutto quello che devi fare è aggiungere la logica di transizione al nuovo stato dagli stati che vuoi essere in grado di passare a questo stato. Molto più pulito di un posto centrale che gestisce tutte le transizioni con un lungo codice spaghetti.

Buona fortuna

    
risposta data 03.06.2014 - 00:09
fonte
0

Un'implementazione di macchine a stati finiti sarebbe molto adeguata per il problema che descrivi. È un buon metodo per tutti i problemi con stati permessi o meno. Questo metodo ti aiuta a verificare se l'analisi è corretta e completa.

Non sono sicuro che tu abbia esperienza nel campo delle macchine a stati finiti (e infine nella progettazione di circuiti digitali). Mi piace il seguente tutorial su youtube: Metodologia per la progettazione di macchine a stati finiti

Buona fortuna per il tuo sviluppo. Se hai bisogno di librerie: mi piace usare Foma (libreria C gratuita) e FSM (codice Java).

    
risposta data 02.06.2014 - 20:23
fonte

Leggi altre domande sui tag