Category Archives: Moe

The Beauty of the Open/Closed Principle

It’s good to be SOLID. Of the principles that make up SOLID, I’ve found the Open/Closed Principle (OCP for short) to be one of the more difficult. There are plenty of explanations around the web, but while identifying the presence or lack open/closed is easy, it’s tougher to achieve.

I also use OCP from the micro to macro scale. It can be applied to classes or it can be applied at a module/library level. Most material on the web covers the easier class level OCP. I’d like to cover the latter using some changes made recently to the Moe state machine library.

The Problem

On my current project, I encountered a great place to use a state machine to simplify a bunch of code. The usage of the state machine itself was interesting and I hope to post about it soon. From a Moe standpoint, I found that the way state actions were implemented didn’t suit my needs. First, I didn’t want to centralize enter/exit actions, particularly at the time of construction. Beforehand, you would add entry and exit actions when you built your state machine. This would mean they were all in a single chunk of code, or you would have to pass the builder around. Not ideal. Second, I also wanted to swap out these actions on demand. When the state machine wasn’t in use, I wanted to disconnect state actions so windows didn’t appear based on wayward events (ie, a late arriving error event from a webcam we were using).

The Solution

I revisited Moe to add the functionality I wanted. What I envisioned was a convention for state actions. Any class could have methods following the form “OnEnter” and “OnExit”. These methods would auto-magically be invoked upon entering and exiting states. These classes could also be added or removed as listeners at any time. I decided to call this functionality state delegates.

While working on Moe previously, I had done a lot of work to support the OCP and this can be seen in the Moe.StateMachine.Extensions library. In that library you can find several helpful additions for Moe, such as logging, state watchers, timers, and asynchronous state machine execution. I specifically wanted that functionality to exist outside of the core state machine. Would the hard work of that refactoring pay off and allow me to add state delegates?

The Changes

You can see the changes that were made in this commit. The solution was to add a traffic cop that would wire up to every state and intercept state enter/exits. When one of those happened, the StateDelegatePlugIn would run through the current listeners and delegate to any methods matching the state name.

This huge addition to functionality (in value, that is) was achieved without touching the state machine at all. This is the OCP on a larger scale. We’ve added valuable functionality to a library without modifying the library itself.

How to move towards OCP

It’s tough, if not impossible, to produce code supporting the OCP from the beginning. Before we can abstract, we need to SEE at least a few examples of usage first. If you were to go back and look at past commits, you’d find several that are focused on refactoring to the OCP after several functional additions were already in place. To begin with, the functional additions were intertwined with the state machine itself. By unwinding those dependencies, I was achieving OCP through actual usage. It would have been too much for my brain to try and see the resulting patterns and needs without already having multiple examples.

When I do something like this, I’m looking to make core classes as simple as possible, keeping as close to the Single Responsibility Principle as I can. Something that I should have done earlier was introduce the Extensions library. By forcing myself to move functional additions to a separate assembly, I would have no choice but to support OCP. When thinking of simplifying or SRP, think of the grand Unix commands. Grep, sed, sort, and so on. Have your components do one thing and do it well.

More Moe

In the last post, I introduced you to Moe the State Machine.  In this post, we’ll explore some more of Moe’s basic functionality, and some of its extended functionality.

Builders and current context

When using the state builder, it is important to understand that the actual builder context will change as you add statements.  For instance, consider the statechart at right.  We have a superstate that has two children state, ChildA and ChildB.  To create ParentState and ChildA, we can use the following code:


StateMachineBuilder stateBuilder = new StateMachineBuilder();
stateBuilder.DefaultTransition("ParentState");
stateBuilder.AddState("ParentState")
    .DefaultTransition("ChildA")
    .AddState("ChildA")
         .TransitionOn("SWITCH").To("ChildB");

The AddState(“ParentState”) moves us into a builder for that state, where we set the default transition to ChildA.  While still in this context, we call another AddState(“ChildA”) which makes it a substate of ParentState.  The TransitionTo() of ChildA takes us to another context, that of the Transition context.  Here we can specify where to transition, and guard clauses.  Under certain circumstances, the builder context can shift back to the parent.  For instance, from the Transition context, an AddState would automatically move up to the ChildA context (adding a child state to the child state, not what we intend for ChildB).

To get ChildB, we need to start again with ParentState and add another child state.  We can get to any state’s context (created already or not) by using the StateMachineBuilder’s indexer like this:


stateBuilder["ParentState"]
     .AddState("ChildB");

What if I don’t want to change state?

Transitions can have guard clauses.  These are nothing more than conditional transitions.  By combining multiple transitions together (and being very careful with your logic), you can use guarded transitions to make branching transitions (going to different states based on some other factor).  Each of the three types of transitions supported (regular, default, and timed transitions) can have a guard clause specified with the .When() syntax of the fluent interface.  All that is specified in the When method is a Func<bool>.  It is up to you, the developer, to specify what the condition.  A guarded transition might look like this:


stateBuilder["ChildB"]
     .TransitionOn("SWITCH").To("ChildA").When(() => SystemInError());

In this case, we have a method returning a bool named SystemInError.  By putting multiple transitions together with guard clauses, we can conditionally branch transitions.

There is no restriction on transitions to states, any state may be chosen, including the originating state.  In the case of a loopback transition, the effect will be the OnExit and OnEnter actions will be executed.

You think you’re funny Mr. State?  You’re going to Timeout!

A common feature of state machines, in particular HSMs, are the notion and use of timers.  These timers are associated with a state, and upon entry to that state become active.  After a specified amount of time, the state machine will fire an associated transition.  In the Moe sample application, timers are used to signal a chance for the stop light.  For longer running operations, a timer can initiate a timeout for an operation that has taken too long.

It is easiest to think of a timeout as a regular event transition that is fired automatically after a specified period of time.  A timeout can be set up like this:


stateBuilder["ChildB"]
     .Timeout(1000, "ErrorState");

Timeouts may also have guard clauses.  In this case, the timeout will fire once, and if the guard is false, will not fire again.

Where have I been?

When Harel introduced statecharts, he included the idea of History states.  As history state is a means of exiting some state, and when directed back to that state’s history, to traverse to the state upon last exit.  There are two forms of history, deep and shallow.  A deep history will go to the last absolute leaf state, whereas a shallow history will go only to the immediate child node.   From there, any default transitions will occur leaving you in a leaf state.

Remember, you cannot be only in a superstate, you must always be in a leaf state.

History states are handled specially, here is how you would wire together a deep history, as opposed to the default shallow history.


stateBuilder["ParentState"].AddDeepHistory();
stateBuilder["CousinB"].TransitionOn("SWITCH").ToHistory("ParentState");

Other features

There are several other features of Moe.

  • Asynchronous – Found in the Moe.StateMachine.Extensions.Asynchronous namespace, calling Asynchronous() on your state machine object prior to Start() will create a thread for event propagation in the state machine.  When would you want synchronous and when asynchronous?  Depends on what you’re doing.  If you are tracking simple state transitions, workflow, parsing, or UI wizard type activities, synchronous is probably best.  If you’re state machine is responding actively to external stimuli, asynchronous is probably the way to go.
  • StateWatcher – Found in the Moe.StateMachine.Extensions.StateWatcher namespace, calling AddStateWatcher will take a callback and a list of states.  As soon as one is entered, the callback is invoked.  This is primarly just convenience.
  • Logger – Building event driven systems can be challenging.  Sometimes you just want to know the sequence of events and state transitions that occur, and by implementing a small ILogger interface, you can gain the information that might help with the tricky problems.  You can attach a logger by importing the Moe.StateMachine.Extensions.Logger namespace, and calling Logger() on your state machine.

Hi, meet Moe.

Introduction

State machines.  State charts.  Automata.  Whatever name you may have heard them called, they are a great tool for some situations.

At its simplest, state machines direct transitions in state based on input events.  Their value comes when we attach behavior to those states, and control transitioning to new states based on input.  State charts, as described by Harel, are an improved form of the original state machines described in traditional Computer Science, making them easier and more concise.  I won’t go into the details, but there is plenty of information available on the web.

Moe is a .NET state machine framework built in C#.  It was born of an actual need to control hardware components.  While I’d learned of state machines in school, the concept had since been forgotten.  A couple colleagues of mine had successfully used state machines for the very problem we were attacking in the past, and the interest was renewed.

I wasn’t happy with the existing .NET implementations I found.  They either forced a bad inheritance hierarchy on you, did not support hierarchical state charts, or were too complicated to use.  This led to my experiment building Moe.

Let’s get started

When building Moe, I wanted to make it to easily support the simplest machines up to very complex machines.  The framework is split into two primary activities.  Constructing a state machine model, and a state machine executing that model.  To build a model, we use builders to assist in rapid creation.  I’ve got a love/hate relationship with fluent interfaces, but it made the most sense in this case and led to the most concise code. For the example, we’ll use the simplest state machine of a switch.  This is the state chart:

Here’s how we begin constructing an on/off switch state machine.

StateMachineBuilder stateBuilder = new StateMachineBuilder();
stateBuilder.DefaultTransition("OFF");
stateBuilder.AddState("ON")
     .TransitionOn("SWITCH").To("OFF")
     .OnEnter(tr => Console.WriteLine("Turned on"));
stateBuilder.AddState("OFF")
     .TransitionOn("SWITCH").To("ON")
     .OnEnter(tr => Console.WriteLine("Turned off"));

What we’ve done here is to create a builder, add two states with one being designated the default transition, the transitions, and finally some actions to perform upon entry of the state.  Interestingly, the states are identified by strings (“ON” and “OFF”), as is the transition (“SWITCH”).  Moe actually takes an instance of type Object for these, only requiring that .Equals() will uniquely identify states and events.  This leaves the user free to use whatever they like to identify states and events.  Enums are a common choice for these, but are not required.

This was a departure from other machines I looked at, requiring that the user inherit from a base State class.  This was something I wanted to completely avoid.  I briefly played with the idea of introducing generics, but it resulted in a generic death spiral throughout the codebase that was not worth the hassle.  The only thing the state machine cares about is Equality for identification.

Something else to point out is the DefaultTransition.  Harel state charts introduced the notion of hierarchical states.  In the above example, the ON and OFF states actually reside in a root superstate.  At any time outside of an event propagation, you must be in a leaf state with no substates.  DefaultTransition is one or more transitions that may happen if a superstate is entered, with no transition to a substate.

Running the state machine

Let’s fire it up.  Again, the state model is separated from the state machine in our implementation.  The basic state machine runs synchronously, meaning when an event is posted it will propagate the event in line.  You can direct the state machine to run asynchronously too, where a thread will handle propagation of events.  That is for another post, for now, let’s start it up.


StateMachine sm = new StateMachine(stateBuilder);
sm.Start();

You can now post your event to the state machine like so:


sm.PostEvent("SWITCH");
sm.PostEvent("SWITCH");
sm.PostEvent("SWITCH");

And you will see your actions executed on the console.

What next?

In the above example, we wired actions to OnEnter events.  We also have the ability to wire to OnExit events.  In upcoming posts I plan to cover more of the features available in Moe, why and when state machines are useful, and use Moe to illustrate some of the design techniques in use today.  Mind you, there is nothing special about this framework itself, but I feel that it’s design and construction can be instructive.

Finally, you can get Moe’s source code on GitHub.