Stop Worshipping the Singleton Pattern

It's about time I wrote this down - I've been thinking this for quite some time, and I found myself repeatedly stating and explaining it to people. Recently, when the discussion came up yet again, I decided to write it down.

I've been taking part in training activities for quite some time now in parallel to my day-to-day work. Most of that is development training (programming, design, good practices, etc.). Specifically when it comes to teaching design (and I'm not getting into how it should be done or whether or not it's even possible to a satisfying extent), the issue of design patterns always comes up. That makes sense, given DP is extremely important for actual hands-on software engineering.

The problem starts when people tell me "look, I really think it is important for that guy to learn DP - it will be a shame if he ends up not knowing what a Singleton is".

Really? the first thing you come up with as an example for a useful design pattern is Singleton? I wouldn't have minded it if it was just that comment. However, this often leads to a discussion where the programmer in question defends Singleton as the "most important and most useful design pattern he ever encountered". Now don't get me wrong - Singleton is indeed an important design pattern and it is important to know what it is. Regardless of that, I believe it is by far not the 'most important' or 'most useful' one.

The most famous design patterns today (most notably the ones from the GoF), always comprise of two parts with varying emphasis. The first is the concept - the main idea behind the pattern. Knowing the motivation, structure and collaborations of a pattern is key to using it correctly. Besides, the concept is important because it tends to be language-agnostic, and assuming you understand it, you can take it with you wherever you go (for example most OO imperative languages).

The second element is the syntactic sugar - how you end up implementing the concept in your language. GoF includes samples for C++ and Smalltalk, for example. It makes a lot of sense knowing the code to implement the patterns in 'popular' languages (C++, Java, and C#, for instance), including some nifty tricks or syntactic sugar. It will improve your ability to use patterns more quickly and more fluently in projects you might encounter in these languages.

Bottom line - it is clear that the most important part of the two is the concept part.

Enter the Singleton pattern. Its syntactic sugar part is immediately apparent (in C++, which is I think the most ubiquitous example) - it uses static members and access control to ensure the desired behavior. Even if you're not in C++, other languages have a similar implementation as well. However, the issue becomes clear when you discuss the concept part. If you take away syntax, the Singleton pattern is a global variable with an 'if' condition ensuring it's initialized once. Not only it's not groundbreaking, it's trivial even for beginners.

What's that you say? All DP can be reduced to what I just said? No. Take Abstract Factory for instance. It's power is in the concept - properly separate an interface to decouple object creation. Take Memento, which has a fundamental concept of taking state snapshots as objects. Take the State pattern, which leads to extremely simplified code and even several elegant solutions for concurrency. With all that, what you define as 'most important for a person to know' is a glorified global variable?

The list goes on, of course, and I'm not arguing the Singleton pattern is the 'crappiest' pattern. there are other patterns which are quite simple and don't have a major concept to introduce which isn't known to novice programmers. Once again as a disclaimer - I do think they are also important and shouldn't be dismissed.

So why does Singleton get thrown in the air so quickly when DP are mentioned? Quite simple - it is short, concise, and easy to remember, explain and demonstrate. Also, it is very hard to write modern projects without needing a singleton. Be it a configuration mechanism, networking code (reactors, anyone?), metadata storage or similar facilities - your solution is likely to have one. It will likely be an object, it will likely be global, and from that point, not controlling the singularity of it will be plain stupid. This is why it is super easy to just throw in a static method and shift some members around and presto - you have a Singleton. If the GoF had 'linked list' as a DP, it would also have been very popular.

My main claim is that the true power of patterns comes from the concepts behind them, not from the brevity of their syntactic implementation or ease of being explained. People who claim they make heavy use of design patterns, while actually all they do is use the Singleton pattern a lot, should try to actually read the rest of the book.

Comments

blog comments powered by Disqus