Why Singletons Are Okay
(Programming)
Singletons are class objects designed so that only one instance of the object can exist in a program. For example, for various reasons, you might want a single instance of a database object. Singletons are the way you execute that.
I've heard a lot of whining about why singletons are bad. Now, let me couch this in the context of web and PHP coding. That's where I live. I don't know how you'd implement a singleton in C, and I don't like C++. So we'll have to confine ourselves to PHP.
Now, let me also make the point that the programming field is full of fads. For example, Object Oriented Programming (OOP). This was supposed to lead to "write-once-use-everywhere" code. The savior of mankind. Um, not so much. And Model-View-Controller (MVC). Yeah, it's convenient. But I've seen implementations which are the worst kind of slavish adherence to "best practices". That's the stuff academics and readers of Datamation dream up to make your programming life more politically correct. Then there are the language fads, which result in things like Haskell. Of course, now I'll get flack from all the Haskell fanboys.
What are some of the complaints about singletons?
Singletons are just globals
And your point is? Globals are deemed universally bad. Apparently, a lot of people who are obnoxiously smart believe this. Fortunately, I tend not to listen to people who are too smart for their own good. Globals are fine in the proper context, and singletons are about the same thing. I've coded hundreds of thousands of lines of PHP, and globals are part of almost every controller I use. For a more widely known example, consider CodeIgniter, the MVC framework. They use globals extensively.
Singletons make code hard to follow
Again, how do you figure? Obviously, singletons are not what the majority of your class objects should be. You use them judiciously when a single object of a class is the only one you want hanging around. But having one or two "necessary" singletons does not make code hard to follow. I assume, of course, that you've studied the code you're modifying, and in that study you discovered which objects were singletons. With that in mind, it's not hard to follow code which contains them. Again, let me stress you don't use singletons randomly. That's just dumb. But where there is a logical need to ensure that a given object is only instantiated once, a singleton is the answer.
Singletons make it hard to test code
A singleton is part of the code you're testing. Testing involves simulating inputs and data stores. Thus you develop a testing harness which does this simulation. Who ever said that singletons must be part of that simulation? Your testing should test the code as though it were in use on a live system. That code will include the singleton, and it needs to be part of the code you test, not some faked up input. Yes, singletons have some peculiarities compared to regular class objects. But that doesn't mean they can't be tested alongside the rest of your code.
Singletons make code hard to maintain
This is pure wishful thinking. You don't go around hacking code, when you don't know the environment you're hacking in. If you just blaze on through, hacking left and right, without realizing that there's a singleton in that code, that's on you. Pay attention. Know the framework in which you're coding.
Singletons make code hard to secure
Maybe that's true in other languages, but not PHP. The scoping rules and general design of the language mean that if you insist, you can pretty much access every variable in every scope. PHP assumes some responsibility is being borne by the programmer. If you're not supposed to access the internals of a mortgage class, then don't do it. It's pretty simple. You only expose globals which are absolutely necessary for the current code. And during the design phase, you determine what variables need to be global and what variables should be passed in to constructors or functions. Do this right, and your worries about what code is accessing what resources should be minimized. If some idiot decides to hack your code later, and starts throwing globals and singletons all over the place, it's not your fault.
Rules to live by
- During design, be sparing in your designation of classes as singletons. Only do it where it makes sense.
- During design, take into account the consequences of making a class a singleton.
- Don't listen to people who whine about your code. Professors and geeks make up rules, and I sometimes wonder of these folks have actually written any code themselves.
- When hacking someone else's code, become familiar with the context of the code, the globals, initializers and such. By all means, be on the lookout for singletons, and keep them in mind as you code.
One other thing I'll say is this: When I do a project from scratch, I try to write a "developer's notes" document which explains the aspects of the project which might not seem obvious unless you do a deep dive into various parts of the code. In writing this document, I think back to projects where I've had to hack other people's code, or come back to old code I wrote years ago. Such projects usually provide me with surprises. If I'd had a design document for the software, a lot of those surprises would have been avoided. And because singletons can cause trouble if you're not aware you're using one, it's a good thing to include in your developer's notes.