Common Singleton Patterns

Another thing that we covered at my recent presentation was common use cases of Singletons.  The problem with artificial examples is that you’re often presented with objections that the point you’re making is restricted to the particular example you’ve given.  So, instead, let’s take a look at some of the most common usages of singleton patterns and explain why you’re breaking your code to use them:

The Current User

I’ve lost count of the number of times I’ve seen the current logged-in user accessed through a static method.  It’s extremely tempting: there’s a phenomenal number of parts of your system that rely on knowing it, and you don’t really want to keep passing the user around everywhere you go.

The problems start when you look at the implementation.  Chances are, if you’re writing a web application, you’re pulling that information out of the HttpContext (or worse, using a component that you don’t know uses the HttpContext).  The first time you try to add in some batch processing in a console application, you’re going to discover one of your main dependencies just fell away and you don’t have a backup.  You could try simulating HttpContext.Current, and you might even succeed (I doubt you’ll enjoy it) but you’ll now have a console app that pretends to be a web application just to support some code that you’re already starting to think of as legacy.

However, even if you could deal with this, you’ve got other problems.  What happens if you wanted to be able to impersonate another user?  It might not sound like much of a concern right now, but wait till you’re supporting the application and want to see what the other guy can see.  Sure, you could deal with this by hacking around with the static methods, but it would have been a whole lot easier if you’d just passed the correct routines what user you wanted.

Another concern: sometimes a workflow has to go through multiple users, an approval process is an obvious example.  Do you really want user A to ask user B to do something and then discover user B doesn’t have the permission?  Much better to be able to pass a user other than the current user into the permission logic and let user A be able to see who exactly can help him.  All of a sudden, your permission system doesn’t rely on the current user at all.

You might be thinking that all of this could be avoided by designing all of these features in at the start, but you’re going heavily into waterfall thinking there, a methodology that has been comprehensively found wanting.  Better is to start with a flexible design that allows you to change behaviour when you need to, and for that you need to be passing around instances, not calling static methods.

The Current Time

If you’ve got DateTime.Now in your code, there’s a good chance you’ve got a bug nearby.  Think about what happens when Daylight Savings Time kicks in.  However, even if you’ve changed your code to read DateTime.UtcNow, you’re still going to have all sorts of problems.  Here’s a concrete example: I have a order processing system with a batch job for Day End.  It uses the current time all over the place, including the truly basic task of working out what day it needs to be processing.

So, what if I want to run the batch on specific data?  On a day anything other than today?  Well, I’m going to have to change the system clock.  You thought it was bad trying to fake an HttpContext, faking the current time is much, much worse.  You’re actually messing with the BIOS.  All because you didn’t write the following code:

private interface IDateProvider {
    DateTime Now { get;  }
}

You can go significantly further down this road: I have unit tests in one project of mine that explicitly tests whether or not the code behaves correctly in Jersey City.  I wouldn’t be able to do that if I hadn’t abstracted out the concept of time from the system.

Logging

It’s amazing how many people approach logging through a singleton approach.  If you’re using a framework, you might not care about this:  there are people who’ve pretty much written the last word on logging and all you need to do is write a configuration file.  The very completeness of the solutions can lead you to thinking that static methods are the right solution for the problem.  Actually, they’re not.  The completeness of the solution has merely minimized the damage.

In our firm, we’ve got a set of static methods used to write to the event log.  Now, unlike using something like log4net, this isn’t a massively configurable and complete solution, it’s just what the developers at the time wrote.  So, you can’t affect policy: you can’t, for instance, filter out logging on any level other than changing the logging library.  You can’t disable logging if you’re running tests.  In practice, you can’t do very much at all.  Contrast this with the solution in one of our fix feeds.  It uses log4net, but more than that, it uses Castle’s logging facility.  Here, we get a logging object passed into the constructor of the class that needs logging.  This logger is specific to the class that is using it: try implementing that using static methods.  (You can: you just need to either pass the caller into every last call or walk the stack trace.  Neither solution is desirable.)

Again, the singleton pattern actually makes things worse, not better, for logging.

Configuration

Anyone whose dealt with .NETs config files for a while will have come across some standard problems:

  • The typeless nature of AppSettings is a pain in the neck.
  • Access to configuration settings can come from anywhere.
  • You’ve often got to include multiple different settings for the same value, to support different assembly’s interpretation.

The second two are because ConfigurationManager is a singleton.

Let’s see how this happens: ConfigurationManager exposes a public static method for AppSettings.  Anyone can use AppSettings however they like. and guess what?  They do.  Now, here’s a common approach to dealing with this problem:

  • Only one class can access AppSettings.
  • Often, this class is a static class, so only has static accessors.
  • Any conversion to correct types is handled by this class.

Now, this is much better, and addresses the previous problems, but there’s still some problems.  The first comes directly from the singleton nature of the solution.  For instance, if you’ve got a single database connection, it might not seem like that big a problem, but the day you have two instances and want to load data from one to the other, you’ll discover that the fact your data access is hardwired to a particular configuration setting is causing you problems.  This is because you’re still breaking the Single Responsibility Principle: your data access class shouldn’t be making decisions about how to handle configuration, and accessing a static method on a configuration class isn’t different from reading the configuration setting directly as far as dependency management.

Another problem is that having a “configuration” class doesn’t really scale: the more assemblies you have, the less likely they are to want to share their configuration settings.  Now, you can always just simply have separate configuration settings for different concerns.  This is actually a good idea, but it still doesn’t deal with what happens when you actually wanted to share configuration settings.

Truth is, most classes and even most assemblies, shouldn’t need to know about configuration settings at all.  Configuration isn’t like logging: logging decisions have to be in the class doing the work, configuration decisions don’t.  Why not just pass the connection string into the constructor?  Same with the mail server, same with the retry policy.  Now, the only place that needs to read configuration is the Main method.

It’s all Microsoft’s Fault

Bill actually has a lot to answer for on this.  In each case we’ve deal with, the design of the .NET API has led us into long-term problems for a bit of short-term gain.  Developers often recognize that they’ve got a problem with HttpContext, the current time or configuration soup, but they don’t know what to do about it.  The .NET framework has lots of these somewhat curious decisions: an API is developed for the lowest common denominator, with the understanding that more sophisticated developers will code around it.  At least it’s usually possible to do so.  Static methods, where they have to be used, can usually be wrapped in instance methods with relatively few ill effects.  In the first case, a simple IIdentity interface which returns the name of the current logged on user can hide an awful lot of HttpContext-related problems.  But you do need to understand that this coupling happens, that it’s damaging and how you can avoid it.

To re-iterate, singleton patterns are dangerous, even those that Microsoft have implemented.

Published by

Julian Birch

Full time dad, does a bit of coding on the side.

One thought on “Common Singleton Patterns”

Leave a comment