Tuesday 24 February 2009

Implementing the State Software Design Pattern in C#

An article about implementing state in a C# application, using the State Software Design Pattern.

Level: Intermediate to Advanced

About The State Software Design Pattern

Extract from Refactoring to Patterns by Joshua Kerievsky

The primary reason for refactoring to the State pattern is to tame overly complex state-altering conditional logic. Such logic, which tends to spread itself throughout a class, controls an object's state, including how states transition to other states. When you implement the State pattern, you create classes that represent specific states of an object and the transitions between those states. The object that has its state changed is known is Design Patterns as the context. A context delegates state-dependent behavior to a state object. State objects make state transitions at runtime by making the context point to a different state object.

The extract above describes the primary reason for applying the State Design Pattern - to retract overly-complex conditional logic. I have a secondary reason for using this pattern, which is....applications get scattered with code representing state values.

A conventional approach of applying a state process model to a software application is to create a lookup table in a database and add state values(ID's) and descriptions to said table. Application code would then use integer values to represent the state lookup values(ID's) of the table. Applications using these hard-coded integers is susceptible to typos and lots of editing and replacing when somebody decides to change the values during development of the model.

An alternative to scattering integers everywhere is to implement an enumerated type that models the states and then to use the enumerated types in place of the integers. This is an improvement but still presents additional maintenance in keeping the enumeration and the lookup table in sync.

Both of these techniques present problems and neither satisfy the primary and secondary problems I have just described. Let's take a look at an example and see how we can apply a more effective design using the State Software Design Pattern. I've created a mock-up; a fictional business problem we can apply this pattern to.

My Fictional Problem

Users are gathering content from third-parties and creating internal documents with it. The content usually has spelling mistakes and grammatical errors and requires some kind of validation and formal sign-off process.

Bring in the UML Diagrams

A UML State Model Diagram

Below is a simple document state process model I am going to use to solve my problem.

Implementing the State Design Pattern in C#: UML State Diagram

Note. This State Process Model would require more states if it was to be applied to a real-world solution. However, I am keeping this example simple for the purpose of this article.

Applying the State Design Pattern

I'm starting by presenting the kind of State Pattern UML Class Diagram you're already familiar with. I've no doubt you have seen this if you have read any Gang Of Four (GoF) publications, or anything by Martin Fowler about the State Design Pattern.

The UML Class Diagram

State Design Pattern Class Diagram

Looks good doesn't it? It looks "Designed"; Object-Oriented! We're on to a winner. However, I'm sure you've seen many class diagrams like this, understood the diagram at a abstract level, but then wondered "how the hell do I implement this?". Well, hopefully I can help you out here. I'm going to take these diagrams one step further and show you an implementation of how the context interacts with the State Pattern. Before I do this I would like to take a step backwards....

An Unconventional Approach: Dropping the State Lookup Table

I'm not going to create anything in a database to model our state process. I'm not creating a lookup table. My state process model is representing a solution to a business problem; it's a solution created for managing the quality of content going in to internal documents. This is business logic (also known as domain logic), so I don't want the database to be responsible for maintaining it.

Ok, so you've picked yourself up off the floor....let's continue, back to the class diagram and applying the pattern.

Creating the C# Classes for State Pattern

Here is the first pass implementation of the classes in the UML class diagram. Note. I have added a prefix of Base to the DocState and a suffix of State to the concrete states.

    // The Base State Class in the Design Pattern
    

    public abstract class BaseDocState
    {
        public abstract void SignOff( );
    }
    
    // The Concrete State Classes in the Design Pattern
    

    public sealed class NewDocState : BaseDocState
    {
        public override void SignOff( )
        {
        }
    }

    public sealed class PendingReviewState : BaseDocState
    {
        public override void SignOff( )
        {
        }
    }

    public sealed class InReviewState : BaseDocState
    {
        public override void SignOff( )
        {
        }
    }

    public sealed class LiveState : BaseDocState
    {
        public override void SignOff( )
        {
        }
    }
    
    // The Context Class in the Design Pattern
    

    public sealed class DocBll
    {
        public void CreateDoc( )
        {
        }
        public void SubmitForReview( )
        {
        }
        public void SignOffReview( )
        {
        }
        public void GoLive( )
        {
        }
    }

What we have now is a code skeleton that maps on to our class diagram. Time to flesh out the classes and show you how they interact.

The Context Class

I'm beginning with the context class, DocBll, because the design will be easier to digest starting with the problem domain.

The first step is to add a state variable to the context, which represents the current state of a document. At the same time I'll throw in a couple of variables to store the data of the document. The variables won't be used in my examples but it will give you a better feel for the class design.

    public sealed class DocBll
    {
        private string _title;
        private string _xmlContent;        
        
        // The Current State
        
        private BaseDocState _currentState;
        
        //
        
        public void CreateDoc( )
        {
            // code here            

        }

        public void SubmitForReview( )
        {
            // code here            

        }

        public void SignOffReview( )
        {
            // code here            

        }

        public void GoLive( )
        {
            // code here
        }
    } 

Now I'll flesh out one of the public methods. I'm going to start with SubmitForReview method in the context class, and you're probably wondering why. Why don't I start with CreateDoc as it's the first method in our process? I will explain shortly. Here is a fleshed-out SubmitForReview method:

    public void SubmitForReview( )
    {   
        _currentState.SignOff( );
    }  

"Is this it? What is this going to achieve?", I hear you ask. Well, not a lot to be honest. Let's expand it a little....

What we really need is to be able to pass information about the context object, our DocBll, through to our current state pattern object. This wasn't included in our class diagram, but I wanted to keep the diagram as simple as I possibly could. I am going to introduce a new class here, and the sole purpose of this class is to provide a communication link between the context, and the current state.

    public sealed class DocStateArgs
    {
        private DocBll _context;

        public DocStateArgs( DocBll context )
        {
            _context = context;
        }
        
        // expose fields of the _context that the
        // state pattern needs to operate, here....

        // .
        // .
        // .
        // .
        
        
        // fields state pattern fill in here....
        
        private bool _hasSignature = false;

        public bool HasSignature
        {
            get { return _hasSignature; }
            set { _hasSignature = value; }
        }

        private BaseDocState _nextState;

        public BaseDocState NextState
        {
            get { return _nextState; }
            set { _nextState = value; }
        }
    }

Our class takes a context object in the constructor so it can expose only the fields that should be exposed to the state pattern, as opposed to every public member of the context object. Also, our class contains two properties which the state will fill in: The NextState, which is the state the context will be moving to (our transition), and HasSignature, which is a boolean indication of whether or not the context is in a valid state to proceed with the request that was made on it.

By design, I have decided that I don't want our state pattern to have direct database access - I don't want it to persist anything. It should simply validate and provide us with authorisation through the HasSignature property.

Here is the DocState Class with its new signature and the DocBll with an implementation of SubmitForReview.

    // The new Base State Class
    
    public abstract class BaseDocState
    {
        public abstract void SignOff( DocStateArgs args );
    }
    
    // The new Context Class
    
    public sealed class DocBll
    {
        private string _title;
        private string _xmlContent;        
        
        // The Current State
        
        private BaseDocState _currentState;
        
        //
        
        public void CreateDoc( )
        {
            // code here            

        }

        public void SubmitForReview( )
        {
            DocStateArgs args = new DocStateArgs( this );

            _currentState.SignOff( args );

            if ( args.HasSignature )
            {
                _currentState = args.NextState;

                // _sqlDocProvider.Commit( .. );
            }
        }

        public void SignOffReview( )
        {
            // code here            

        }

        public void GoLive( )
        {
            // code here
        }
    }      

Let's get back to the CreateDoc method....

By default, when a class is instanciated all its object members will be initialized to null, which means that when the DocBll context class is instanciated the state variable _currentState will be null, and will still be null CreateDoc is called. This means that the implementation of CreateDoc will have to do something extra. It will have to test for a null value and create a state if the test returns true. Here's an implementation of the CreateDoc method:

    public void CreateDoc( )
    {
        if ( _currentState == null )
        {
            _currentState = new NewDocState( );

            
            // hang on a minute, I don't like this!!!
            // I want to look the same as the others!!!
            // Why don't you implement the Null Object Pattern for me!!! 
        }
    }

There's actually no reason why the CreateDoc method should be implemented differently to the other methods on DocBll, and with the addition of one small class consistency will be brought back in line - there will be no need for the null checks we can see in the previous code example.

The Null Object Software Design Pattern

Extract from Refactoring to Patterns by Joshua Kerievsky

If a client calls a method on a field or variable that is null, an exception may be raised, a system may crash, or similar problems may occur. To protect our systems from such unwanted behavior, we write checks to prevent null fields or variables from being called and, if neccessary, specify alternative behavior to execute when nulls are encountered.

Repeating such null logic in one or two places in a system isn't a problem, but repeating it in multiple places bloats a system with unnecessary code. Compared with other code that is free of null logic, code that is full of it generally takes longer to comprehend and requires more thinking about how to extend.

Here is NullDocState Null Object Pattern implementation:

    public sealed class NullDocState : BaseDocState
    {
        public override void SignOff( DocStateArgs args )
        {
            // validate the context here....


            // if (all is well) then  // set the next state and sign it off....
            {
                args.NextState = new NewDocState( );

                args.HasSignature = true;
            }        
        }
    }

As well as providing you with a Null Object definition, here I have given you a full implementation of the SignOff method.

Here is a complete implementation of the DocBll Context Class

    public sealed class DocBll
    {
        private string _title;
        private string _xmlContent;        
        
        // The Current State initialized to NullDocState
        
        private BaseDocState _currentState = new NullDocState( );
        
        //
        
        public void CreateDoc( )
        {
            DocStateArgs args = new DocStateArgs( this );

            _currentState.SignOff( args );

            if ( args.HasSignature )
            {
                _currentState = args.NextState;

                // _sqlDocProvider.Commit( .. );
            }
        }

        public void SubmitForReview( )
        {
            DocStateArgs args = new DocStateArgs( this );

            _currentState.SignOff( args );

            if ( args.HasSignature )
            {
                _currentState = args.NextState;

                // _sqlDocProvider.Commit( .. );
            }
        }

        public void SignOffReview( )
        {
            // code here            

        }

        public void GoLive( )
        {
            // code here
        }
    }

The Concrete State Classes

Here is the implementation of the modelled conrete states:

    public sealed class NewDocState : BaseDocState
    {
        public override void SignOff( DocStateArgs args )
        {
            // validate the context here....


            // if (all is well) then  // set the next state and sign it off....
            {
                args.NextState = new PendingReviewState( );

                args.HasSignature = true;
            }
        }
    }
    
    
    public sealed class PendingReviewState : BaseDocState
    {
        public override void SignOff( DocStateArgs args )
        {
            // validate the context here....


            // if (all is well) then  // set the next state and sign it off....
            {
                args.NextState = new InReviewState( );

                args.HasSignature = true;
            }
        }
    }
    
    
    public sealed class InReviewState : BaseDocState
    {
        public override void SignOff( DocStateArgs args )
        {
            // validate the context here....


            // if (all is well) then  // set the next state and sign it off....
            {
                args.NextState = new LiveState( );

                args.HasSignature = true;
            }
        }
    }
    
    
    public sealed class LiveState : BaseDocState
    {
        public override void SignOff( DocStateArgs args )
        {
            args.HasSignature = false; // end of state model
            
            // the above is just a cheap way of indicating the
            // end of the state model for our example.  In a
            // real application you'd probably want to be more
            // informative about why it can't be signed off.
        }
    }

To Conclude Implementing the State Design Pattern in C#

I have given you a very simplistic solution, demonstrating the use of the State Design Pattern, and the transformation of a business problem through analysis, class design, through to the implementation. I hope my writing is clear and you feel you now have the understanding to apply these techniques in your own solutions.

Missing from this Article

What this article didn't cover is how to persist a context's state to a database and then load the context object with state. I will be following this article up with a part 2 where I will add a little more functionality to these classes and also show you how to persist and load.

Useful Links

Monday 23 February 2009

Cloning Objects for the Asp.Net Cache when Data Caching

The importance of object cloning to protect data in the Asp.Net cache when Data Caching.

Level: Beginner to Intermediate

Introducing Cloning Objects for the Asp.Net Cache when Data Caching:

Let's imagine you've populated an object in memory and then written the object to the Asp.Net Cache. Do you know that when you read your object from the cache

  MyClass myObject = ( MyClass )HttpRuntime.Cache[ "mykey" ];
Fig.1

you will have a reference to the same object instance that the cache has access to? This means that any changes you make in your object (fig.2) will be seen by all future requests for the same cached object.

  myObject.Description = "My very own description";
Fig.2

Now this isn't necessarily a good thing. Infact, this could be very bad for you because maybe, you would like to cache an object in the Asp.Net Cache, and then preserve the object until it expires. At the same time, new requests for this cached object might want to make slight modifications to it for their own use, so in essence, if we need to preserve data in the Asp.Net Cache yet allow requests modifications - we have to give each one their very own copy of the cached object.

Protecting Data in the Asp.Net Runtime Cache

To protect and preserve cached data an object should be cloned both ways(when inserting into the cache, and when reading from the cache), using a deep copy, and let me stress "DEEP".

Let me show you some code examples I created for this article. I have created a generic CacheList class that will allow a user to add a generic type to a list and provide caching and loading from the cache. I started by creating a helper class and added a method that will allow me to clone a list.

A Helper Method to Clone List

  public static class GenericsHelper
  {
    public static IList<T> CloneList<T>( IList<T> source )
        where T : ICloneable
    {
      IList<T> clone = new List<T>( source.Count );
      foreach ( T t in source )
      {
        clone.Add( ( T )t.Clone( ) );
      }
      return clone;
    }
  }
Fig.3

CacheList: The Generic List Class

Here are the operations available to a client of CacheList:
  • Add( T item ) : void // call to add an item to our list
  • CacheIt( string cacheKey, DateTime absoluteExpiration ) : void // call to insert list into the runtime cache
  • LoadCached( string cacheKey ) : bool // call to load list from the data in the cache and allow mods without affecting cache

Here is an implementation of CacheList:

  public sealed class CacheList<T> where T : ICloneable
  {
private IList<T> _dataList = new List<T>( );
public void Add( T item ) { _dataList.Add( item ); }
public void CacheIt( string cacheKey, DateTime absoluteExpiration ) { // clone the data list IList<T> clone = GenericsHelper.CloneList<T>( _dataList ); // insert into the runtime cache HttpRuntime.Cache.Insert( cacheKey, clone, null, absoluteExpiration, Cache.NoSlidingExpiration ); }
public bool LoadCached( string cacheKey ) { // perform thread-safe read from cache object obj = HttpRuntime.Cache[ cacheKey ]; // if not null clone it, ret. true to indicate clone success if ( obj != null && obj is IList<T> ) { _dataList = GenericsHelper.CloneList<T>( ( IList<T> )obj ); return true; } return false; }
public IList<T> DataList { get { return _dataList; } }
}
Fig.4

My List is Implementing ICloneable

I have placed a constraint on my list which specifies that we can only stored types implementing the ICloneable interface. Let me point out that I'm assuming the implementations of this interface are performing deep copies and not shallow ones.

Use a search engine to search for ICloneable and you will no-doubt find all sorts of discussions about how good or bad it is, and to be honest I can see the arguments against using this interface. In a nutshell developers are suggesting this method isn't clear enough; it doesn't indicate whether a object that implements it is performing a deep or a shallow copy. However, if you agree with the reasons against using it then you don't really have a problem; just your own cloneable interface to write.....and maybe you could make it generic. This is an article by Brad Adams about implementing ICloneable, or not as his case may be.

Will a deep copy affect performance?

This I can't answer for you I'm afraid. I mean, if you are loading and caching a list of lookup values for a drop down list then I would say "don't worry about it". If you're loading ten thousand search results then you might possibly run in to performance issues, but at the same time I'd probably suggest you don't cache this information.

Thanks for reading

Well that's it for the code that preserves our cached data using cloning. This is a pretty simple example and a very simplistic implementation of a list. However, I didn't want to detract from purpose of the article. I'm going to extend this article in future and show you how this sort of cache access can be wrapped in a business/domain object.

I hope you enjoyed the article, there will be many more to come.