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 ... 5 6 [7] 8 9 10
Print
Author Topic: StateMachine - A PureMVC / AS3 Utility  (Read 105266 times)
puremvc
Global Moderator
Hero Member
*****
Posts: 2871



View Profile WWW Email
« Reply #90 on: March 24, 2009, 04:58:02 »

Personally, I handle view states using Flex.

If you're not using Flex, and need to implement view states, you probably. Want to pick up a copy of the 'Gang of Four' book Design Patterns. (For ISBN, check the PureMVC Best Practices doc, its mentioned at end of the TOC). Or of course, just google 'State Pattern'.

View states are different from application state as   managed by a Finite State Machine. I won't try to explain it all here; for a fine evenings read, contrast the two by checking out the wikipedia articles on State Pattern and on Finite State Machines.

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


View Profile Email
« Reply #91 on: March 25, 2009, 02:50:29 »

this seems to be a question that is asked a lot...
is it possible to pin your last answer up somewhere?? a FAQ page??
Logged
puremvc
Global Moderator
Hero Member
*****
Posts: 2871



View Profile WWW Email
« Reply #92 on: March 25, 2009, 01:47:01 »

True that. I'll try to remember to take care of this tonight.

-=Cliff>
Logged
deltajam
Courseware Beta
Full Member
***
Posts: 25


View Profile Email
« Reply #93 on: March 26, 2009, 12:20:16 »

Cliff, thanks for your reply.

So something like a fullscreen state, would it fall under a view or application state?
Logged
puremvc
Global Moderator
Hero Member
*****
Posts: 2871



View Profile WWW Email
« Reply #94 on: March 26, 2009, 04:16:25 »

That depends. Is there any different functionality available in your fullscreen state?
 
-=Cliff>
Logged
deltajam
Courseware Beta
Full Member
***
Posts: 25


View Profile Email
« Reply #95 on: March 27, 2009, 11:01:25 »

Hmmm.  Well there are different types of fullscreen states in my app.  The one I was mentioning was when on a landing page and transitioning form the normal screen to fullscreen, it adds and removes components.  When say a video component is viewed, it has small, normal, and fullscreen states.
Logged
puremvc
Global Moderator
Hero Member
*****
Posts: 2871



View Profile WWW Email
« Reply #96 on: March 27, 2009, 01:34:34 »

Then you're probably looking to implement view states.

You don't see it much, but the nice thing about Flex and RIA's in general (as opposed to HTML) is that you can easily switch your application to a different configuration of functionality and components depending on the turf available to you.

A common case would be an MP3 player which might have a 'tiny' state that has minimal controls to show you the track name, pause/play, and a button to go to 'normal' state, where you might have a grid with all your tracks, a full transport, and perhaps links to buy the track, etc. The 'fullscreen' mode for a MP3 player is typically a visualization mode where you drop the funky 'spectral analysis' science.

So in the MP3 player those three states are all quite different, and more appropriately handled as application states with the state machine. And of course there may be different view states for the components common to different application states.

-=Cliff>
Logged
devorb
Newbie
*
Posts: 2


View Profile Email
« Reply #97 on: April 11, 2009, 12:13:49 »

Hi Guys,
I was trying to connect the state machine with some unit testing (Fluint and FUnit) and came to the following problem: whenever i want to see if a given state was 'changed' I allways see the previous state. Here is my code:
:
<state name={STATE_REGISTERING} changed={REGISTER_TRY}>
    <transition action={ACTION_REGISTER_OK} target={STATE_REGISTERED}/>
</state>

So I make a listener for REGISTER_TRY and in that function I want to check the state if it's STATE_REGISTERED. But it's not, and the reason is that in StateMachine class:

:
// 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 );

In my code the CHANGED notification upadtes the status variable(I listen for this in a Mediator)
So you see, the notification with my data is coming sooner, and the notification of the state changed is coming later, so my status variable is changing later, so I allways see the previous state first.
So what I did, I replaced the 2 lines with each other, and now my state changes first, then comes my notification where I can check the state...

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

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

Is it an error or am I doing something the wrong way?
Logged
puremvc
Global Moderator
Hero Member
*****
Posts: 2871



View Profile WWW Email
« Reply #98 on: April 11, 2009, 05:23:53 »

:
<state name={STATE_REGISTERING} changed={REGISTER_TRY}>
    <transition action={ACTION_REGISTER_OK} target={STATE_REGISTERED}/>
</state>
So I make a listener for REGISTER_TRY and in that function I want to check the state if it's STATE_REGISTERED. But it's not

You're just interpreting your FSM incorrectly.

In this case, when the StateMachine sends REGISTER_TRY, its current state will be STATE_REGISTERING. Your definition says that REGISTER_TRY is the note to send when the state has fully been changed to STATE_REGISTERING. Further, it says that whenever the action ACTION_REGISTER_OK is sent while in the state STATE_REGISTERING, that we should begin a transition to the state STATE_REGISTERED.

The state specific changed note is sent first by design. It is the last user definable step in the transition, executed once the machine has reached the state in question (the currentState property within the machine has just been updated to the new state at this point) and has with it any data you were tunnelling from the previous state. This is where you should kick off any actions that work with that data or are only executed for this transition.

The more generic StateMachine.CHANGED note is informing you that all user defined notes in the transition (exiting, entering, changed) have been sent and the machine will now become quiescent until a new StateMachine.ACTION is received.

On the StateMachine.CHANGED note, you can, with all certainty, be sure that there is nothing else to be done. If it were switched around as you suggest, then there may or may not be something left to do depending on whether there's a state-specific changed note defined.

I am using both notes successfully throughout my apps at the moment with no odd behavior.

-=Cliff> 

« Last Edit: April 11, 2009, 05:55:53 by puremvc » Logged
Neil Manuell
Courseware Beta
Sr. Member
***
Posts: 109


View Profile Email
« Reply #99 on: April 21, 2009, 05:15:49 »

re: state layout "middle-ware" application
just to say I have finally got round to looking at the flare framework, and it seems pretty straightforward to use (once I got my head around it).
so I might start throwing up some tests (when I find the time).

unfortunate turn of phrase... maybe "throwing out" would have been better.


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


View Profile Email
« Reply #100 on: April 24, 2009, 07:03:25 »

just a thought...

If the StateMachine is queried reguarding the current state during an entering notification, it will return the previous state.

I was wondering if there should be a neutral StateTransitionState, so the transitionTo method would read
something like.

I'm not sure if this would make any major practicle difference but it would be slightly more "truthful".

:

{
            // Going nowhere?
            if ( nextState == null ) return;
           
            // Clear the cancel flag
            canceled = false;
               
            // Exit the current State
            if ( currentState && currentState.exiting ) sendNotification( currentState.exiting, data, nextState.name );
           
            // Check to see whether the transition has been canceled
            if ( canceled ) {
                canceled = false;
                return;
            }

            // makes currentState into a neutral State
            currentState  = new StateTransitionState();

            // Enter the next State
            if ( nextState.entering ) sendNotification( nextState.entering, data );
            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 );
       
        }

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



View Profile WWW Email
« Reply #101 on: April 24, 2009, 12:50:17 »

Actually, after some recent talks with Simon Bailey, I'v been thinking of adding another cancel check after sending the entering note for the next state, but before setting current state to next state. That would give that note some teeth in terms of acting as a given state's entry guard. Why should the exit state be the only side of the transition with a guard.

An exit guard let's you keep users from leaving a state without saving or abandoning edits, for instance.

An entry guard is good for keeping unauthorized persons from accessing certain functionality.

So when that entry guard rejects entry to a state, we wnt to simply abort the transition, remaining in the existing state.

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


View Profile Email
« Reply #102 on: April 25, 2009, 03:08:20 »

yes, that sounds good.
I have stopped using the entering notification for a state in favour of the entered one in 1.1, simply because it has no more value, and actually "lies" about the current state.

Cancelling a transition in the entering state would give it its power back, because I think that its job is a very different one than the entered.

so if you cancel an entry note, the state will revert back to the previous state, and trigger its entering state again (as its state's exiting note will have been sent. )

And if no cancellation is made, there will still be that little lie about the current state. What do you think of a neutral state (that holds previous and next state) to cover the small period between exiting the old state and before entering the new?
Logged
Neil Manuell
Courseware Beta
Sr. Member
***
Posts: 109


View Profile Email
« Reply #103 on: April 25, 2009, 10:03:05 »

like this?
:
protected function transitionTo( nextState:State, data:Object=null ):void
        {
            // Going nowhere?
            if ( nextState == null ) return;
           
            // Clear the cancel flag
            canceled = false;
               
            // Exit the current State
            if ( currentState && currentState.exiting ) sendNotification( currentState.exiting, data, nextState.name );
           
            // Check to see whether the transition has been cancelled in the exiting state
            if ( canceled ) {
                canceled = false;
                return;
            }
           
            // Enter the next State
            if ( nextState.entering ) sendNotification( nextState.entering, data );

           // Check to see whether the transition has been cancelled in the entering state
            if ( canceled ) {
                canceled = false;
                 if ( currentState.entering ) sendNotification( currentState.entering, data );
            }else{
                 currentState = nextState;
            }
       
            // Send the notification configured to be sent when this specific state becomes current
            if ( currentState.changed ) sendNotification( currentState.changed, data );

            // Notify the app generally that the state changed and what the new state is
            sendNotification( CHANGED, currentState, currentState.name );
       
        }
Logged
puremvc
Global Moderator
Hero Member
*****
Posts: 2871



View Profile WWW Email
« Reply #104 on: April 25, 2009, 10:48:53 »

The thing is when we are entering a state, we're not *really* in that state. If you are 'entering' your office, you're really still in the hallway or the doorway until you're fully in the room, right? At which point it is valid to say that your state has 'changed' from being in the hallway to being in the office' at any time before, you might still bail out and go down the hall to get coffee. And I'm not sure there's any value ti isolating the point in that transition when you're 'in the doorway'; no longer in the hall but not yet in the room. Its like purgatory, what is there to do there, really?

By not changing the current state untill we've triggered the previous state's exiting guard and the next state's entering guard, we can cancel at either point and nothing more need be done. There won't be a re-transition to the previous state because you never left it. If you want to do anything that rearranges the view do it on the 'changed' note for the destination state. That's the first point at which you can be sure you're in the new state.

-=Cliff> 
Logged
Pages: 1 ... 5 6 [7] 8 9 10
Print