In my few days of being a developer, I’ve heard and seen lots of talk about Singletons. Things like
Singletons are teh suck. Don’t use them. EVAR.
Singleton’s saved my life and marriage!
In fact, I might’ve been the person that said both of these… gasp!
I never like to speak in absolutes, so I’ll say it this way (see what I did there?)… if you’re striving to implement a singleton, you’re probably wrong. For all you guys that are right, I guess you’re right, and you can leave now, I guess. This might help you out.
I was reading a blog from Mr. Dependency where he was talking about statics and basically what amounts to global state, and how that binds you into globally available, global data, which usually (always?) turns into anarchy.
How do we always get ourselves into this mess if we know it’s bad in the first place? Well, some of us (those who are now zombocomming, from above) don’t know it’s bad in the first place, and the rest of us probably do it because it’s easy to implement, and we understand it. Long story short, we can do the singleton implementation in our sleep, so we pull out the singleton hammer, and smack the nail. It always goes in a little sideways, but at least it goes in.
Maybe we should be using a different hammer?
What I’d like to do now, is propose to split singleton in two. I think there are two distinct responsibilities that the current thought of ‘singleton’ introduces. It:
- Manages Session Scoping/Lifecycle/Lifestyle (albeit, poorly, only one strategy is available)
- Disables the ability to create more
When I talk about this out loud, I call the two approaches the singleton implementation pattern, and singleton lifecycle.
What I am a fan of, is the singleton lifecycle. You create one of those objects, and use it throughout the application. You don’t get messy and allow global access to it all over the place (which necessarily happens when you have global state). You intentionally inject it to collaborators, and intentionally don’t inject it to non-collaborators (don’t just hand this guy out willy-nilly, he’s important).
So naturally, the naysayers ask/demand:
How do you manage that there is a public constructor on this class!? Dev’s are going to be new’ing this thing up all over the place!
False. Use a DI tool and let it manage it for you. Or establish a convention with your team, and enforce it through social contracts.
Both of these approaches allow your scope lifecycle turn into whatever you want at any time, in case you decide global isn’t what you really want. It can be application session scoped, or some other scope, test scoped, or whatever you want… incredibly flexible.
If you go with the DI tool approach, instead of tying yourself to a particular scope, you can now have any scope you want, by changing a configuration parameter. Delaying decisions until the latest responsible moment… seems like I’ve heard that one before.