I finally understand singletons. These have been bugging me for some time, not helped by quite a lot of misleading information going around. I’ve seen several explanations as to what they are and even one or two of why they are A Good Thing. Mostly I’ve been confused by these and just put the matter aside until a rainy day.
However, if you’ve got to implement IntelliSense, you can’t avoid understanding them. It turns out that there’s nothing very special about a singleton method – they just live in a special ‘look-aside’ list in an object. When an object oriented language looks up a method, it searches for the method in the object’s class. If it doesn’t find it, it looks in the object’s parent or ‘super class’. With Ruby, all that happens is that the object’s look-aside list is examined first before the hierarchy is searched. And that’s all there is to it. Sure, there’s syntactic sugar allowing you to define several methods at once. Also, internally, it’s not really implemented as a look-aside list, but in principle, singletons are simple.
The real confusion came from a drawing in Ruby’s object.c file which purports to show the relationship of Object, Module and Class together with their ‘meta-classes’. It was this meta-class business that threw a spanner in the works. To me, a meta-class is something that describes or defines a class. A Ruby meta-class is nothing of the sort – it’s a lightweight class which works as a method look-aside. Nothing more. The diagram is actually correct, but it’s trying to say something very simple in a very complicated way
Having figured out what singleton methods are, the next step is to work out what use they are. In most other languages, singletons aren’t explicitly generated by the language, but they are there. I’ve used them on occasion in both Visual Basic .Net and C#, typically where there’s only ever going to be one of the objects (for a class that implements a message queue, say).
But in Ruby, if you introduce a singleton method, you’ll probably find that you end up moving the special object behaviour to a more general class or the object’s class itself as you refactor and simplify your program (I find I do this almost automatically all the time in C# - Visual Studio’s refactoring tools are highly useful here).
Incidentally, if you don’t do this refining and simplification, you’ll find that the cost of maintaining your program will be a lot greater than if you did. I’ve spent some considerable time over the years trying to hammer this simple fact home to all the programmers that have worked for me: it’s not the cost of you (the programmer) writing the code that’s significant. The cost lies in all the following programmers who have to maintain your crappy code.
My bottom line is that singletons are simple but unless you have a good reason to use them, don’t.