Steve Smith's Blog

Musings on Software and the Developer Community

Code Review – Singleton Pattern Issues

One of my applications relies on a singleton pattern to create a single instance of a server which processes requests from many different ASP.NET handlers.  It is created using pretty much standard Singleton code:

public static Context CreateContext()
{
    return CreateContext(new ConfigurationFileSettings());
}

Recently, this server needed to be made aware of whether requests were coming into it via SSL or standard HTTP.  The solution that was checked in (and which worked and passes local tests) is to create a new property of Context called IsSecureConnection, and to allow this to be passed into its public constructor like this:

public Context(ISettings settings, 
    bool isSecureConnection)
{
    this.Settings = settings;
    this.IsSecureConnection = isSecureConnection;
}

This is pretty much classic Dependency Injection and most of the time is what I would consider the right approach to the problem.  However, in this case it fails to take into account how this object is used, because of the fact that it’s using a Singleton.  And in this case nothing ever calls this constructor anyway – the actual solution that was applied instead only made use of the IsSecureConnection property (which was read/write).

The client code in the ASP.NET handlers that invokes the Context class looks like this (before adding any support for SSL):

Context engineContext = Context.CreateContext();

After adding support for SSL, this code became:

Context engineContext = Context.CreateContext();
engineContext.IsSecureConnection = isSecureConnection;

Looks fine, right?  Run it through some tests – things behave as expected.  SSL requests get routed to the Context object with IsSecureConnection = true.  Regular HTTP requests get routed with IsSecureConnection = false.  Stick a fork in it and ship it…

Global State and Static / Singleton Objects

The problem of course is that many different ASP.NET handlers are talking to the same exact instance of Context.  In this particular application, this is taking place tens of times each second.  So if you imagine that 49 requests come in during a given second over HTTP and 1 comes in over HTTPS, it’s quite likely that while the Context has had its IsSecureConnection property set to one value, it’s in the middle of processing another request.

The other issue here is that whether or not a given request is using SSL is a lower level concern to the Context object which is in essence a request manager.  The only call that the handlers ever send to Context is something like this:

Response myResponse = engineContext.GetResponse(_myParamsDTO);
This is the level of detail where the HTTP/HTTPS information is important, and the value should be passed at the method level into the GetResponse() method either as a separate parameter or as part of the DTO currently used.  Then, even if many requests are being handled concurrently, none of them will be setting the global state of the singleton Context object, so all of them will be processed correctly.
 
Recommendation
 
In general, I’m not a big fan of the Singleton pattern, and even less so of static objects and methods.  They’re extremely difficult to test and prone to problems with synchronization and multiple threading like the one shown here.  In development, things that work just fine often end up failing in production under load.  If you think your application really needs a static or singleton, consider whether or not this is a premature optimization, and build the application using standard object creation semantics until you have proof that this will not be capable of meeting your design’s needs.
 
If you do use static methods, you should be careful not to new up objects in them.  That is, they should be leaf nodes in your object/call graph, operating only on their parameters and instantiating nothing on their own.  In this way, they remain testable and do not introduce nasty dependencies into your application.

    kick it on DotNetKicks.com

Wednesday, 26 August 2009

Comments

 avatar

ds r4 said on 03 Oct 2009 at 1:57 AM

Thanx for the information. I searched MSDN for a class related to SSL connectivity. I couln't find any. there must be some as most the sites with authentication requires SSL. please provide information over the class name and it's dll.


 avatar

buy structured settlement said on 02 Feb 2010 at 1:43 AM

I have been using a Func pad for the last 6 years. Nothing comes close. I use the ArchType model with the aluminum bevel and found that to be the best (it helps to hold it's shape better). Love 'em.