Futurescale, Inc. PureMVC Home

The PureMVC Framework Code at the Speed of Thought


Over 10 years of community discussion and knowledge are maintained here as a read-only archive.

New discussions should be taken up in issues on the appropriate projects at https://github.com/PureMVC

Pages: [1] 2
Print
Author Topic: State Machine  (Read 21678 times)
Neil Manuell
Courseware Beta
Sr. Member
***
Posts: 109


View Profile Email
« on: October 12, 2008, 02:44:02 »

hi cliff

another one for your very long queue (if you like it) :)

a very simple implementation of a State Machine which I have found very useful in combination with trilec's chain utility to manage my command structures.

code on my google code svn here: http://code.google.com/p/puremvc-utilities/

and a quick tutorial on my blog, here: http://revisual.co.uk/?p=237

cheers
Logged
puremvc
Global Moderator
Hero Member
*****
Posts: 2871



View Profile WWW Email
« Reply #1 on: October 12, 2008, 07:40:17 »

Cool, I'll take a look at this shortly.

-=Cliff>
Logged
puremvc
Global Moderator
Hero Member
*****
Posts: 2871



View Profile WWW Email
« Reply #2 on: October 13, 2008, 01:28:49 »

This looks cool.

I'd refactor a few things to save keystrokes at implementation time, and DRY up the repeated concatenations to create note names within StateMachine.

Change StateNotificationNames to StateConstants, and make it contain:

:
// shorter, friendlier constants :)
public static const CHANGE_STATE:String = "changeState"
internal static const EXIT:String = "exit" // only visible to the package
internal static const ENTER:String = "enter" // only visible to the package

StateMachine gets a method like this:

:
private function getNoteName(state:State, phase:String):String
{
     return  state.name + phase;
}


and does:

:
public function registerStateChangeCommands(enterCommand:Class, exitCommand:Class, state:State):void
{
                       
    facade.registerCommand(getNoteName(state, StateConstants.ENTER), enterCommand);
    facade.registerCommand(getNoteName(state, StateConstants.EXIT), exitCommand);
                               
}
               
public function removeStateChangeCommands(state:State):void
{

    facade.removeCommand(getNoteName(state, StateConstants.ENTER));
    facade.removeCommand(getNoteName(state, StateConstants.EXIT));
                               
}

private function exitState(state:State):void
{
    if(currentState == null) return
    sendNotification(getNoteName(state,EXIT), state);
}
               
private function enterState(state:State):void
{
    viewComponent = state;
    sendNotification(getNoteName(state,ENTER), state)
}


-=Cliff>
Logged
puremvc
Global Moderator
Hero Member
*****
Posts: 2871



View Profile WWW Email
« Reply #3 on: October 13, 2008, 02:38:20 »

Also here:

:
public function changeState(state:State):void
{
                       
    if(currentState && state.name == currentState.name)
                 throw new Error ("The Application is already in this state");
                               
    exitState(currentState);
    enterState(state);
                       
}

I think throwing an Error is a little severe for trying to reenter the same state. I'd opt for a do nothing approach:

:
public function changeState(state:State):void
{
                       
    if(currentState && state.name == currentState.name) return;
                               
    exitState(currentState);
    enterState(state);
                       
}

This stops any bad feedback loop, but doesn't penalize the developer for something out of his control, for instance if the state change happens on a mouse event and the user going back and forth might be generating a stream of mouse events that trigger the state change based on mouse position. If they can just convert the event into a notification and send it, then if the state is the same, it's ignored. Only when it changes will the exit/enter commands be triggered. No harm, no foul.

If the developer is concerned that an attempt to reenter the current state is contrary to the design of their app and wish to flush out those bad calls, then they can subclass, override the method, and throw an error. Or, you could additionally implement:

:
public function changeStateStrict(state:State):void
{
                       
    if(currentState && state.name == currentState.name)
                 throw new Error ("The Application is already in this state");
                               
    changeState(state);
                       
}

-=Cliff>
« Last Edit: October 13, 2008, 02:47:32 by puremvc » Logged
Neil Manuell
Courseware Beta
Sr. Member
***
Posts: 109


View Profile Email
« Reply #4 on: October 13, 2008, 11:40:28 »

cool, will implement those

also thought that it might be handy to send some notifications
ie EXITING_PHASE
TRANSITION_PHASE
ENTERING_PHASE
Logged
puremvc
Global Moderator
Hero Member
*****
Posts: 2871



View Profile WWW Email
« Reply #5 on: October 14, 2008, 07:19:14 »

I'm not sure if the phase notifications might be useful, or just a distraction.  What do you envision their intended use being?

When you execute the command associated with the not name state.name+ENTER, you'd be able to do anything there.

If the util sends an ENTERING_PHASE note first, what would listen for it that wouldn't just as easily go in the command idendified above?

Crosscutting concerns like logging, perhaps? That would keep each command from having to call (or know) the logger.

Would these notes contain the old state and the new state?

-=Cliff> 
Logged
Neil Manuell
Courseware Beta
Sr. Member
***
Posts: 109


View Profile Email
« Reply #6 on: October 14, 2008, 07:39:18 »

well, to tell you the truth, I probably couldn't find a use for such Notifications (which is probably why I didn't have them).  I just figured for completeness. So if you think they are superfluous I'll ditch the idea until someone gives a good reason.
:)
Logged
trilec
Sr. Member
****
Posts: 52



View Profile WWW Email
« Reply #7 on: October 15, 2008, 12:47:55 »

Hi Guys,
Sorry it's been a while since my last post, I've had so many multi-projects going on just finding time to breathe was becoming an issue... :o
I have noticed that the chaining utility has a flaw when assigning multiple commands unless you reregister the mediator
Cliff, is it possible to have a hook into the registration process to allow reinitialization for the notification of interest?
(For this to happen behind the scenes so the programmer doesn't have to do with reregistering mediator)
also it looks like some fantastic work is being done with a state machine from "Fleecie" I'm not sure if he's facing the same issues and look forward to experimenting with this development.
It would be nice to have a PureMVC sanctioned style of state machine and if I can be of help (with what little time I have) it may be good to continue along Fleecie development trunk so as to not fragment and help provide a solidified end product.

As always
keep well
Trilec
Logged
Neil Manuell
Courseware Beta
Sr. Member
***
Posts: 109


View Profile Email
« Reply #8 on: October 15, 2008, 11:48:08 »

re chaining util... does it have to re-register?? does my hack break another aspect? (see your Chaining Utility post) why can't it declare all its interests on initial registration?

re state machine.. go for it :)
Logged
puremvc
Global Moderator
Hero Member
*****
Posts: 2871



View Profile WWW Email
« Reply #9 on: October 16, 2008, 09:42:36 »

After going thru Fleecie's code I think you can go ahead and consider it the sanctioned approach. Its a matter of getting it ready, in the repo, doc'd and demoed.

-=Cliff>
Logged
Neil Manuell
Courseware Beta
Sr. Member
***
Posts: 109


View Profile Email
« Reply #10 on: October 16, 2008, 12:56:55 »

got the demo, but need to do some documenting... am off to Mexico for two weeks though, so I may no to able to do this till I get back
Logged
puremvc
Global Moderator
Hero Member
*****
Posts: 2871



View Profile WWW Email
« Reply #11 on: October 16, 2008, 02:02:29 »

Enjoy the trip. We'll still be here when you get back :)

-=Cliff>
Logged
Neil Manuell
Courseware Beta
Sr. Member
***
Posts: 109


View Profile Email
« Reply #12 on: November 08, 2008, 10:29:48 »

OK, implemented changes, and refactored into the multicore package.

for now, down load alpha from my google code page:

http://code.google.com/p/puremvc-utilities/downloads/list
« Last Edit: November 08, 2008, 10:31:27 by fleecie » Logged
Neil Manuell
Courseware Beta
Sr. Member
***
Posts: 109


View Profile Email
« Reply #13 on: November 09, 2008, 01:07:26 »

hey, just come across the finite state machine discussion group :~/

wondering where my little util comes in to the wider view.
obviously its a very simple lightweight implementation.

also, perhaps I should subclass and add some state history?
Logged
Jason MacDonald
Sr. Member
****
Posts: 243


View Profile Email
« Reply #14 on: November 09, 2008, 03:22:43 »

also, perhaps I should subclass and add some state history?

I was looking at doing exactly that with your utility. And also having some kind of a stateVo to store a few configs in.

I was planning to use your utility to implement a generic set of commands (enter and exit) rather than an individual set of commands for each state. Many of my states share a lot of things in common, and are driven by an XML "template" so they change depending on the XML template driving that particular implementation. Writing concrete commands for each state doesn't work for my implementation  as they are really built using the XML. Something more generic would work well if the XML (templateVO really) could be passed in for each state automagically through some kind of stored VO that was registered when the state was created.

Not sure I'm explaining this well, but in my head it makes sense. I'm basically setting up a "view" with enter command, and tearing it down with exit and then loading the next view. The views are built according to an XML template that loads swf's on to the main view and are positioned through styles that are loaded.

I definitely like the concept though and it provides a great starting place so thank-you for sharing it with us.
« Last Edit: November 09, 2008, 06:09:05 by jasonmac » Logged
Pages: [1] 2
Print