t has become fashionable to condemn the singleton pattern. Apart from specific complaints, it is said to be not OO. Now what I’m going to provide is not a general response to general remarks, it is a PHP specific response to attacks on singleton. It’s based on my own actual development experience.
To get some context, I’ve picked on a set of objections from Steve Yegge’s blog. He seems to be talking primarily about Java and C++, and maybe his comments apply with greater force in that context. They’re very different languages from PHP. Anyway, I’ll take his summary set of points and reply to them.
a) I haven’t covered even a tenth of the issues. But I’ll name a few of them.
Well, I can only respond to the ones he has mentioned!
b) One is memory management; a Singleton is basically just a memory leak, if nobody is going to be using it for a while. But you have no idea when to deallocate it, because nobody’s going to call you and say “nobody’s going to be using you for a while!”
Besides, you can’t tell who has kept around references to your Singleton instance, since you were pretty blase about handing it out, weren’t you? (Note: Java’s weak references can help with this issue).
A PHP application is normally running as part of a web server. It handles a request and then terminates. Ideally, it does this in less than a second. The singletons that I write are often there to handle pools of useful data, so it is not desirable for them to be deallocated mid stream.
Within reason, memory is not an issue for web applications. It is much better to use up half a megabyte of data space than to keep making SQL requests on a database. I monitor memory usage on my web sites very carefully, and it is actually kept under very tight control in my Aliro CMS framework, which uses singletons to manage a variety of objects.
c) Speaking of memory leaks, what if your Singleton has a handle to some limited resource, like a database or file handle? I guess you get to keep that sucker open until your program ends. Thank God C++ programs never last longer than about 10 minutes before crashing, usually from running out of resources, or from trying to access a Singleton that someone freed.
Well, actually, no. Suppose we address the specific items mentioned by Steve. In PHP applications, it is generally thought better not to use persistent database connections. So the connection lasts only for the duration of a request. (For various technical reasons, persistent connections are liable to hang around and multiply uselessly, creating far more problems than they solve). And the kind of file operations that my singletons do are to read the entire contents of a cache file, which is then automatically closed.
d) Another issue is that the Singleton design is syntactically noisy; most languages don’t support it (well, Ruby does, sadly, but that was probably before Matz knew any better), so you have to stick in boilerplate code not only in the Singleton, but in everyone who uses it.
There’s no real argument here, only a difference of taste. Personally, I don’t regard the time spent writing out the names of things a major factor in software development productivity. It isn’t too hard to learn to type at 40 word per minute, and that means maybe 200 lines of code an hour or more. I freely admit that I don’t create 200 lines of working code per hour. Time spent typing isn’t the issue. So I don’t mind writing long names if they make things clearer.
In PHP 5 (who cares about 4 now?) you can call a method on a singleton by writing:
mySingleton::getInstance()->myMethod($parameters);
It doesn’t bother me having to write getInstance quite often. I could call the method something shorter like GI, but that would obscure the meaning, so I don’t do that. If I’m going to use the singleton a lot, then of course I assign it to a variable, and write:
$mySingleton = mySIngleton::getInstance();
$mySingleton->myMethod($parameters);
And in the class itself, the getInstance method is a single line (it’s on two lines here because of layout constraints) that is invariant in every singleton class:
public static function getInstance () {
return is_object(self::$instance) ?
self::$instance : (self::$instance = new self());
}
It doesn’t trouble me that I have to put that code into each simple singleton, because there is a big payoff in efficiency through the pooling and cacheing of data.
e) Then there’s the subclassing thing. It’s almost impossible to subclass a Singleton, and if you manage it, then you shouldn’t have been using a Singleton in the first place. You don’t even want to go there. I’ve walked roads that I dare not recount. Just pretend you can’t do it, and you’ll save yourself amazing amounts of pain.
Now this is just plain wrong. It might be true in some languages, I cannot say. But it is emphatically not true in PHP as is clearly demonstrated by some of the code in Aliro. Many of the singletons used in Aliro are subclasses of a class called cachedSingleton. This subclassing provides an automatic mechanism whereby the data that is set up in the singleton’s constructor is automatically cached without any code being required in the singleton.
Because of this, it makes good sense to carry out expensive database operations and to manipulate the data retrieved from the database in the constructor. This work is only done from time to time, when the cache expires. The rest of the time, the singleton has very simple, efficient methods that work on well structured data from cache.
And that is not the end of it. Aliro has a handler class for each type of add on that can be installed into the base CMS. All those handler classes have things in commmon, so they are subclasses of aliroCommonExtHandler. And, would you believe it? The class aliroCommonExtHandler is a subclass of cachedSingleton.
Isn’t that proof enough that singletons CAN be subclassed very successfully?
f) static methods are as flexible as granite. Every time you use one, you’re casting part of your program in concrete. Just make sure you don’t have your foot jammed in there as you’re watching it harden. Someday you will be amazed that, by gosh, you really DO need another implementation of that dang PrintSpooler class, and it should have been an interface, a factory, and a set of implementation classes. D’oh!
Well, I’m not on the same wavelength as Steve here, I don’t really know what he is saying. The nearest thing in PHP to a class method (as opposed to an object method) is a static method. There are specific cases where a class method is the ideal solution to an object design problem. I’ve written elsewhere about why too general use of static methods is bad, but they do have a place.
The obvious alternative to consider instead of singleton classes would be class methods. Suppose we think about menu entries. Each menu entry might be an object of a menu class (possibly a framework of classes). We could then suppose that methods that manipulate or cache numbers of menu objects would be class methods. But in PHP those would have to be static methods.
Quite apart from the vague but fearsome drawbacks cited by Steve, PHP static methods are extremely inflexible when it comes to inheritance. It is very difficult to build a framework of classes that use a limited number of static methods for generic operations, alongside ordinary object methods for individual object behaviors.
Don’t suppose that’s all. There are many other problems. For instance, try adding multithreading in and see what happens. Well, I’ll tell you what happens: half the time, you get a Doubleton or a Tripleton, unless you’re a synchronization expert, and having a Tripleton is about as desirable as having three Balrogs show up at your tea party. And even if you’re a synchronization expert and get the double-check idiom right, you’ve still got one Balrog to deal with, and they’re no picnic.
Yes, I’ve written multithreaded code in online systems. But this just isn’t relevant to PHP where the code processes a single request to completion.
But these problems all fade into insignificance compared to the Big One, which is that the Singleton “pattern” encourages you to forget everything you know about OO design, since OO is hard, and procedural is easy.
This sounds quasi religious to me, and I try to avoid religious wars! Nobody should use a singleton unless it is justified by OO design considerations. In the code I write, there are certainly situations where that seems to me exactly the situation. An object ought to represent some identifiable entity in the problem we are trying to solve. As we get into the details of how a system such as a content management system will work, we will find ourselves talking about entities that are pretty abstract and technical.
In those areas, it seems to me perfectly natural that we should envisage, say, an object that knows about all the plugins (added pieces of code that can be dynamically triggered) that have been installed into a particular CMS, and knows how to trigger the correct set of plugins for any particular trigger. And other such things.
We will also have a set of objects that represent the plugins. It might be that in an ideal world, we would treat the class of plugins as the correct location for knowledge and behaviors that relate to many plugins. But in PHP as it currently exists, that cannot be done in an elegant way. Whereas, contrary to Steve’s claims, a framework of singleton classes most certainly can be built. The result can be both efficient and elegant.