Dependency Inversion for Dummies: Unity and StructureMap

by Ben Hart 20. November 2008 14:55

This is it. The moment you've been waiting for. The series that has you periodically checking back to see if there is another instalment continues (since the frequency of my posts has you questioning whether the feed is working). Dependency Inversion for Dummies is back...

Previously...

When we started on this journey, early on, we were empowered with the knowledge of how insidious dependencies can cripple an application's ability to change. Despite this alarming revelation, in the spirit of developers knowing that the time of failed software projects must change, we read on. Yes we can.

Rather than despair at this new knowledge we considered that a simple means to reduce this restrictive coupling is constructor injection. We struggled through references to teen chick-rock, arrogant comparisons to blockbuster TV-Series, bad examples, always seeking this better way. Yes we can.

When we then discovered that inverting our dependencies can make for more work in object creation, rather than walking away and dismissing this as a fad, we took the high road to find out how centralising object creation can help. Yes we can.

When all seemed lost, when the temptation to ignore the breakthroughs of those that came before us began to overwhelm our new sensibilities, we learned that factories or service locators are not only simple concepts, but remarkably easy to implement and use. Yes we can.

And, when promises of a follow-up were not kept, and when a week became a fortnight, a month, more, did we lose faith in the value of this blog, or did we stand up, with resolve and patience, and understand that Ben Hart is an African, and that in Africa, we work on African Time?

Unity and StructureMapYes we did

Today we use some tools, and compare them with the simplest of all requirements. This will not be a comparison of features, nor an evaluation of any sort. Don't leave this settled on an IoC container without investigating them yourself. Take a look at least at Autofac, Ninject, Windsor and Spring.NET before you make up your mind. Choose the one that works for you, while all similar in the basics, they all bring something different to the party (some bring the whole bar!).

Today we're just going to look at the tool I use against the one released by Microsoft. The Apache 2 OSS against the MPL. The industry veteran against the newcomer. Hulk Hogan against Toa.

 [While I generally don't care much for what people think of me, the thought that anyone might assume that I knew who Toa was before this blog post is too much to bear. This was merely the first image result that had an oldie of WWF (in my time, the kids call it WWE these days) with a newcomer. That's my story, and I'm sticking to it.]

Where's the code?

Remember last time we had centralised object creation into a simple service locator. It wasn't all that pretty. It was called by a simple console application that requested an instance of the ITagService in order to retrieve tags. The whole application fits into this tiny box:

class Program
{
    static void Main(string[] args)
    {
        ITagService tagService = ServiceLocator.GetInstance<ITagService>();
        foreach (string tag in tagService.GetUniqueTags())
        {
            Console.WriteLine(tag);
        }
        Console.ReadLine();
    }
}
 
public static class ServiceLocator
{
    public static T GetInstance<T>()
    {
        return (T)GetInstance(typeof(T));
    }
    public static object GetInstance(Type type)
    {
        return GetInstance(type.Name);
    }
    public static object GetInstance(string name)
    {
        switch (name)
        {
            case "ITagService":
                return new UniqueTagService(new TagDatabase());
        }
        throw new ArgumentOutOfRangeException("name", string.Format("{0} is not a registered type.", name));
    }
}
 
public interface ITagService
{
    IList<string> GetUniqueTags();
    int TagCount();
}
 
public class UniqueTagService : ITagService
{
    private ITagData _db;
 
    public UniqueTagService(ITagData database)
    {
        _db = database;
    }
 
    public IList<string> GetUniqueTags()
    {
        return new List<string>(_db.GetTags().Distinct());
    }
 
    public int TagCount()
    {
        return _db.GetTags().Length;
    }
}
 
public interface ITagData
{
    string[] GetTags();
}
 
public class TagDatabase : ITagData
{
    private string[] _tags = new[] { "Word1", "Word2", "Word3", "Word1" };
 
    public string[] GetTags()
    {
        return _tags;
    }
}

Rather than change much else, we're simply going to extend the service locator to use the new tools in our belt. Notice that our client code is only calling the generic GetInstance<T> method, the overloads were simply to confuse you. So, without any further ado, let's meet our contestants.

First into the ring: the drum beater, the system cheater, the broadcaster, the drummer... can a get a shout out fooooooorrrrrrrr.......

StructureMap

First up you'll need to download the latest binaries from the sourceforge site and add a reference to StructureMap.dll. While there are other means to configure, the easiest has to be the internal dsl. The simplest means to use this is the creation of a registry file, and the override of the configure() method.

public class MyRegistry : Registry
{
    protected override void configure()
    {
        ForRequestedType<ITagService>().TheDefaultIsConcreteType<UniqueTagService>();
        ForRequestedType<ITagData>().TheDefaultIsConcreteType<TagDatabase>();
    }
}

All we've really done here is mapped the implementation we desire to the type that will be requested. Next thing is to let StructureMap know about the registry, and wire it into our service locator.

public static class ServiceLocator
{
    static ServiceLocator()
    {
        ObjectFactory.Initialize(c => c.AddRegistry(new MyRegistry()));
    }
    public static T GetInstance<T>()
    {
        return ObjectFactory.GetInstance<T>();
    }
}

For simplicities sake I've called ObjectFactory.Initialize() from the static constructor of our already static service locator. You'd generally only want to call this once in an application, and this achieves this. Note the lambda adds the registry to the object factory, and that our GetInstance<T> defers to the factory.  That's all that's required. (Note also that having the service locator wrapping the IoC container is not something I'd recommend, rather just a means to continue without changing any more code.)

More astute readers may wonder HTF this works? All we've requested is the ITagService. ITagService has a dependency to ITagData, previously we had to instantiate the TagDataBase and pass it in. WTF is going on here?

That, my friends, is the beauty of auto-wiring. StructureMap takes it upon itself to examine the requested type for dependencies, and creates and passes those in when requested. Just don't forget to say thank you.

Well that was pretty simple. Now the one I've been l've been waiting for. The one I've been meaning to look at for ages. The one that at first appalled me as a senseless waste of resources when the existing alternatives were so plentiful. The one that will likely be the most adopted despite its relative youth. Can I get a whoop-whoop foooooorrrrrrr.....

Unity Application Block

First up you need to track down the download of the binaries. If StructureMap is a little modest with its download link, Unity can only be described as coy. Following the links you'll likely end up here. Install the msi, and add a reference to Microsoft.Practices.Unity.dll.

The container in Unity is called UnityContainer (ObjectFactory in StructureMap provides static methods that wrap the Container, but it's still there). Unity is a breeze to get started with. All we need to do is create the container in our service locator, and register the types.

public static class ServiceLocator
{
    private static IUnityContainer _container;
 
    static ServiceLocator()
    {
        _container = new UnityContainer();
        _container.RegisterType<ITagService, UniqueTagService>();
        _container.RegisterType<ITagData, TagDatabase>();
    }
 
    public static T GetInstance<T>()
    {
        return _container.Resolve<T>();
    }
}

F*ck me, that was easy. Finding the download took longer! So easy that I had to find a similar implementation in StructureMap...

public static class ServiceLocator
{
    private static Container _container;
    static ServiceLocator()
    {
        _container = new Container(x => 
        { 
            x.ForRequestedType<ITagService>().TheDefaultIsConcreteType<UniqueTagService>();
            x.ForRequestedType<ITagData>().TheDefaultIsConcreteType<TagDatabase>();
        });
    }
    public static T GetInstance<T>()
    {
        return _container.GetInstance<T>();
    }
}

Here we're accessing the container directly, configured through the constructor. A few more lines of code, but as simple. I'll likely stick to using registries, but options are useful. (Note this would have taken me longer to discover if not for Jeremy D. Miller's epic weekend series of posts documenting StructureMap 2.5, this one in particular.)

Wrapping up

Remember that the above is the simplest of uses for a IoC container, but already I hope the value is clear. Next time we'll look at some of the more advanced uses, and, since I've enjoyed my introduction to Unity, maybe even get to know Autofac a little better...

Be the first to rate this post

  • Currently 0/5 Stars.
  • 1
  • 2
  • 3
  • 4
  • 5

Tags: , , , ,

C# | Design Patterns

Dependency Inversion for Dummies: Factories and Service Locators

by Ben Hart 12. October 2008 14:09

In my previous post on dependency inversion I elaborated on constructor injection, the injecting of objects a classes depends on into said class's constructor. We saw that this injection both made the dependency more explicit, as well as going some way towards revealing the class with the dependency's purpose. I had stated that explicitly declaring these dependencies makes construction of the object more complex, and had the risk that you end up repeating much code every time you construct a class. I took some hints from the Hollywood TV Series Scriptwriter's Bible by leaving off with a cliffhanger (my way of encouraging Kiefer to roll out the next season of 24 on schedule)... "join me next time when we look at some creational patterns that solve this". And I know you've been hanging.

Creational Patterns

A cursory glance over sites that list design patterns shows that they're generally grouped into categories. These likely hark to the original groupings in the GOF book: creational, structural and behavioural. The book defines creational patterns as being those that:

"...abstract the instantiation process. They help us make a system independent of how its objects are created, composed, and represented."

The book illustrates 4 such patterns: Abstract Factory, Builder, Factory Method, Prototype and Singleton, some competing, many quite tailored to specific scenarios. Common to all, though, is centralisation of object creation. None of these patterns really fit our quite simple case, though, but quoting the GOF gives me some geek cred, so deal with it.

First a few modifications to our code

Remember that in the last post our unremarkable TagService did little more than than filter tags from a data store to be unique. It had a dependency on a concrete data store, which we effectively eliminated. We were stuck in a situation where we knew we needed an instance of a class, we just didn't want to build it in our code. While waxing lyrical about programming to an interface and not an implementation, more astute readers would have picked up the most obvious violation of this, within the console class itself. The first step of today's exercise is thus extracting an ITagService interface.

class Program
{
    static void Main(string[] args)
    {
        ITagService tagService = new UniqueTagService(new TagDatabase());
        foreach (string tag in tagService.GetUniqueTags())
        {
            Console.WriteLine(tag);
        }
        Console.ReadLine();
    }
}
 
public interface ITagService
{
    IList<string> GetUniqueTags();
    int TagCount();
}
 
public class UniqueTagService : ITagService
{
    private ITagData _db;
 
    public UniqueTagService(ITagData database)
    {
        _db = database;
    }
 
    public IList<string> GetUniqueTags()
    {
        return new List<string>(_db.GetTags().Distinct());
    }
 
    public int TagCount()
    {
        return _db.GetTags().Length;
    }
}
 
public interface ITagData
{
    string[] GetTags();
}
 
public class TagDatabase : ITagData
{
    private string[] _tags = new[] { "Word1", "Word2", "Word3", "Word1" };
 
    public string[] GetTags()
    {
        return _tags;
    }
}

Another Interface?

Better believe it. We don't want our client code (the console app) to depend directly on a concrete tag service. The interface defines the functionality we require, gluing the concrete service with the console app just creates a further dependency, one we'll regret when the inevitable changes come through.

Notice, also, that the tag service has been renamed. Its function is to draw tags from a database, and filter them to be unique. Having classes and members that are aptly named is the single best convention we can adopt, and saves having to insist on developers commenting their code (which is about as effective as herding cats).

The dependency is still there

Exactly. The console class requires the tag service, and still constructs it when required. If we continued on this path, we'd soon have a number of locations that cement that same dependency. A number of stinky dependencies. Yuck.

Simple Factory

Probably the simplest means we could improve this is through a factory. Not the abstract factory the GOF defined (which would allow us to construct and return different tag services according to need), but a plain old simple factory (to coin an acronym, POSF), a class whose purpose is to build an object.

class Program
{
    static void Main(string[] args)
    {
        ITagService tagService = TagServiceFactory.BuildTagService();
        foreach (string tag in tagService.GetUniqueTags())
        {
            Console.WriteLine(tag);
        }
        Console.ReadLine();
    }    
}
 
public static class TagServiceFactory
{
    public static ITagService BuildTagService()
    {
        return new UniqueTagService(new TagDatabase());
    }
}

In the above code we've simply created a static class with a method that constructs and returns a tag service when requested. The main advantage here is that we've encapsulated the creation of the tag service, and have centralised it. Other code that might require the service can request one, without knowing all the gritty details of the concrete class, and required dependencies. Should we need to change the implementation of ITagService (for example, change the data store), we need only change it in one location.

Service Locator

The above implementation is pretty simple, but has already greatly improved our code. A potential downside would be the explosion of a number of factories, one for each requested type. A simpler scenario will be a centralised service locator, a one-stop-shop from which we can request a type, and receive an object. DI containers do just this, but let's take a look at a pretty naive implementation of our own.

public static class ServiceLocator
{
    public static T GetInstance<T>()
    {
        return (T) GetInstance(typeof(T));
    }
    public static object GetInstance(Type type)
    {
        return GetInstance(type.Name);
    }
    public static object GetInstance(string name)
    {
        switch (name)
        {
            case "ITagService":
                return new UniqueTagService(new TagDatabase());
        }
        throw new ArgumentOutOfRangeException("name", string.Format("{0} is not a registered type.", name));
    }
}

While not so pretty, this simple class allows us a centralised and flexible means to register and construct services. A real service locator would likely construct the classes dynamically using reflection, and hopefully do some autowiring of dependencies, with some caching for good measure. This one serves to illustrate the concept, though.

Client code could choose which method they'd like to call, but having the generic saves some casting. Our console app uses the service locator with this line of code:

ITagService tagService = ServiceLocator.GetInstance<ITagService>();

Of course you'd be crazy to reinvent the wheel, and there are ample DI/IOC containers out there that do just this for us. I personally use StructureMap, but have always meant to investigate the competition.

Next week on Dependency Inversion for Dummies: We establish a shortlist of DI containers, compare how types are registered, define auto-wiring, learn about instance caching, and generally have the time of our life.

Currently rated 5.0 by 1 people

  • Currently 5/5 Stars.
  • 1
  • 2
  • 3
  • 4
  • 5

Tags: , ,

C# | Design Patterns

Layers are not tiers

by Ben Hart 28. September 2008 15:49

I've been spending more time at the asp.net forums recently. Aside from a bit of shameless self-promotion, I do genuinely enjoy helping other people out. I'm fairly opinionated, and I'm distinctly aware that many of my opinions offend what others consider to be rules, so it's turning out to be an interesting exercise in diplomacy too.

One recurring question people seem to have relates to layered architectures. The questions typically ask about n-tier architecture, or mention data access tiers and the like. What's fairly common is the use of the term tier and layer, and these are used by many interchangeably. This is incorrect.

What's a tier?

When I was at uni, we spent some time learning about the evolution of system architectures. The course started with mainframes, went into the development of the client/server model, discussed 2-tier applications, and the evolution to n-tier. We learnt about things like CORBA, distributed processing, and a lot more stuff I quite quickly forgot. At the time, though, I had a clear idea of what a tier was.

Mainframe It was clear that original mainframes hosted the complete application, and that interaction with the system was through interfaces served directly from the host.

Client/Server (2-Tier) Client/server made a lot of sense, too, and were the systems that I began to develop. We had rich (well we thought so) user interfaces that connected directly to a centralised database. It was clear to me that this was 2-tiered, the database was hosted on one machine, and the system that needed the data on another. Processing was indeed distributed, even if a little heavy on the client. Having all the power of client machines let us do some amazing things, never dreamed of on the mainframe.

I never really got n-tier systems back then, mainly since I never developed any. I understood academically, though, that n-tier systems introduced another tier between the client (desktop app) and the server (database), to distribute even further the load.

A 3-Tier System Architecture

In this middle-tier data could be aggregated before being sent to the client, for one, resulting in less network traffic. Business processes could be orchestrated from this middle tier too, and databases could be locked down to prevent all these clients accessing them. The clients themselves could be trimmed down, since most direct data access had been rolled into this middle tier. The clients were more about presenting the data, and acted as the interface between the user and the middle tier. Having this middle tier results in a 3-tier architecture. Further tiers could be introduced too, and rather than specifying the number of tiers each time, it's much simpler to just call the architecture n-Tier.

An n-Tier System Architecture

The key aspect, though, is that the system as a whole is distributed across many computers, to centralise related functionality, and distribute processing.

When did it all go wrong?

I think it became confusing when people started calling the middle tier(s) the business logic tier. Despite often being accurate, this is not necessarily the case. If I had an n-tiered application, it is quite feasible that all business logic remained in the client, and that my middle tier only simplified data access, and prevented all the clients on the network interacting directly with a database. This might have violated some original vision of what the middle tier should be, but it is feasible nonetheless.

If we had never started calling this middle tier business logic, we likely would have avoided all the confusion when we try and extol the virtues of a layered application architecture.

Layers

When most of us started developing data-driven applications, we generally added some controls to a form, or perhaps emitted some html from a script, and used this to display data we retrieved from a database. We generally lumped connecting to the database with retrieving the data and displaying it all within the same script or class, and were likely quite pleased with the results.

Over time we learned that mixing all this code together became quite a headache. If we needed to connect to a different database we needed to change connection information in numerous places. When we changed a column name in our database we needed to change SQL statements all over the place. When our user informed us that a customer must have at least one address, we had to add checks into numerous 'controllers'. Our developers with a better eye for design (but completely ignorant of databases) kept accidentally breaking our data access when they tweaked the appearance of the UI. It became clear that code that delivered such different functionality should be separated, and that code that is similar should be grouped, and never repeated.

So we introduced layers into our applications. Data access follows distinct patterns, and relies on the same configuration, so having a data access layer was an immediate quick-win. When we need to change database connection information it was obvious to jump into the data access layer. All SQL statements reside there too, so changing column names became much easier.

Business rules tend to change as often as our database, so centralising these were obvious too. When the rule was introduced that customers must have an address, changing this in one place meant that all dependent user input was validated, eliminating the possibility that we forgot about a seldom used interface in the admin section, for example.

This left our UI to only concern itself with processing user input, and displaying the results. Designers can work on this without interfering with any other application logic. We can have multiple different UI technologies (windows and web) running the same business logic and data access, they just need to call the now encapsulated functionality.

These are the typical layers we see in an application, often called data access, business logic and user interface, separated as such because the separation is obvious. While I've moved away from these layers per se, they're still widely used, and are what most people refer to when discussing layers (and, misguidedly, tiers)

A Traditional Layered Architecture

The diagram above represents a system distributed across three tiers, with a layered application architecture evident in the web tier. The separation of layers in the web tier is logical, they need not run on a different machine or process to exhibit it. Typically we'd divide them into different assemblies, but not necessarily. If these related concepts were grouped into classes found in the App_Code folder on an ASP.NET web site, I'd still have to concede that the site is layered along these lines.

So why is a layer not a tier?

Simply because a layer is about the logical separation of related functionality. The separation allows a much higher level of reuse within an application, and ensures greater maintainability. If we've separated out these layers into assemblies, we can likely plug these into other projects, and reuse them without any further development. If you haven't layered your application into related functionality, you'd better close your browser and start right now.

A tier, on the other hand, is all about physical distribution. In .NET we'd be making extensive use of serialisation and remoting (or xml web services), and all things quite hard to maintain. We might get a lot of reuse, but this is at the cost of much greater complexity, and lower overall performance. Distributing an application across physical boundaries (across machines and/or processes) should not be a trivial decision to make.

And, in a nutshell, that's why I think we need to clear up the semantics of tiers and layers. One cannot be argued against, the other needs to be argued for. The sooner we all are talking about the same thing when discussing them, the better.

Update: Added a few diagrams, and elaborated on them based on suggestions from Jim Tollan.

Currently rated 4.6 by 5 people

  • Currently 4.6/5 Stars.
  • 1
  • 2
  • 3
  • 4
  • 5

Tags: , ,

.NET | Application Architecture | Design Patterns

Dependency Inversion for Dummies: Constructor Injection

by Ben Hart 24. September 2008 12:06

Dependency inversion is not really a design pattern. It is more of a principle, one that if followed allows the creation of much more maintainable, testable and elegant code. It reduces coupling, and can increase cohesion.

It falls under a broader principle, Inversion of Control (IoC), and is widely used. I'm not going to go into great detail, mainly since that's going to reduce my average page-read time from 00:00:05 to 00:00:01, and I'm starting to find the tracking stats from Google a little depressing.

I read about Unity. That's Dependency Inversion.

Largely. Unity is Microsoft's first official entrant in the IoC container space. These are tools that simplify Dependency Inversion, and there are many others, most a lot more mature than Unity. These tools typically do much more than simple dependency injection, too, and they're worth looking into.

This post is not about tools, though, but rather the underlying principle that they support. I do reserve the right to jump on the tool comparison bandwagon at some point, though, and I will illustrate their utility in follow up posts.

What's a dependency?

Dependencies are everywhere in our code. Whenever one class relies on another class for functionality, a dependency forms between them - they become coupled. This becomes problematic when we wish to change the class that another depends on, anything beyond the most simple of changes tends to break everything else. Our code becomes brittle.

The following sample shows a simple console app that outputs tags. It uses a service that retrieves tags from a database, and returns only unique ones in a list. A fabricated scenario, but illustrative.

class Program
{
    static void Main(string[] args)
    {
        var tagService = new TagService();
        foreach (string tag in tagService.GetUniqueTags())
        {
            Console.WriteLine(tag);
        }
        Console.ReadLine();
    }
}
 
public class TagService
{
    public IList<string> GetUniqueTags()
    {
        ITagData db = new TagDatabase();
        return new List<string>(db.GetTags().Distinct());
    }
 
    public int TagCount()
    {
        ITagData db = new TagDatabase();
        return db.GetTags().Length;
    }
}
 
public interface ITagData
{
    string[] GetTags();
}
 
public class TagDatabase : ITagData
{
    private string[] _tags = new[] { "Word1", "Word2", "Word3", "Word1"};
 
    public string[] GetTags()
    {
        return _tags;
    }
}

In this code, TagService depends on a TagDatabase, evident when it creates one when we call GetUniqueTags. (Note that we're aware that it is better to program against an interface than an implementation, hence ITagData.) We also quickly realise that GetTagCount also creates the tag database, our first concern, so let's sort that out.

class Program
{
    static void Main(string[] args)
    {
        var tagService = new TagService();
        foreach (string tag in tagService.GetUniqueTags())
        {
            Console.WriteLine(tag);
        }
        Console.ReadLine();
    }
}
 
public class TagService
{
    private ITagData _db;
 
    public TagService()
    {
        _db = new TagDatabase();
    }
 
    public IList<string> GetUniqueTags()
    {
        return new List<string>(_db.GetTags().Distinct());
    }
 
    public int TagCount()
    {
        return _db.GetTags().Length;
    }
}
 
public interface ITagData
{
    string[] GetTags();
}
 
public class TagDatabase : ITagData
{
    private string[] _tags = new[] { "Word1", "Word2", "Word3", "Word1" };
 
    public string[] GetTags()
    {
        return _tags;
    }
}

All that we've done at this stage is constructed the database within the constructor of the service, allowing us to reuse it across methods.

Looks like a good layered application to me

We often see these patterns in a layered architecture, one that has UI depending on a Business Logic Layer (BLL), which in turn depends on a Data Access Layer (DAL). Often code in a form will create a BLL class, which in turn creates a DAL class for data. We'll often claim that by doing so we've separated our concerns, and can quite easily swap out a different database layer if we so desire. Given the above pattern, it's as simple as going through every BLL class, and changing the constructor to create the new DAL class. Each, and every class? That's not that simple...

It also creates ignorance amongst the users of our BLL classes that what they're actually doing is hitting the database. They just new up an object, blissfully unaware that they're actually newing up a whole chain of them. They might not even have the database set up on their machine, and get a fright when they first run the application.

Tell me what you want, what you really, really want

Apart from an anthem of an era most of us would like to forget, this turns out to be a good strategy in life. If we are open about our requirements, people can think about whether they are able to provide them. If they don't have what we want, they know they need to get it. If they can't get it, well, they better find someone else.

Ok, you've lost me with the spice girls wisdom. What does this have to do with dependency inversion?

Well, as I mentioned, we need to be open about our requirements.

I'll tell you what I want, what I really, really want

The easiest means to invert dependencies are to declare them in your constructor. Rather than allow the user of your class to whimsically new it up, force them to provide it the dependencies. This is known as Constructor Injection, when we inject the objects a class depends on into its constructor. I've modified the sample to illustrate.

class Program
{
    static void Main(string[] args)
    {
        var tagService = new TagService(new TagDatabase());
        foreach (string tag in tagService.GetUniqueTags())
        {
            Console.WriteLine(tag);
        }
        Console.ReadLine();
    }
}
 
public class TagService
{
    private ITagData _db;
 
    public TagService(ITagData database)
    {
        _db = database;
    }
 
    public IList<string> GetUniqueTags()
    {
        return new List<string>(_db.GetTags().Distinct());
    }
 
    public int TagCount()
    {
        return _db.GetTags().Length;
    }
}

Notice that the console now creates the service providing the newed up database, and that I can't create the service unless I've got a database to give it. I've decoupled the two classes, with the only dependency being that which matters, the interface.

I can now use the service against any class that implements the ITagData interface, allowing me great flexibility to unit test it, implement ITagData's that retrieve from any source, and so on.

The service is immediately a lot more reusable, and its purpose has become a lot clearer. Rather than being a class that creates a database, retrieves all tags and finds those that are unique, it's now a class that takes a given database, and returns those tags that are unique. That subtle difference goes a long way towards providing better cohesion, and a code base that's built to last.

Where to from here?

The above sample relies on the console app to create both classes, with one being passed into the other. In this simple example this is easy, but in real applications the number of classes that are created quickly spirals. Further, when we need to use the service in a number of places we'll end up repeating creating these classes again and again, resulting in some equally brittle code.

Join me next time when we look at some creational patterns that solve this, and bring in some of the tools I mentioned above.

Currently rated 5.0 by 4 people

  • Currently 5/5 Stars.
  • 1
  • 2
  • 3
  • 4
  • 5

Tags: , ,

C# | Design Patterns

Design Patterns 101: State Pattern

by Ben Hart 20. September 2008 14:07

Let's get back to basics.

I've learnt over the years that there are common problems encountered when developing software. Often one finds the same recurring challenge in code. Something seems familiar, and you're sure it's not the music blaring from your neighbour's earphones. You've a growing feeling that you've seen this before, a recognition that you're repeating yourself, a developer's déjà vu. You've just found a pattern.

Design Pattern? Is that like the paisley wallpaper in my bathroom?

No, but sort of. Design patterns are formalised solutions to common software problems. While we like to think that we're special, the truth is that most software problems have already been solved. You're actually one of millions hacking away at your IDE. One of millions who's had to step back, and say, "hey, what's the best way to do this?" The best ways have a habit of recurring, and eventually become distilled as a named pattern.

There is no better way for a developer to spend their time than familiarising themselves with design patterns. If you were sitting with a car designer who was pondering how best he could get his funky new Italian sports car rolling on the tarmac, you'd be quite quick to quip, "Dude, it's called a wheel, connected to an axle. Where did you go to car design school?" Software design patterns are to your software as wheels, axles and doors are to a car designer. You customise them to your need, weave them together while building your masterpiece. You shouldn't dream of reinventing them.

State

The problem that the state pattern solves is everywhere. Look into your code and find those switch's and nested ifs. Look at them, and see if you repeat the same switch or nested ifs elsewhere. Yes? Really? Man, you better get yourself some state.

State is useful when we find ourselves manipulating an object differently based on the object's state. Imagine we had to deal with orders in our system. An order is for a customer, and it can be dispatched to that customer. We cannot change the customer of an order after it has been dispatched. Our class might look something like this.

public class Order
{
    public string Customer { get; set; }
    public bool IsDispatched { get; set; }
 
    public void ChangeCustomer(string customer)
    {
        if (IsDispatched)
        {
            throw new Exception("Order has already been dispatched");
        }
        Customer = customer;
    }
 
    public void Dispatch()
    {
        if (IsDispatched)
        {
            throw new Exception("Order has already been dispatched");
        }
        IsDispatched = true;
    }
}

We've only implemented the simplest of features, and already we're seeing ourselves repeating ourselves. I hate repeating myself. Look at those checks for IsDispatched. They're ugly, and fragile.

If we puzzle over the above class, we're quick to notice that order actually consists of two states, let's call them "New" and "Dispatched". A "New" order behaves differently to a "Dispatched" order.

A battle of two approaches

Some might say at this point that what we actually have is a hierarchy, and instinctively jack out the base class Order, with 2 sub-classes New and Dispatched. For better or worse, an object can't be two types at once, and transitioning it from New to Dispatched is going to be more painful than gender reassignment surgery, and probably less effective.

Besides, there's a saying that we should favour composition over inheritance, and I think it to be true. Inheritance paints us in a corner, it constrains our code. As soon as sub-classes depend on their base's behaviour, we can never easily modify the base. We might save a few lines of code here and there, but we pay for those later.

What we need to do here is introduce a class that represents the Order's state.

public class Order
{
    public Order()
    {
        State = new New(this);
    }
 
    public IOrderState State { get; set; }
    public string Customer { get; set; }
 
    public bool IsDispatched
    {
        get { return State.IsDispatched; }
    }
 
    public void ChangeCustomer(string customer)
    {
        State.ChangeCustomer(customer);
    }
 
    public void Dispatch()
    {
        State.Dispatch();
    }
}
 
public interface IOrderState
{
    bool IsDispatched { get; }
    void ChangeCustomer(string customer);
    void Dispatch();
}
 
public class New : IOrderState
{
    private readonly Order _order;
 
    public New(Order order)
    {
        _order = order;
    }
 
    public bool IsDispatched
    {
        get { return false; }
    }
 
    public void ChangeCustomer(string customer)
    {
        _order.Customer = customer;
    }
 
    public void Dispatch()
    {
        _order.State = new Dispatched();
    }
}
 
public class Dispatched : IOrderState
{
    public bool IsDispatched
    {
        get { return true; }
    }
 
    public void ChangeCustomer(string customer)
    {
        throw new Exception("Order has already been dispatched");
    }
 
    public void Dispatch()
    {
        throw new Exception("Order has already been dispatched");
    }
}

Note, firstly, that the order does a lot less now. It defers much of its decision making to its state. Rather than trying to change its own customer, it asks its state to. It doesn't dispatch itself, the state takes care of that.

Secondly, note that we have a lot more classes. This is often a good thing. A class should have a single responsibility - it should define, exhibit and encapsulate one concept. When something goes wrong, we know exactly where to look. If we're curious, we can take in a whole concept just by reading one class.

In this code we have a simple interface that defines what each state must be able to do. We can open New and understand what a New order should do. I can change this behaviour easily, without worry about what might happen to my other states, or Order. Similarly for Dispatched.

And, most usefully, should I need to introduce a new state, I just need to create one class, and define the transitions between it and the other states. My order remains unchanged.

Wrapping up

Note that this is not necessarily the best example, and you might right to point out that such simple requirements have been over-engineered. State really shows its mettle when you have fairly complex states, and many of them (but is extremely useful even if not!). Consider that Order would most likely have "New", "Approved", "AwaitingDispatch", "Dispatched" and "Delivered" states. Complex workflows like these are crazy to do without State.

Other good examples are adjusting calculations based on state (if the account balance is less than 0, charge interest, greater than 500 give more interest), changing rewards based on importance (gold customers get double points), and so on. Good examples are everywhere. Unfortunately, I didn't think of them when I started writing this post.

Technorati Tags: ,,

Currently rated 5.0 by 1 people

  • Currently 5/5 Stars.
  • 1
  • 2
  • 3
  • 4
  • 5

Tags: ,

Design Patterns | C#

Powered by BlogEngine.NET 1.4.5.0
Theme by Mads Kristensen

About me...

I'm a passionate .NET developer, with C# my language of choice. I've been at it for a number of years now, and enjoy that I'll never shake the feeling I'm just starting out.

I love software, and I love building it even more. I love knowing that my work facilitates others', and that one line of code at a time, we're increasing our capability.

More...



Page List