Friday 15 October 2010

A Tale of Singletons and Global State

Some weeks ago, I received one odd feedback. I was talking to this guy and he said "A fellow of mine read in your blog that you are in favor of singletons. Is that true?" I remembered that the post was ultimately about Design Patterns. I used some extrapolations of the Singleton Pattern to get to Dependency Injection. I never supported singletons. I just used it as a very simple and known pattern to get to something bigger. I was so astonished by the question that I couldn't answer it. At the time, I was not able to support my real opinion. Today, I'll try to express myself clearer.

According to wikipedia, the singleton pattern is a design pattern used to restrict the instantiation of a class to one object. This is useful when exactly one object is needed to coordinate actions across the system. In the usual way it's implemented, there's a private constructor and an static property or method that always returns the same instance. There are a few big problem with such a class. One, it violates the single responsibility principle. A class should not be responsible for its own lifetime. Two, the singleton instance is attached to the global state.

It happens that both these problems can be eliminated and we still have a singleton. The creation of the singleton could be delegated to a factory. And the factory doesn't have to be attached to the global state. That's what differentiates a good singleton (one instance per factory) from a bad singleton (one instance per AppDomain or JVM).

I have seen a good deal of bad singletons in projects I've worked on. They caused me pain. Many times, I was forced to convert some of them into something nicer. I know how hard they are to test, and how they tend to create hidden dependencies. I don't like the bad singleton. Some people even say they are evil. Nevertheless, they are ubiquitous. Just for the sake of the example, let's consider the .NET framework. Here is a list of singletons (and static functions that access some form of global state) built in the framework:
System.AppDomain.CurrentDomain;
System.DateTime.Now;
System.Environment.*;
System.Globalization.CultureInfo.CurrentCulture;
System.IO.File.Open(...);
System.Random.Random(); //uses System.Environment.TickCount
System.Threading.SynchronizationContext.Current;
System.Threading.Thread.CurrentThread;
System.Threading.Tasks.Task.Factory;
System.Transactions.Transaction.Current;
System.Web.HttpContext.Current;
System.Windows.Application.Current;
System.Windows.DependencyProperty.Register(...);
System.Windows.EventManager.*;
System.Windows.Forms.Application.*;
System.Windows.Forms.MessageBox.Show(...);

Of course, .NET is not an exception. All the main platforms we use today have quite a few examples like those. Do you know any singleton-free programming platform? The only one I've heard of is Newspeak. Why aren't there more languages like that? Why do we use programming platforms so packed with vicious singletons and APIs that access global state? I don't have a complete answer to these questions, but one thing is certain. There must be a good reason for them to be there. The cost of removing all singletons probably doesn't pay off. In fact, I think it's close to being impossible.

Let's consider the computer's clock. In .NET, we can read the current time by reading the DateTime.Now property. Although it's not a classic singleton, it's completely equivalent to one. It could be like that: Clock.Instance.GetCurrentDateTime(). The real problem here is that we are accessing global state. Every time we read the value, it changes. Now, is that such a bad thing? Of course not. A clock is supposed to move without being told so. A stopped clock is useless. Would you blame the framework designers for coding a singleton in such a special case? I wouldn't. There's usually only one physical clock available in a machine anyway.

What about a logical clock? I needed one once. The application I came to work with had a rule engine. Many of the rules were dependent on the current date and time. For example, the customer would be eligible for a fee waiver only if his/her last payment were due for less than a couple of days. No surprise, the team found out that rules like that were the hardest to test. The only way to fake the system time is by changing the computer's clock. However, it affected the application in other unforeseen ways, and that was not a viable solution. Not being able to test all the rules, the original team did the best they could with the time that was given to them. They deployed the application without testing everything.

Nonetheless, the situation can always get worse. Another problem appeared. We realized that many users were working in a different time zone and that the application was using the machine's local time. It was supposed to use US Central Standard Time. Compensating the local time zone wouldn't fix it because some users had an incorrect time zone set. And the users could always fiddle with the local clock. In the end, we simply couldn't trust the system's time.

The solution? I created a logical clock that gets synced with a trusted server every now and then, completely independent of the local time. I just provide the rule engine with a proper clock and the time zone bug was fixed. Since there's only one synced clock per rule engine (and one rule engine per application), the clock is a singleton. A good one though. Good enough to have one additional benefit. We could now test the time-dependent rules easily. All we need to do is to mock the clock.

So, what's my take on singletons? They are a necessary evil that has to be understood and handled with care. If you really need to create one, make sure it's a good one.