|
|
Comments and Discussions
|
|
 |

|
What are these and how are these defined? I'm having a real time picturing the UML state machine for this.
|
|
|
|

|
Does your Statecharts engine support AND-states (concurrent states)?
|
|
|
|

|
Article author wrote: This implementation does not currently support orthogonal states, ... , forks, joins, synch states...
May be, it's possible to run several of these state machines engines in parallel, and that will mimic AND-states.
P.S. I'm exploring issues associated with concurrent state machines too. I wrote a humble article about joins http://www.codeproject.com/KB/architecture/join_pseudostate.aspx[^]. Check it out.
modified on Thursday, February 26, 2009 4:10 PM
|
|
|
|

|
I thought about that. Actually it's not the same. It *is* possible to express AND-states by the product automaton of all substates, but that enlarges the state machine quite alot.
|
|
|
|

|
A well balanced article, reflecting a more comprehensive, compared to flow charts, design approach. My 5.
However, it's really interesting to recall specification description language (SDL) (1980), which provided perfect possibilities to describe a system as a set of communicating processes.
Take a look at http://www.sdl-forum.org/SDL/index.htm
You may also notice SDL stencil in MS Visio.
In my opinion, whatever UML statecharts suggest to meet software design needs, is just a simplified version of SDL constructs (inventing a wheel one more time).
Oleksiy
|
|
|
|

|
Hi !
I also developed a statechart engine myself a few years ago (in 2002 !) in C++ that I ported into C# as an training for this new language (at the time being
My implementation has got those specifications :
* fully supported OMG-UML 1.4 features (See chapters 2.12 and 3.74-3.83) :
- static named events with optional action parameters
- dynamic inherited events with internal data (and optional action parameters)
- guards (conditions on events)
- nested composite states (tree set)
- initial stubstate
- final stubstate / completion transition / completion event (= unnamed event)
- compound multi-level transitions
- internal transitions
- default transition (no event + [else] guard)
- immediate transitions (unnamed event)
- entry/exit actions (nested)
- junction and choice points (static and dynamic branches)
- deep and shallow history pseudostates
- TimeEvent / [after] guard (periodic timers allowed for inner transitions)
- deferred events (be careful to args lifetime)
- compliant to "step to completion" rule (propagated events sent within actions are deferred)
- including of submachines
* extended features :
- self-transitions are allowed for top state
- entry/exit actions are allowed for top state
- able to send asynchronous events to a state machine using the system threads pool and locks
- logging traces and errors to streams
* not yet supported features :
- do activity
* unscheduled features :
- concurrent transitions (region)
- join and fork vertices
- SynchState, [is_in()] guard
- ChangeEvent (boolean)
- [when] guard
|
|
|
|

|
the interface looked like this :
//
// STATE MACHINE ENGINE BASE CLASS
//
#ifndef MOD_CSTATEMACHINE_H
#define MOD_CSTATEMACHINE_H
#include "delegate.h"
//------------- CLASS INTERFACE ---------------
namespace StateMachines
{
// a guard must be true to validate a transition triggered by an event
// (remember that if you declare the same event with different guards
// for a finite state, only one transition path must be true at a time !)
typedef delegate fguard;
// an action is simply a boolean function call with an untyped parameter
typedef delegate faction;
// a function which must return a timeout value in milliseconds
typedef delegate ftimer;
// inherite from this base class to build your own state machines
class CStateMachine
{
public:
// private inner class hidding implementation
class CHandle;
// a event must be unique in a state machine context
// we have two solutions to achieve this goal :
// - declare static events with a name
// - inherate each event you need from a base class
class CEvent
{
public:
operator const char *();
operator bool();
operator == (CEvent &evt);
operator != (CEvent &evt);
// needed internally for STL
operator == (CEvent *evt);
operator != (CEvent *evt);
virtual ~CEvent() {};
protected: friend CHandle;
CEvent(IN const char *name, IN bool need_args);
const char *m_name;
bool m_need_args;
void *m_args;
};
class CDynamicEvent : public CEvent
{
public:
CDynamicEvent (IN const char *name, IN bool need_args = false);
};
class CStaticEvent : public CEvent
{
public:
// to ease user life, reference is made fully automatic
operator CEvent * () { return static_cast(this); }
CStaticEvent (IN const char *name, IN bool need_args = false);
};
// predefined events
static CStaticEvent EVT_NULL; // do nothing but helps generalizing msg pump loops
static CStaticEvent EVT_TIMER; // on WM_TIMER, send EVT_TIMER with event_args equals to msg.wParam (ie. the timer id)
// need to be declared here because of cross references between transition and state classes
class CTransition;
class CTransitionUnnamed;
// a state is a set of transitions to states
// (a state machine is a tree set of states)
virtual class CState
{
public:
operator const char *();
~CState (void);
protected: friend class CHandle;
// Note: VC++ bugs when using ellipses AND default arguments at the same time
bool Set (const char * name,
faction & on_entry,
faction & on_exit,
class CState & upper_state,
class CState & default_state,
class CTransition ** transition);
virtual bool Behave (IN CHandle *Handle, void *event_args) = 0;
const char * m_name;
faction m_on_entry;
faction m_on_exit;
class CState * m_upper_state;
class CState * m_default_state;
// dynamic
class CState * m_last_substate;
class CStateMachine *m_self;
vector m_transition;
};
// abstract class used to make a difference between persistent states and transcient pseudostates
virtual class CSubState : public CState
{
};
// abstract class used to make a difference between persistent states and transcient pseudostates
virtual class CPseudoState : public CState
{
};
class CContainerState : public CSubState
{
public:
bool Set (const char * name,
faction & on_entry,
faction & on_exit,
CContainerState & upper_state,
CSubState & initial_substate,
CTransition * transition,
...);
bool Set (const char * name,
CContainerState & upper_state,
CSubState & initial_substate,
CTransition * transition,
...);
private:
bool Behave (IN CHandle *Handle, void *event_args);
};
class CTopState : public CContainerState
{
public:
bool Set (const char * name,
faction & on_entry,
faction & on_exit,
CSubState & initial_substate,
CTransition * transition,
...);
bool Set (const char * name,
CSubState & initial_substate,
CTransition * transition,
...);
private: friend class CHandle;
bool Behave (IN CHandle *Handle, void *event_args);
// dynamic
class CContainerState * m_including_state;
};
class CIncludeState : public CContainerState
{
public:
bool Set (const char * name,
faction & on_entry,
faction & on_exit,
CContainerState & upper_state,
CStateMachine & substatemachine,
CTransition * transition,
...);
bool Set (const char * name,
CContainerState & upper_state,
CStateMachine & substatemachine,
CTransition * transition,
...);
private: friend class CHandle;
bool Behave (IN CHandle *Handle, void *event_args);
// dynamic
class CStateMachine * m_substatemachine;
};
class CSimpleState : public CSubState
{
public:
bool Set (const char * name,
faction & on_entry,
faction & on_exit,
CContainerState & upper_state,
CTransition * transition,
...);
bool Set (const char * name,
CContainerState & upper_state,
CTransition * transition,
...);
private:
bool Behave (IN CHandle *Handle, void *event_args);
};
class CFinalState : public CPseudoState
{
public:
bool Set (const char * name,
faction & on_entry,
CContainerState & upper_state);
bool Set (const char * name,
CContainerState & upper_state);
private:
bool Behave (IN CHandle *Handle, void *event_args);
};
class CDeepHistoryState : public CPseudoState
{
public:
bool Set (const char * name,
faction & on_entry,
CContainerState & upper_state,
CSubState & default_state);
bool Set (const char * name,
CContainerState & upper_state,
CSubState & default_state);
private:
bool Behave (IN CHandle *Handle, void *event_args);
};
class CShallowHistoryState : public CPseudoState
{
public:
bool Set (const char * name,
faction & on_entry,
CContainerState & upper_state,
CSubState & default_state);
bool Set (const char * name,
CContainerState & upper_state,
CSubState & default_state);
private:
bool Behave (IN CHandle *Handle, void *event_args);
};
class CChoiceState : public CPseudoState
{
public:
bool Set (const char * name,
faction & on_entry,
CContainerState & upper_state,
CTransitionUnnamed * transition,
...);
bool Set (const char * name,
CContainerState & upper_state,
CTransitionUnnamed * transition,
...);
private:
bool Behave (IN CHandle *Handle, void *event_args);
};
// a transition is triggered by an event associated to { a guard, a next state, an action }
class CTransition
{
public:
// used to initialize NO_MORE_TRANSITIONS
CTransition (void);
~CTransition (void);
// evt : the event triggering the transition
// guard : must return true to validate the event and so the transition
// next_state : the next state to the be set as the current active state when transition is validate by the event and guard
// action : the action to be done between the exit and entry actions of the destination state
CTransition (class CEvent & event,
fguard & guard,
class CState & next_state,
faction & action);
// evt : the event triggering the transition
// guard : must return true to validate the event and so the transition
// next_state : the next state to the be set as the current active state when transition is validate by the event and guard
CTransition (class CEvent & event,
fguard & guard,
class CState & next_state);
// evt : the event triggering the transition
// next_state : the next state to the be set as the current active state when transition is validate by the event and guard
// action : the action to be done between the exit and entry actions of the destination state
CTransition (class CEvent & event,
class CState & next_state,
faction & action);
// evt : the event triggering the transition
// next_state : the next state to the be set as the current active state when transition is validate by the event and guard
CTransition (class CEvent & event,
class CState & next_state);
// a transition internal to a state (no state change, no exit/entry action done)
// evt : the event triggering the internal transition
// guard : must return true to validate the event and so the transition
// action : the action to be done inside the current state context
CTransition (class CEvent & event,
fguard & guard,
faction & action);
// a transition internal to a state (no state change, no exit/entry action done)
// evt : the event triggering the transition
// action : the action to be done inside the current state context
CTransition (class CEvent & event,
faction & action);
// default transition if no others matches the current event
// next_state : the next state to the be set as the current active state when transition is validate by the event and guard
// action : the action to be done inside the current state context
CTransition (class CState & next_state,
faction & action);
// default transition if no others matches the current event
// next_state : the next state to the be set as the current active state when transition is validate by the event and guard
CTransition (class CState & next_state);
// default internal transition if no others matches the current event (no state change, no exit/entry action done)
// action : the action to be done inside the current state context
CTransition (faction & action);
// assignment operator needed by vector template
virtual CTransition& operator=( const CTransition &t );
// comparison operators needed by delegate template
operator == (CTransition &transition);
operator != (CTransition &transition);
protected: friend class CHandle;
class CEvent m_event;
fguard m_guard;
class CState * m_next_state;
faction m_action;
// dynamic
UINT_PTR m_timer;
DWORD m_timer_duration_ms; // milliseconds
ftimer m_ftimer;
bool guard_timer (void * event_args);
};
// a transition not triggered by an event but only by its guard
class CTransitionUnnamed : public CTransition
{
public:
// guard : must return true to validate the transition
// next_state : the next state to the be set as the current active state when transition is validate by the guard
// action : the action to be done between the exit and entry actions of the destination state
CTransitionUnnamed (
fguard & guard,
class CState & next_state,
faction & action);
// guard : must return true to validate the transition
// next_state : the next state to the be set as the current active state when transition is validate by the guard
CTransitionUnnamed (
fguard & guard,
class CState & next_state);
// guard : must return true to validate the internal transition
// action : the action to be done inside the current state context
CTransitionUnnamed (
fguard & guard,
faction & action);
};
// a transition internal to a state (no state change, no exit/entry action done) that defers the event to the next state change
class CTransitionDeferEvent : public CTransition
{
public:
// evt : the event to be deferred
// guard : (delegate) must return true for the event to be deferred
CTransitionDeferEvent (class CEvent & event,
fguard & guard);
// evt : the event to be deferred
CTransitionDeferEvent (class CEvent & event);
// a transition internal to a state (no state change, no exit/entry action done)
// that defers the event to the next state change by default
CTransitionDeferEvent (void);
};
// a transition performing an action and a state change when the timeout occured
class CTransitionTimer : public CTransition
{
public:
// duration : value of the timeout in milliseconds
// next_state : the next state to the be set as the current active state when transition timed out
// action : the action to be done between the exit and entry actions of the destination state
CTransitionTimer (
DWORD duration_ms,
class CState & next_state,
faction & action);
// duration : value of the timeout in milliseconds
// next_state : the next state to the be set as the current active state when transition timed out
CTransitionTimer (
DWORD duration_ms,
class CState & next_state);
// ftimer : function which returns the timeout value in milliseconds
// next_state : the next state to the be set as the current active state when transition timed out
// action : the action to be done between the exit and entry actions of the destination state
CTransitionTimer (
ftimer & fduration,
class CState & next_state,
faction & action);
// ftimer : function which returns the timeout value in milliseconds
// next_state : the next state to the be set as the current active state when transition timed out
CTransitionTimer (
ftimer & fduration,
class CState & next_state);
// duration : value of the timeout in milliseconds
// action : (delegate) the action to be done between the exit and entry actions of the destination state
CTransitionTimer (
DWORD duration_ms,
faction & action);
// ftimer : function which returns the timeout value in milliseconds
// action : (delegate) the action to be done between the exit and entry actions of the destination state
CTransitionTimer (
ftimer & fduration,
faction & action);
};
static CTransition NO_MORE_TRANSITIONS;
// fire an event with or without args to a state machine (in the current thread context)
bool Fire (IN CEvent &event, void *event_args = NULL);
// retrieve the variable parameters as a (va_list *) in action function
// (be careful, events can't be deferred because args are not persistent)
bool Fire (IN CEvent *event, ...);
// send an event with or without args to a state machine internal thread
// event pointer must be allocated with "new" and args must be persistent
// Note that whether a Send() is called within an action,
// the event will be deferred to comply with the "step to completion" rule
bool Send (IN CEvent *event, void *event_args = NULL, bool high_priority = false);
// used usually in an action transition for forwarding the event to sub-machines
// (may also be the last sent if not called within an action function context)
CEvent * GetCurrentEvent (void);
// used in guards to synchronize concurrent machines
bool Is_In (IN CState &state);
// return the state machine name
operator const char *();
// useful to add traces in actions
void Error (IN char *printf_format, ...);
void Trace (IN char *printf_format, ...);
CStateMachine::CStateMachine (IN CTopState &top_state,
IN char *name = "",
IN FILE *traceout = NULL,
IN FILE *errorout = NULL);
virtual CStateMachine::~CStateMachine ();
// initialize the machine at its initial active state
// and within or not its own thread
bool Run(bool thread = false);
private: friend CHandle; friend CIncludeState;
CHandle *Handle;
};
}
#endif // MOD_CSTATEMACHINE_H
|
|
|
|

|
Declaration of a StateChart would look like this :
class CSMTest::CHandle : public CStateMachine
{
public: friend CSMTest;
// finite list of states
CTopState TOP_STATE;
CContainerState STATE_1;
CDeepHistoryState STATE_1_H;
CSimpleState STATE_1_1;
CSimpleState STATE_1_2;
CSimpleState STATE_2;
// prototypes of the transition functions
bool Process_Interrupt (MSG *args);
bool Ack_Interrupt (MSG *args);
bool Set_State_High (MSG *args);
bool Set_State_Low (MSG *args);
bool Count_Signal (va_list *args);
bool Timeout_Occured (MSG *args);
bool Entry_Action (MSG *args);
bool Exit_Action (MSG *args);
DWORD Timer_Duration (void *event_args);
// a template to help casting devired class transition functions
// to its CStateMachine parent class generic prototype
template
faction CSM_ACTION(PARAM_TYPE f) { return faction(*this, reinterpret_cast(f)); }
// a define to help casting devired class guard functions
// to its CStateMachine parent class generic prototype
template
fguard CSM_GUARD(PARAM_TYPE f) { return fguard(*this, reinterpret_cast(f)); }
// a define to help casting devired class timer functions
// to its CStateMachine parent class generic prototype
template
ftimer CSM_TIMER(PARAM_TYPE f) { return ftimer(*this, reinterpret_cast(f)); }
// ctor/ dtor
CHandle::CHandle (char *name, CSMTest *self);
};
// ---- declaration of static data members ----
CStateMachine::CStaticEvent CSMTest::EVT_INTERRUPT ("EVT_INTERRUPT");
// ---- declaration of the transition functions ----
bool CSMTest::CHandle::Process_Interrupt (MSG *args)
{
return true;
}
bool CSMTest::CHandle::Ack_Interrupt (MSG *args)
{
return true;
}
bool CSMTest::CHandle::Set_State_High (MSG *args)
{
EVT_PULSE *event = (EVT_PULSE *) GetCurrentEvent();
Trace("w = %lu, l = %lu", event->m_msg.wParam, event->m_msg.lParam);
return true;
}
bool CSMTest::CHandle::Set_State_Low (MSG *args)
{
EVT_PULSE *event = (EVT_PULSE *) GetCurrentEvent();
Trace("w = %lu, l = %lu", event->m_msg.wParam, event->m_msg.lParam);
return true;
}
bool CSMTest::CHandle::Count_Signal (va_list *args)
{
MSG msg = {0};
msg.wParam = va_arg (*args, WPARAM);
msg.lParam = va_arg (*args, LPARAM);
Trace("w = %lu, l = %lu", msg.wParam, msg.lParam);
return true;
}
// generic entry action
bool CSMTest::CHandle::Entry_Action (MSG *args)
{
return true;
}
// generic exit action
bool CSMTest::CHandle::Exit_Action (MSG *args)
{
return true;
}
DWORD CSMTest::CHandle::Timer_Duration (void *event_args)
{
return 5000;
}
bool CSMTest::CHandle::Timeout_Occured (MSG *args)
{
Trace ("Timer occured !");
return true;
}
/***********************/
/* FONCTIONS PUBLIQUES */
/***********************/
CSMTest::CSMTest (char *name)
{
m_Handle = new CHandle (name, this);
if (m_Handle->Run(true) == false)
throw;
}
CSMTest::CHandle::CHandle (char *name, CSMTest *self)
: CStateMachine (TOP_STATE, name, stdout)
{
TOP_STATE.Set (
"TOP_STATE", CSM_ACTION (Entry_Action), CSM_ACTION (Exit_Action), STATE_1,
&NO_MORE_TRANSITIONS
);
STATE_1.Set (
"STATE_1",CSM_ACTION (Entry_Action), CSM_ACTION (Exit_Action), TOP_STATE, STATE_1_1,
new CTransition ( EVT_INTERRUPT, STATE_2, CSM_ACTION (Process_Interrupt) ),
&NO_MORE_TRANSITIONS
);
STATE_1_1.Set (
"STATE_1_1", CSM_ACTION (Entry_Action), CSM_ACTION (Exit_Action), STATE_1,
new CTransition ( EVT_PULSE(), STATE_1_2, CSM_ACTION (Set_State_High) ),
new CTransition ( EVT_SIGNAL(), CSM_ACTION (Count_Signal) ),
&NO_MORE_TRANSITIONS
);
STATE_1_2.Set (
"STATE_1_2", CSM_ACTION (Entry_Action), CSM_ACTION (Exit_Action), STATE_1,
new CTransitionDeferEvent ( EVT_INTERRUPT ),
new CTransition ( EVT_PULSE(), STATE_1_1, CSM_ACTION (Set_State_Low) ),
new CTransitionDeferEvent ( EVT_SIGNAL() ),
new CTransitionTimer (CSM_TIMER (Timer_Duration), STATE_1_1, CSM_ACTION (Timeout_Occured) ),
&NO_MORE_TRANSITIONS
);
STATE_1_H.Set (
"STATE_1_H", CSM_ACTION (Entry_Action), STATE_1, STATE_1_1
);
STATE_2.Set (
"STATE_2", CSM_ACTION (Entry_Action), CSM_ACTION (Exit_Action), TOP_STATE,
new CTransition ( EVT_END_OF_INTERRUPT(), STATE_1_H, CSM_ACTION (Ack_Interrupt) ),
new CTransition ( EVT_SIGNAL(), STATE_1 ),
&NO_MORE_TRANSITIONS
);
}
CSMTest::~CSMTest (void)
{
// this will automatically delete all allocated states and kill thread
delete m_Handle;
}
bool CSMTest::Send (IN CStateMachine::CEvent *event, IN void *args)
{
return m_Handle->Send (event, args);
}
|
|
|
|

|
And usage :
void main (void)
{
CSMTest Test("TEST");
UINT choice;
MSG msg;
msg.wParam = 1;
msg.lParam = 2;
do
{
cout << "WM_QUIT = 0" << endl
<< "WM_INTERRUPT = 1" << endl
<< "WM_END_OF_INTERRUPT = 2" << endl
<< "WM_PULSE = 3" << endl
<< "WM_SIGNAL = 4" << endl
<< "Send : ";
cin >> choice;
switch (choice)
{
case 1:
// sending a static event
Test.Send (CSMTest::EVT_INTERRUPT);
break;
case 2:
Test.Send (new CSMTest::EVT_END_OF_INTERRUPT());
break;
case 3:
Test.Send (new CSMTest::EVT_PULSE(&msg));
break;
case 4:
Test.Send (new CSMTest::EVT_SIGNAL(1, 2));
break;
}
}
while (choice != 0);
}
|
|
|
|

|
Sounds very full-featured. Perhaps that would make a good submission for CodeProject.
gschultz
|
|
|
|

|
StateChart has recently (like about 3 to 4 years) come upon the scene as a very useful and valuable alternative to FlowCharting. It describes the various stages every application go through when being used (meaning, when the application is running). Those stages are what StateCharts present as 'states'.
Describing 'states', forces everyone involved in the developmental stage of the project to focus (in a sort of hierarchical manner) on what the application is suppose to accomplish every step of the way, and the order in which those steps are to be followed.
Whether you are a user, analyst, programmer, or the person who writes up the schedule when certain programs get run, StateChart has a place for everyone to participate in the entry of their specific set of information.
On the surface the entire concept might appear rigid and not very flexible, but that is not true. There is enormous flexibility in the methodology that is very much in sync with OOD and OOP. Therefore, whether you know it or not, if you are programming in Windows, or using Visual C++, or any Object Oriented language, you are already writing your programs according to 'states', and StateChart is the method through which you can record and show how your applications function to whatever level of detail you wish to describe it.
Personally, I have just started using StateCharts recently (like a few months ago), and there's no turning back for me when it comes to describing and explaining how one program, a group of programs, or an entire system functions.
It is a very productive methodology to become acquainted with and use, especially for those times when things in your program (or system) are not working well and you need something solid on which to fall back on. Best of all, the learning curve is not very difficult since almost everything about it is repetitive.
Picture a mosaic with each piece of the mosaic a 'state'. You describe each particular piece, where it's located, how to get there, and where next from there you go. That's StateChart!!
William
Fortes in fide et opere!
-- modified at 12:26 Tuesday 30th August, 2005
|
|
|
|

|
How is this different from sequence diagrams? I've always found those really, really useful, and I'm not really familiar at all with state charts.
¡El diablo está en mis pantalones! ¡Mire, mire!
Real Mentats use only 100% pure, unfooled around with Sapho Juice(tm)!
SELECT * FROM User WHERE Clue > 0
0 rows returned
Save an Orange - Use the VCF!
|
|
|
|

|
Sequence diagrams are like flowcharts, or Finite State Machines.
With flowcharts, situations can quickly become overcrowded and confusing since the person drawing the flowchart might (from time to time) succumb to the temptation of (at one time) become really detailed about the logic flow he/she is presenting, and then at other times become less detailed. IOW, there could be a mixture of more detailed, less detailed, kind of detailed, not as detailed, and a whole variety of ways the behavior of what you're presenting can become. IOW, it is not uniform, plus there could be a lot of repetition of paths you're describing (which is what would cause it to become overcrowded and confusing).
With State Machines (DFSM, or NFSM) you don't have the same problem as flowcharting because you are confined to one level of detail: States. The drawback one has when dealing with FSM, is the lack of tools (or primitives, like descriptive notations) that would allow you to describe what you're trying to do to any level of depth that you might want to analyze what it is you're doing. IOW, FSM sort of force you to remain at a high level of description for what it is you're trying to do.
Enter StateCharts: It forces you to retain the 'state' level of description for what it is you're trying to describe (which is very good), but it also offers you the necessary notations that would allow you to get down as deeply as you wish to go in doing your analysis. So you have rigidness at the 'state' level, but enormous flexibility to describe however deeply you wish to go in your analysis (because at each level of depth, you must apply the behavior of 'state').
With StateCharts you have the best of both worlds. You have the discipline of sticking to 'state' description, and you also have the flexibility of going however detailed you wish to go.
William
Fortes in fide et opere!
-- modified at 18:22 Tuesday 6th September, 2005
|
|
|
|

|
Sequence diagrams are most similar to flowcharts, in that they show the sequence of invocations of methods/routines. Unlike flowcharts, which can sprawl out in two dimensions, sequence diagrams designate that the vertical dimension (usually) shows time/order of invocation, while the horizontal dimension (usually) shows different objects. This makes sequence diagrams easier to organize and read than flowcharts. (I haven't drawn a flowchart in almost 20 years!)
Statecharts (and finite state machines) show "state", i.e., the stable modes or situations that a piece of code or a system can be in, along with the transitions between those states. So a statechart for a traffic signal would have states {green, yellow, red}. An invoice might have the states {created, mailed, paid, written-off}. Statecharts would then show what could cause transitions among those states.
gschultz
|
|
|
|

|
Hey WREY, take also into account that FlowChart are perfectly representative of the way Imperative languages works, whereas StateChart are perfect towards Functional languages. I think if Functional languages were more widely known and used, StateChart would also have more success because more easily usable and mirror-copy of the code...
Kochise
In Code we trust !
|
|
|
|

|
WREY wrote: StateChart has recently (like about 3 to 4 years) come upon the scene as a very useful and valuable alternative to FlowCharting...
StateCharts are an addition to FlowCharts, rather than alternative. StateCharts display the big picture better than flowcharts, and they are better suited for describing interactive systems. FlowCharts are more useful for describing the fine details, e.g. how a particular state responds to a particular message.
|
|
|
|
 |
|
|
General News Suggestion Question Bug Answer Joke Rant Admin
|
This lightweight class allows you to easily implement a UML statechart in C++.
| Type | Article |
| Licence | |
| First Posted | 22 Aug 2005 |
| Views | 59,903 |
| Downloads | 1,503 |
| Bookmarked | 38 times |
|
|