omaskery / fsm-rs

A simple Finite State Machine library in Rust, define a couple of enums, construct a machine, define some transition behaviours and voila!
MIT License
14 stars 2 forks source link

Added support for transition guards which allow to control transition on certain conditions. #2

Open lyuts opened 8 years ago

lyuts commented 8 years ago

A sample implementation for adding support of transition guards to the state machine. This will allow to define transition conditions and let the transition occur only if all associated guards evaluate to true.

omaskery commented 8 years ago

This is really interesting and unexpected, thank you!

I really like how you've implemented this, much more elegant than I was considering. I'm really interested now because your solution might completely solve a problem I was having in coming up with my own approach:

I had aspirations of adding information to Event and State enums (removing the constraint on them being C-like enums). To explain, I'll use the example situation in the README.md with the coin-operated turnstyle: if I wanted to make it so that the InsertCoin event contained the amount of money inserted, how would this be handled using your transition guard approach?

Thanks again, I really appreciate your help :)

lyuts commented 8 years ago

I think I would have organized the state machine in such a way: Add an intermediate state, MoneyDeposited, or something similar. Let's assume for a moment that we have to insert several coins to unlock, e.g. 2.25$ per entry. InsertCoin event takes us to MoneyDeposited state. Guard sits on a transition from MoneyDeposited to Unlocked state and will let the transition happen only when sufficient amount of money is inserted. To make that happen we need to make sure that on (re)entry to MoneyDeposited state we update the amount inserted so far. Now that brings us to questions how to handle a case when something can be unlocked with a single coin? In that case the same Guard can be reused on the transition from Locked to Unlocked. This is a rough idea.

Also, in my opinion events and states are same for every case and should not contain any information that distinguishes them from other instances of same event/state. I mean, InsertCoin for 50 cents should not be different from InsertCoin of 25 cents. Same idea with states. It is hard to picture it with a turn style example, so I'll just make up an imaginary case with vending machines. Let's say we have a vending machine and we sell goods with different prices. Also, buyers can be of two types, regular buyer and a buyer with a discount card/token/voucher. If we don't overload events and states we can have a single set of states that could handle all types of goods and buyers.