When it comes to software architecture classes or programming courses in general, the term “pattern” seems to be the ultimate buzzword at universities. “Use this pattern here, that one over there, oh and here do it like the GoF but hell don’t you dare doing it like that guy did back in 1995”. The Gang of Four (GoF) has done quite a job promoting more or less standardized ways of dealing with certain coding problems. Most of these patterns are straightforward and frankly plain logical, but it’s good to read about them anyway. However, there is one specific pattern that gets hate from (seemingly) every coding-related website on the Internet. I’m talking about the infamous Singleton Pattern, probably the most overused and frequently misplaced programming anti-pattern of all time that’s creeping in even the best code bases — and of course it sucks!
I agree, it does come in handy more often than it should, but so does simple copy & pasting of code instead of spending time on the proper design of data structures and class responsibilities. Still, no serious coder does this and gets away with it (in my perfectly flawless universe at least, the reality looks rather dark and gloomy). Developers that just rush in usually get bitten in the rear sooner or later.
The Singleton Pattern gives programmers a false impression of good design because it provides short-term simplicity at the cost of long-term maintainability and scalability. Do not be fooled: just because the Singleton Pattern makes certain tasks easier at first glance doesn’t mean it’s a good choice in the big picture of your software design — and here’s why.
You’re probably more or less familiar with the Singleton Pattern, so I’ll keep this section short and concise. A basic scaffolding (no actual functionality) of said pattern in C# could look like this:
public sealed class Singleton
Looks may vary, depending on the programming language and the choice of features used for the implementation. The code provided here is a simple-thread-safe version using lazy initialization. Methods can later be called directly with
There are several major issues with this pattern that I’m going to talk about in the following section. Personally, I am on the same side with the guys claiming that the Singleton Pattern should lose its pattern status and be declared an anti-pattern. Especially in larger applications and more complex projects where hundreds of classes are involved, this anti-pattern almost always does more harm than good. Here are the main reasons why the Singleton Pattern sucks and why it should generally be avoided at all costs.
The main problem with the Singleton Pattern is that it is a sorry excuse for global variables — the bane of every programmer’s existence. Applying the pattern introduces global state into the application domain. This is generally bad because global variables don’t care about the program’s structure, the state of its threads and its execution flow. While accessing the singleton object can be made thread-safe (as shown in the example above), the actual state is still global, which — in almost all cases — is undesirable.
Having global and persistent state is also a huge problem for automatic testing. Effective unit tests are designed to check one single individual task or operation while running independently and concurrently. Having to deal with global state can have devastating effects where tests randomly fail or succeed depending on the order of execution.
Most of the singleton classes I’ve stumbled across (and had the pleasure to replace) were incompatible with general software architectural design principles. They often serve as aggregates for different (sometimes even unrelated) functionality, thereby introducing various dependencies and frequently violate basic single-responsibility concepts.
Singletons tend to be used widely in different parts of the application by different classes which then all implicitly depend on the entire set of dependencies introduced by the singleton aggregate. This is undoubtedly terrible design.
I have seen so many cases where coders are using the Singleton Pattern simply to avoid having to pass an object down the scopes. Singletons are accessed with “hard references” to a static object that cannot be abstracted and refactored easily without causing things to break all over the program. This is especially problematic in the not unlikely case that there is a sudden requirement to create more than one object of this type.
Reusability and maintainability go down the drain…
If there were only downsides it wouldn’t be a pattern, would it? It does indeed have some benefits, especially when the only obvious alternative is global variables. For one, singleton classes give the programmer more direct control over the creation process and allows for a more complex initialization that is done within a constructor. This is often not possible with global variables, though keep in mind that they should never be used anyway.
I am pretty sure that there is a small number of use cases that justify the application of the Singleton Pattern. From the top of my head, however, I can only think of the one classical example: log files.
Loggers fall into the category of singleton-tolerable classes because they commonly channel information from different sources into one single log file. Without a global way of accessing logging functionality, a log object would have to be passed down the entire call hierarchy, involving a vast number of classes and methods. Since this log object would normally always be the same instance anyway throughout the entire runtime, the creation of a singleton class is perfectly justifiable here.
You may have noticed that there is an awful amount of objectivity going on in this post. That’s probably because this topic has nothing to do with personal taste or disturbing experiences, but solely with logical design decisions.
Just this morning I had to deal with a problem that involved a singleton class, which gave me enough incentive to start writing on this article.
It boggles my mind to realize how often this anti-pattern is still being used, so I hope to spread a word of warning that might make someone think twice before blindly applying the pattern just out of momentary convenience.