State pattern using C#. Part 01

I have been busy for a while writing my two books about MVVM and WPF but I am almost done so be ready to get more posts in the next months. This one is the first of a series that I will write to solve the state pattern issue.

Today I want to start to talk about the state pattern, a design pattern used to represent the state of an object and how we can apply this pattern in a normal WPF application.

The problem we have is that based on the state of an Order we can or we can’t execute a specific action.

Before starting to talk about the pattern we need a sample application, right? So, what is better than having a nice WPF application that we will use to represents the problem? Smile

Process an order using States

The example I want to use is the classic Order entity that during the order process can be moved to different states. The following diagram create with Visual Studio shows you what I am talking about:

StateDiagram

The previous image shows the state diagram applied to an Order:

  • You can create  an order and after it is created the state is of type Created
  • Then you can modified the order or you can cancel the order; if you cancel the order, its state is cancelled and you can’t do anything anymore
  • An order that has been created can be approved and its state will change to approved

So in the previous Use Case we have identified 4 actions (blue) and 3 states (white), for each action there is a specific state, in a specific state you can execute only a specific or a set of specific actions and from one state you can move only to one or more specific states. For instance, from the Approved state we can’t rollback to the Created state and so on …

Now, how would you express the previous diagram using a Domain Model composed by an Order entity and a State property? First thing first is to implement a Domain Entity.

OrderObject

Now we can implement the classic state pattern described by Martin Fowler.

Classic implementation of the State Pattern

If you are an MVVM developer you may believe that the first and almost the easiest way of implementing this pattern is to use the Command pattern, right? So, if we plan to extend that in the Order entity we should have a model like the following one:

CommandPattern

Where the command implementation may be something like this:

Command Pattern
  1. CreateOrder = new Command(
  2.     () => true,
  3.     () =>
  4.         {
  5.             Code = “ABC123”;
  6.             State = OrderState.Created;
  7.         }
  8.     );
  9. ModifyOrder = new Command(
  10.     () => State == OrderState.Created,
  11.     () =>
  12.         {
  13.             State = OrderState.Modified;
  14.         });
  15. CancelOrder = new Command(
  16.     () => this.State == OrderState.Created || this.State == OrderState.Modified,
  17.     () => { this.State = OrderState.Cancelled; });

 

When an order is created, by default, we do not allow any state so the default state is undefined and these are the tests:

TDD – change state
  1. [Test]
  2. public void AssertThatANewOrderIsUndefined()
  3. {
  4.     var order = new Order();
  5.     Assert.That(order.State, Is.EqualTo(OrderState.Undefined));
  6. }
  7.  
  8. [Test]
  9. public void AssertThatANewOrderCanBeCreated()
  10. {
  11.     var order = new Order();
  12.     order.CreateOrder.Run();
  13.     Assert.That(order.State, Is.EqualTo(OrderState.Created));
  14. }

 

The last step needs to verify that if we try to move from one state to a not allowed state, the action that we try to execute will throw an exception:

TDD – Not allowed method
  1. [Test]
  2. public void AssertThatCannotApproveANewOrderNotCreated()
  3. {
  4.     var order = new Order();
  5.     Assert.That(order.State, Is.EqualTo(OrderState.Undefined));
  6.     Assert.Throws<NotSupportedException>(() => order.ApproveOrder.Run());
  7. }

 

Conclusion using the Classic method

This technique is not clean and it is very verbose but it is absolutely testable, but not maintainable. For instance, if the number of state enum will increase we have to touch all over the code that execute the flow logic and probably we need also to refactor all the commands so we can say that this solution is fine but not maintainable at all.

Another gap of this solution is that every time we want to execute a command we need to fire the CanExecute method that may process some “long running” business logic behind:

Command Run() method
  1. public void Run()
  2. {
  3.     if (canExecute == null || canExecute.Invoke())
  4.     {
  5.         this.execute.Invoke();
  6.     }
  7.     else
  8.     {
  9.         throw new NotSupportedException(“The action can’t be executed.”);
  10.     }
  11. }

In the next blog post we will see a different approach. At the end of the series (04 posts) I will provide a WPF application on www.codeplex.com with the source code posted in this series; please be patient for now as I can’t upload the final source code yet.