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 ... 6 7 [8] 9 10
Print
Author Topic: StateMachine - A PureMVC / AS3 Utility  (Read 107753 times)
Neil Manuell
Courseware Beta
Sr. Member
***
Posts: 109


View Profile Email
« Reply #105 on: April 25, 2009, 11:04:38 »

well, I guess it depends how you define these things.

I would say that if you are going from the hallway into the office you leave the hallway, and enter the office by passing through the doorway. And the doorway is neither in the hallway, nor is it in the room, it is the place that connects them (though I agree that in a synchronous system this transition phase has much less value than in an asynchronous one).

The way I have seen the entering phase is as a preparation phase. You use it to prepare the correct environment for that state, and while its being prepared, you arn't in that state, because its not fully prepared. The entered note indicates this. The exiting state is the same but in reverse. As soon as you start de-preping that state it is no longer in that state, but in a dismantling phase.

As you go through the doorway, you switch the light off in the hallway, then you switch on the light in the office, and walk in (ok, maybe not always in that order but lets stick with it).

It seems that the only use for the entering and exit notes in your suggestion are as a hooks  to allow cancellation of the transition. You can no longer, for example use the entering phase to say, disable interaction, and turn it back on on the exiting, because if the next state's entering phase cancels the transition, the user interaction is not switched off again, breaking state's environmental safety, which is surely the whole point of having a FSM.

Looking again at this, I see that it is the entering phase that can be used only as a cancellation hook. The preparation of the state can be done in the changed note. So you can check whether the conditions are right on entering, when you hit the changed note, disable user interaction, and do what is to de done in that state, then on exiting enable interaction again.  If the next state cancels the transition, the preparation is done on the entered, so the states environment is not compromised.  

OK

So thats alright then.

(though I think that
a) the names of the states are no longer quite as descriptive and
b) it would need good documentation of the phases and the consequences of cancelling in the wrong places.)

Logged
Neil Manuell
Courseware Beta
Sr. Member
***
Posts: 109


View Profile Email
« Reply #106 on: April 26, 2009, 03:53:29 »

no, thats not right, because with your description, on cancellation of a transition, the entered phase will NOT be reinvoked.  OK, I go with the non reinvoking of the entering phase, but if a state's exiting phase has been invoked, its entered phase must be reinvoked if cancelled. Otherwise you can't maintain the state's proper environment

am i making sense?


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



View Profile WWW Email
« Reply #107 on: April 26, 2009, 03:22:14 »

Your considering the exiting and entering notes as being part of the state during which you might do some activity related to that state that you'd have to undo.

What I'm saying is that you use those notes as exiting or entering GUARDs, not 'phases'.

Guards keep you from leaving or entering a state. If you are stopped by the guard, that's it. So don't assume you'll get past the exit guard, and therefore do any teardown on the exiting note only check to see if they can leave.

Nor should you assume you'll get past the entry guard for the next state until you try. Again you may be stopped, and that's it.

If either guard stops you the state doesn't change, period.

Therefore, only on the new state's 'changed' note are you in the new state, and only then do you perform any activities related to being in that state.

This keeps the transition process simple and predictable. No need to re-enter a state you never left from a state you never made it to.

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


View Profile Email
« Reply #108 on: April 26, 2009, 03:44:03 »

OK, cool...
lets say I've navigated the exit guard of a state successfully, and done my teardown.  However the next state's entry guard has forbidden entry. So I am still in the previous state, but I have already torn it down...
how do I overcome this?
Logged
puremvc
Global Moderator
Hero Member
*****
Posts: 2871



View Profile WWW Email
« Reply #109 on: April 26, 2009, 05:16:59 »

By holding off on the teardown intil the state has changed.

For instance let's assume you have a view stack with children like product chooser view and shopping cart view.

Let's say that on the change of state from product chooser view to shopping cart view, you change the index of the view stack to the corresponding view. This happens as either as a result of the state specific-'changed' note or from the StateMachine.CHANGED note.

So in the hideEffect handler for the product browser, ii do any visual outties I want to, and from the hide handler, I kick off any commands that need to run to do logic.

Likewise in the shopping cart view's showEffect handler, I take care of any visual intro, and in the show handler I kick off any logic for getting the data for the new view.

So again there are two bardos that must be crossed before a transition is complete; the exiting and entering guards. Don't count your chickens before they're hatched by doing any teardown or(build up) in anticipation of a state change that may not happen.

Restrict exiting and entering code only contain guard logic (go/no go) logic.

Also, remember that the code that sends the StateMachine.ACTION to initiate a state transition can asume the burdon of doing async user interactions like 'Are you sure you want to exit this state without saving?' And waiting for your cancel or ok before proceeding. This is easy to do while in the stability of a state but not while doing a transition, where a sequence of code is executing

You can always have whatever code would have sent the StateMachine.ACTION instead check if you want to save and handle it before sending the ACTION that kicks of the StateMachine's transition. Then the exiting guard can check a confirmation proxy for the flag that tells it it can go. No async required at that step.

So part of it is not getting too fancy with the guards; let it be as easy for them do decide go/no as it is for the bouncer to decide who to let into the club. Let the guard rely on braun not brains. 'You're not on the list, beat it' or 'I'm sorry I can't let you leave the room, the detective gave strict orders'.

The list maker and the detective have already done their work, the guys guarding the doors are just following orders.

In practical terms, be go don't kick off the state change until your reasonably sure it will go through) and allowing the machine to maintain an atomicity in the transition. Nothing happens unless everything happens. No partial state change undo's to manage.

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


View Profile Email
« Reply #110 on: April 27, 2009, 01:51:09 »

so a change of conception in my head, not necessarily in the code. :)

will need to think about this.
« Last Edit: April 27, 2009, 02:39:39 by Neil Manuell » Logged
Neil Manuell
Courseware Beta
Sr. Member
***
Posts: 109


View Profile Email
« Reply #111 on: April 28, 2009, 02:09:45 »

Just starting a new project, so I'm going to try these potential changes out, see what comes out.
will let you know.

is this what you were thinking:

:
protected function transitionTo( nextState:State, data:Object=null ):void
{
// Going nowhere?
if ( nextState == null ) return;

// Clear the cancel flag
canceled = false;

// send exiting notification for the current State
if ( currentState && currentState.exiting ) sendNotification( currentState.exiting, data, nextState.name );

// Check to see whether the exiting guard has been canceled
if ( canceled ) {
canceled = false;
return;
}

// send entering notification for the next State
if ( nextState.entering ) sendNotification( nextState.entering, data );

// Check to see whether the entering guard has been canceled
if ( canceled ) {
canceled = false;
return;
}

// only change state nownow
currentState = nextState;

// Send the notification configured to be sent when this specific state becomes current
if ( nextState.changed ) sendNotification( currentState.changed, data );

// Notify the app generally that the state changed and what the new state is
sendNotification( CHANGED, currentState, currentState.name );

}


« Last Edit: April 28, 2009, 02:19:44 by Neil Manuell » Logged
puremvc
Global Moderator
Hero Member
*****
Posts: 2871



View Profile WWW Email
« Reply #112 on: April 28, 2009, 09:29:58 »

Yes, this looks correct. The following was the only code change (inserted), right?

:
// Check to see whether the entering guard has been canceled
if ( canceled ) {
canceled = false;
return;
}

If so, you can check in the change and I'll build and rev the project. I'm positive about the 1.1 state of affairs and the usage of exiting being a guard and of entering being essentially useless. As a guard, both notes have an unambiguous reason for being.

Right now, I barely use either of them, relying entirely on StateMachine.ACTION, per-state-'changed' and StateMachine.CHANGED notes to drive the application and it is squeeky clean. I do use the exiting in one place to cancel a transition away from a state, and it works fine. Now, If entering could keep me from transitioning to prohibited states (even if I was ok to leave my previous state), then it would rock.

-=Cliff>
« Last Edit: April 28, 2009, 09:39:29 by puremvc » Logged
Neil Manuell
Courseware Beta
Sr. Member
***
Posts: 109


View Profile Email
« Reply #113 on: April 28, 2009, 09:32:44 »

yep, thats right
Logged
Neil Manuell
Courseware Beta
Sr. Member
***
Posts: 109


View Profile Email
« Reply #114 on: May 06, 2009, 01:41:51 »

have stuck a demo visualisation of the FSM Markup Utiliy I have been working on here:http://revisual.co.uk/?p=501.

Logged
newtriks
Courseware Beta
Full Member
***
Posts: 23


 - newtriks
View Profile WWW Email
« Reply #115 on: May 06, 2009, 06:50:20 »

Cheers guys, I really like this utility and the new logic you have implemented was exactly what I was looking for in a demo I was putting together.  So I have integrated the new code as detailed above in the following post:

Combining the PureMVC StateMachine Utility with Slacker http://cli.gs/pSUVae

Cheers,

Simon

[ Twitter ] @newtriks
[ Blog ] http://www.nutrixinteractive.com/blog/ 
Logged
Neil Manuell
Courseware Beta
Sr. Member
***
Posts: 109


View Profile Email
« Reply #116 on: May 06, 2009, 07:19:58 »

@cliff, I have added the entering guard code in to the svn
Logged
puremvc
Global Moderator
Hero Member
*****
Posts: 2871



View Profile WWW Email
« Reply #117 on: May 06, 2009, 07:51:39 »

@Neil, Re the FSM visualizer - I LOVE IT! If those lines could be annotated (perhaps in italics?) with the actions that trigger the transitions being shown, that would be over the top awesome. Probably be nutty hard to do though if their library doesn't expressly provide for line names. :)

@Simon, heh, any chance you could rename that demo to 'Slack Against the Machine' ? :)

-=Cliff>

Logged
Ondina
Sr. Member
****
Posts: 86


View Profile Email
« Reply #118 on: May 07, 2009, 05:13:51 »

@Cliff

Hmm... you know what? Your demo is not good at all. It distracted me from my goal (learning more about StateMachine). It made me listen to the cool sound tracks and after a while my mind entered in a state of not caring anymore about FSM&Co  :)

O.K.  Back to the earthy state... Thank you for the much awaited demo! I'll come back with questions after trying it.

One little observation, not related to puremvc:
I have an external sound card, that was off by the time I started your demo and that made the app throw an error when I was  trying to select an item. Maybe you should catch this(sound off) somewhere in your code.


@Simon

I'll post my questions regarding your demo in here instead of your blog.

Here the FSM:
var fsm:XML =
<fsm initial={StateConstants.LOAD}>
<state name={StateConstants.LOAD}>
<transition action={ActionConstants.ACTION_LOAD} target={StateConstants.LOGIN}/>
</state>
<state name={StateConstants.LOGIN} exiting={ ApplicationFacade.CHECK_LOGGED_IN }>
<transition action={ActionConstants.ACTION_USER} target={StateConstants.STATE_2}/>
<transition action={ActionConstants.ACTION_ADMIN} target={StateConstants.STATE_3}/>
</state>
<state name={StateConstants.STATE_2} changed={ ApplicationFacade.CHECK_LOGGED_IN }>
<transition action={ActionConstants.ACTION_LOGIN} target={StateConstants.LOGIN}/>
<transition action={ActionConstants.ACTION_THREE} target={StateConstants.STATE_3}/>
</state>
<state name={StateConstants.STATE_3} changed={ ApplicationFacade.CHECK_LOGGED_IN } entering={ ApplicationFacade.CHECK_ADMIN }>
<transition action={ActionConstants.ACTION_LOGIN} target={StateConstants.LOGIN}/>
<transition action={ActionConstants.ACTION_TWO} target={StateConstants.STATE_2}/>
</state>
</fsm>;

1.Why do you need  changed={ ApplicationFacade.CHECK_LOGGED_IN }  in state 2 and 3? You  can be in those states only after a successfully login, right?
2.Then in the LOGIN state I expected it to do something in case the password/username was wrong, because in your CheckLoginStatusCommand you have this:
override public function execute(notification:INotification):void
{
      if( !lgnPrx.login_success ) sendNotification( StateMachine.ACTION, null, ActionConstants.ACTION_LOGIN );
}
I modified it to see what was going on:
if( !lgnPrx.login_success ){
   Alert.show("wrong pw");
   sendNotification( StateMachine.ACTION, null, ActionConstants.ACTION_LOGIN );
} else{
   Alert.show("Hi "+lgnPrx.username);
}
And if login_success==true  then it does say “Hi username”, after logging in.
It is actually normal, because it happens only  on exiting the LOGIN state.
So sendNotification( StateMachine.ACTION, null, ActionConstants.ACTION_LOGIN ); is not doing anything.
Was your intention to cancel the transition to the next state?


The cool thing is: entering={ ApplicationFacade.CHECK_ADMIN }, because I can do something like this:

CheckAdminStatusCommand
...
if( !lgnPrx.userAdmin ) {
sendNotification( StateMachine.CANCEL );
Alert.show("you are not admin");
}
...
when the user with restricted access clicks on the admin button.

Thank you  Cliff, Simon, Neil, gjstrab  for your demos and explanations/posts.

Ondina
Logged

~ Ondina ~
Neil Manuell
Courseware Beta
Sr. Member
***
Posts: 109


View Profile Email
« Reply #119 on: May 09, 2009, 11:04:29 »

More functionality to the FSMVisualisation (we need a name, any suggestions?).
http://revisual.co.uk/?p=517

@Cliff Yes, nutty hard, haven't fond a way to label them actions, but surely there will be. Am thinking of a rollover info box that will show all the info.

functionality now includes adding/deleting states adding/deleting actions.  Very crude at the mo, will whip up something more appealing when I have done more functionality.


Logged
Pages: 1 ... 6 7 [8] 9 10
Print