Cross Functional Teams and Systems Thinking

Cross functional teams have been promoted by agile methods for years now, and it can be hard to fully appreciate their value without having experienced the tremendous value of such a team. The same could be said for much of agile practices, but I want to focus on cross functional teams.

What are cross functional teams?

A software development team that is cross functional might include developers, user experience designers, testers, production support, and subject matter experts. All of these individuals work together on a team towards a common goal. This differs from traditional methods where each specialty is in a silo, interacting with other specialties at specified gates or milestones.

Ok, so where is the value?

Having experienced a very successful, cross functional team led me to several conclusions. First, it improves communication among the people working towards the solution. When a developer has an unclear requirement or an alternative idea, it’s natural to turn to a team member who can clarify the requirement or refine the idea. If a tester encounters what might be a bug, it’s a simple matter of turning to the developer to work through the issue. This eliminates all the red tape (in the form of bug tracking) and waste and takes care of the problem quickly. And this arrangement allows for constant collaboration in solving problems, which not only solves problems more quickly, but typically results in a superior solution.

Recently I’ve been involved with a team that is not cross functional. Specifically, developers and testers are firmly segregated. In this organization, a build is handed off at the end of a sprint.  Testing will only be conducted on functionality that is mostly complete. The intent is to minimize retesting, but this goal is misplaced in my opinion. Retesting shouldn’t be the worry, the testing inventory that builds up should.

In thinking about the problem, I realized a significant benefit cross functional teams, and it is that the approach forces systems thinking. Systems thinking, in its simplest form, is consideration of an entire system and how the components interact and affect one another.  It’s simple, when divided into different groups, to focus on local optimization. That is, when I’m a tester thinking only about testing software, my apparent goal is to test software and report bugs. As a developer, my goal is to crank out the spec’d software.

It’s too easy to lose sight that our goal is to deliver solutions, or in agile terms, working software. Actually, that isn’t even quite correct. Our goal is to deliver business value. When we have a cross functional team, we are forced to think in terms of systems, whether we realize it or not. For someone altering requirements, the effects of those decisions are apparent when you are part of the team. When a developer is cranking out too much functionality (oh yes I said it), the effect on the tester sitting next to them will be evident.

We like to talk about constant feedback, and a cross functional team will give you feedback on how the team itself is performing, and how the system is working (or not).

Why the resistance?

Perhaps one of the greatest impediments is territoriality. Managers get queasy about relinquishing their minions to a team. This can even be extrapolated to the fear of empowering teams with decision making, but that is another post.

Mentioned earlier, local optimization is another roadblock. The idea of an employee’s not being 100% utilized in doing their job is heresy. Excess inventory- for example, testing inventory–can cost far more than time spent idle.

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.