From: Jim Weirich Date: 2004-11-04T15:35:54+09:00 Subject: Re: fsmgen 0.1 On Wednesday 03 November 2004 09:03 pm, Mark Probert wrote: > Funny how this happens .. :-) How do you access the state machine, Jim? Several ways. The simplest is to just inherit the FSM and implement the actions as methods ... class TurnStile < TurnStileFSM def alarm_on() ... end def alarm_off() ... end def lock() ... end def unlock() ... end # etc. end ts = TurnStile.new ts.coin # ts.unlock is called ts.pass # ts.lock is called ts.pass # ts.alarm_on is called You can also setup the FSM as a separate object that interacts with your domain object ... class TurnStile def initialize @fsm = TurnStileFSM.new(self) end # Define unlock, lock, alarm_xx as before def person_attempts_to_pass @fsm.pass end end This second way might be better if the FSM events do not map cleanly to your domain object. I'm still playing around with the ideas. > I also came up with a similar scheme before I went to the generator > approach. One of the advantages that I saw to using a YAML file is that > the schema is pretty clean (events, actions, state transitions) and you > only have to implement the actions. Same here, the user needs only implement the actions, the event methods and all the book-keeping is handled automatically. The Ruby syntax is even vaguely reminiscent of Bob Martin's SMC (State Machine Compiler), but with do/end instead of curly braces and colons on the state/event/action names. One of the big advantages of the rubyesque syntax is the ability to specify nested states. For example, perhaps we would like the turn stile to go into repair mode from any of the running states. We could specify that by placing an explicit event line in every running state, or we could do something like this ... state :running do # unless overridden, this event definition applies to # all the nested states. event :service, :repair_mode, :unlock state :unlocked do # as before end state :locked do # as before end end state :violoation do # as before end Now a :service event in either :locked or :unlocked will put the turnstile in repair mode. (Note: the prototype doesn't support nested states at the moment. I'm just speaking hypothetically). Currently the prototype just builds a simple state transition table in the FSM class. But once you have the table built, you can generate any number of implementations (e.g. table-base, case statement based, GOF state pattern). You are not even limited to Ruby, but could generate the FSM in any language (again, similar to SMC). > Then again, that is based on a server > receiving client messages, which may be a different model to the one you > are using. I am not assuming any kind of server implementation. Events are methods on the FSM object and actions are methods on the domain object (which might be the same object!). You would have to add server specific code to my prototype if that's how you were going to use it. > Are you going to publish your StateMachine class? The prototype is research for something I'm writing on state machines. Eventually I plan publish it, but for now it is just an experiment. If anyone is interested, I'm can email them a copy of the prototype. (if you ask by email, use the jweirich@one.net address. My normal email server is a bit flakey over the past day or so) -- -- Jim Weirich jweirich@one.net http://onestepback.org ----------------------------------------------------------------- "Beware of bugs in the above code; I have only proved it correct, not tried it." -- Donald Knuth (in a memo to Peter van Emde Boas)