Blog

  • Home /
  • Blog /
  • Don’t Give Up on the State Pattern Just Yet - Revisited

Don’t Give Up on the State Pattern Just Yet - Revisited

March 27, 2010

In my previous post on the subject, I showed how you can remove some of the friction caused by applying the State pattern. In fact, as some of you rightfully pointed out, this friction isn’t caused by the State pattern itself but by a violation of the Interface Segregation Principle.   The use of role interfaces somewhat mitigated this violation but caused some type checking and casting in the context class (named Account in our example).

I just wanted to put out a slight variation of our solution that defers this kind of type checking until runtime. In other words, we’re going to apply some duck typing in order to come up with some improvements.

But hang on, isn’t C# supposed to be a static language and isn’t duck typing an exclusive feature of dynamic languages like Ruby or Python? Heck no! One can have duck typing in a static language as well. A good example of this is the Boo programming language which is a static language but provides the ability to give up this safety net. But I do believe that dynamic languages like Ruby or Python provide a more supple syntax for supplying duck typing capabilities while a static language usually requires a bit more ceremony.

The latest C# 4.0 compiler delivers some dynamic language features using the dynamic keyword which in turn accomplishes it’s functionality by leveraging the DynamicObject class (which seems to live in the System.Dynamic namespace). I have to admit that I didn’t spent much time on this yet.

But while the rest of the world is still on .NET 3.5 or earlier versions of the .NET framework, we don’t have to wait until the next upgrade to use some of the dynamic language features like duck typing, mixins and the like.

Let me first show you the code of the Account class from the previous post that demonstrates the type checking and casting to a role interface: 

What I would like to do is to remove the CanWithdraw check entirely without running into a NullReferenceException when a particular state doesn’t support withdrawing money. But first, I want to slightly decouple the Account class from the SilverState, GoldState and RedState classes by introducing an interface named IAccountStateChanger.

This is now used by the state classes to change the state of the Account class without using a property setter in order to get rid of the false sense of encapsulation. The implementation of this interface by the Account class is where the fun begins.

Besides having a state we also introduced a dynamic state which is simply an instance of Linfu’s DynamicObject class. I’ll talk about the missing state method handler part shortly, but first let’s look what we can do with our dynamic state object.

Notice that we got rid of the type checking part. But what if a particular state doesn’t support withdrawing money? Here’s were the method missing piece of the puzzle falls in. Linfu provides an interface named IMethodMissingCallback which lets you decide what to do when the requested method call cannot be resolved.

public void Withdraw(double amount)
{
    // One can not always withdraw
    if(false == CanWithdraw())
    {
        // Should throw an exception or at least a towel
        Console.WriteLine("No funds available for withdrawal!");
        return;
    }

    var canWithdraw = (ICanWithdraw)State;
    canWithdraw.Withdraw(amount);

    ...
}

private Boolean CanWithdraw()
{
    return State is ICanWithdraw;
}

You can do pretty much anything in here like delegating the call to another method, but for demonstration purposes we just write a message to console. As shown earlier we literally add an instance of this handler to the dynamic object and we’re all set up. Using this approach yields the same results but without the type checking.

I’d like to mention that I’ve been using the DynamicObject class from Linfu 1.0 which you can download here. For some reason this class hasn’t been included in the 2.0 release and higher which is a bit sad because I really like some of the possibilities it has to offer. I’ll cover some of these in one of my next posts.

If you and your team want to learn more about how to write maintainable unit tests and get the most out of TDD practices, make sure to have look at our trainings and workshops or check out the books section. Feel free to reach out at infonull@nullprincipal-itnull.be.

Profile picture of Jan Van Ryswyck

Jan Van Ryswyck

Thank you for visiting my blog. I’m a professional software developer since Y2K. A blogger since Y2K+5. Provider of training and coaching in XP practices. Curator of the Awesome Talks list. Past organizer of the European Virtual ALT.NET meetings. Thinking and learning about all kinds of technologies since forever.

Comments

About

Thank you for visiting my website. I’m a professional software developer since Y2K. A blogger since Y2K+5. Author of Writing Maintainable Unit Tests. Provider of training and coaching in XP practices. Curator of the Awesome Talks list. Thinking and learning about all kinds of technologies since forever.

Contact information

(+32) 496 38 00 82

infonull@nullprincipal-itnull.be