The Singleton Pattern
Welcome to the second in a series of posts about anti-patterns in Ruby!
What is a singleton? A singleton is a single instance of a class, particularly a single instance of a class - to be a singleton, a class must have the property of only being able to be created once (note that a singleton could not be created yet, so a singleton doesn't have the property of necessarily existing).
Why use a Singleton pattern?
* You have a single resource that you need to model - for instance, a log file.
* You need quick access to a particular resource throughout your system and don't want to have to remake it every time.
* Having more than one of a resource might be dangerous in your system - for example, if you're designing hardware related to a physical system, it may cause serious problems if you have multiple instances of an object floating around and different parts of the software are making calculations from different representations of a real-world machine part.
* ...other reasons that you need only a single instance of a class.
But you better have a darn good reason if you're going down this path because singletons are generally considered an anti-pattern and they give off a bad code smell.
Singletons make code less flexible, which in and of itself is enough to generally avoid them - code needs to be flexible because, in addition to the seeming inexterminability of some bug somewhere, the computer ecosystem that any particular piece of code exists in almost always changes. Operating systems change, hardware changes, databases change, user needs change, everything about the web changes...and if you want your code to continue to be useful, you should expect that you need to change it too, especially in ways that you don't think you'll need to.
Sure, there's plenty of COBOL and the like running deep within the electronic hearts of our most important institutions, but even those old COBOL programs sometimes have to be picked up, dusted off, and given a big spray from a can of Raid - remember the Y2K bug? You might not be able to think of a reason you need more than one instance of your class now, but that could change.
But there are other reasons singletons can be bad:
* Singletons can be hard to test, since it can be a pain to get them into the state you need them to be for your test - since a singleton can be accessed from anywhere and it's the only one, it could be altered by some other area of your code. Singletons keep their state as long as your program is running, so the order of testing can make a difference as to what state a singleton is in.
* Singletons are often put into code as a way to avoid having to pass information around; though having a single reference can be easier, it's also more dangerous for the same reasons as above: the singleton's state could, unbeknownst to you, unintentionally be impacted by other areas of your code when you need to reference it.
* Singletons with dependencies on each other can cause tricky situations if you need to remove one of them from your code.
You may notice that these sound a lot like the problems with global variables. They are. In fact, a lot of folks basically equate singletons with global variables or global state. This isn't a totally fair comparison - singletons can have additional logic and other capabilities that global variables don't have. But there's enough similarity there to make you squint. And, like global variables, when you're tempted to use a singleton, you should take pause before doing anything rash.
Okay, enough scare talk. We want to make a singleton. How do you do that? In Ruby, it's pretty simple: use the Singleton module. Ruby comes pre-loaded with the ability to make singletons! How easy!
That's all you need to do. If you try to create an instance of FirstSingleton,
you get an error message:
that's no problem:
If you try to create more than one instance, you still only get one:
Comments
Post a Comment