Cool Singleton Article

Three years ago, I wasn’t against singletons. Times change. You learn more. Once fully committed to TDD, loose coupling and reusability, there’s really no place for a singleton. In my browsing today, I saw it referred to as an anti-pattern. I don’t know if that’s a shared opinion across the masses, but I concur.

That’s not to say that sometimes your application doesn’t need a shared object. When it does, though, it should be the application that manages the shared object,  not the the object itself.

For the same reasons, except in rare known circumstances, statics are automatically red flags when used in objects. Its ok for a consumer of the object to keep a static reference if it chooses but, again, that’s the choice of the consumer not of the object. (A valid exception is private read only literals. For example:

 </p>  <p>// based on a true story.    <br />private static readonly string[] _logCategories = new string[]     <br />{ &quot;cat 1&quot;, &quot;cat 2&quot;, &quot;cat 3&quot; };    <br />

These days, I’m very passionate about my position on statics and singletons. SINGLETONS = BAD. OBJECT LEVEL STATICS = BAD. Two weeks ago it was suggested, at work, that one of our major components should be converted to a singleton. I disagreed. Everything in the object is already static anyway; instantiating it doesn’t really do anything other than give access to the static cache. Anyway, I expressed my opinion about it. We’ll see what happens, but its none of my business.

Unity and its lifetime manager eliminates the need for singletons and statics. If you’re not using unity, then maybe you need to hang on to a static reference. Even if you are using unity, maybe you have a static reference to the unity container to eliminate all other static references. (Or, maybe not. I prefer to inject the container rather than have everything use a common static container. But, I know that lots of people just put a static reference for the entire app to share. If you do that, though, then you’re compromising the design.)

Anyhoo, I was poking around on StackOverFlow.com and came across a question about singletons. One of the responses referred to this article.

http://www.yoda.arachsys.com/csharp/singleton.html

I tried writing something like this once, but his is much better. I remember mine being a disaster. In fact, I’m not going to bother looking it up. (Also, I think I wrote it before I was against them.)

This lays it out pretty nicely, though I don’t fully agree with it.

I’m not responding to the author’s comments here… I’m just looking at the code samples and responding with my own opinion which may or may not agree with is.

Version 1 – Complete crap. This is a very common mistake not only with singletons but with thread-safety in general.

Version 2 – No good. That lock is only ever useful once, yet you lock every time you need it.

Version 3 – He doesn’t like this one. I do, though I write it a little differently. He makes some interesting comments. For example: it doesn’t work in java. I knew that, I just didn’t remember why. (I ran into that several years ago, but forgot the explanation). More relevant, he states it may work in .Net 2.0 but doesn’t conform to the standard. That’s food for thought. I didn’t know that. Regardless, this would be third on my list of best approaches.

Sidebar: I prefer a get method rather than a property (even though fxcop hates that), but I’ll go with the property.

 private static Singleton _instance = null; private static object _lock = new object(); public static Singleton Instance { get { if (_instance != null) { return _instance; } lock (_lock) { if (_instance != null) { return _instance; } _instance = new Singleton(); return _instance; } } } 

Version 4 – Now we’re getting somewhere. This is the way to do it.

Of course, this isn’t lazy loading. If you do something with the class other than call the singleton, the singleton is going to get instantiated for no reason. But, your class should do exactly one thing, so that shouldn’t be the case.

This would be my second on my list of best approaches.

Version 5 – I’ve never done this one, but have seen it twice at work. (One of them was a demo of a non-work related project. I don’t remember what the first one was). If you need lazy loading, then sure, this will work. But, per my point in Version 4, you shouldn’t need lazy loading.

Version 6 ?!?!?! – The article doesn’t have a version 6, but another way to do it is to use the static constructor rather than the variables initializer. In the end, they end up being the same thing because the static initializers just get moved to the static constructor anyway. I think that using the initializer reads much better.

It was once argued to me that you can’t do anything complex in the initializer. All you can do is instantiate something. Not true… you can intialize to the result of a static method call. Put all the work in the method call.

So there you go. To summarize, here’s my list of preferred approaches

  1. I the name of all that is holy in the religion of your choice, don’t do it. Say nay to the singleton. there are plenty of swell better alternatives.
  2. Version 4 – Static initializer.
  3. If you must lazy load (in the scenario where the object only exists for purposes of the singleton), this is the way to lazy load. Despite the other guy’s valid objections, I’ve been doing this and preaching this for years. It always works. (I call it check/lock/check).

One is the overwhelming winner. There is always an alternative to singelton. Don’t put the lifetime management of your object inside the object. Its none of your object’s business about how its used… its a unit of work. Let the consumer decide how to best implement that unit of work.

Advertisements

Leave a Reply

Please log in using one of these methods to post your comment:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s

%d bloggers like this: