In every software, there are some things that have to be unique. For example, a Rails app has only one logger. Also, applications must have configurations, like environment, various API keys and etc. Take the configuration example - we need only one configuration for a runtime of an application. If all of the configuration data is stored into a class, then the whole app will need to use an object of that class. Hence, we use singletons - classes that can only have one object instantiated from them.
Basically, singleton classes prevent instantiation of more than one object of that class. Some people say that singletons are bad, some don’t. But I am pretty sure there are fine use-cases that we need to be aware of.
There are couple of ways to implement this pattern in Ruby:
Ruby Singleton Module
Ruby’s Standard Library has a module that allows the creation of Singleton pattern. Using it is really easy.
Here, we create a Configuration class - a class that has a hash called ‘data’
that will contain all the configration data. We added the
add method that
accepts a key and a value pair as arguments. This method will add the key-value
pair to the data hash.
As you can see, instantiating a new object of this class is prohibited.
Accessing the singleton is done using the
instance class method.
Also, using the
add method is done by calling it on the
Instantiating a single object of a class
So, how can we reproduce the same class as a Singleton without mixing in the Singleton module?
So, where’s the magic? The
add methods look pretty
usual. We create a class variable
@@instance that is an object of the
Configuration class. The key thing here is that we ‘protect’ the
Configuration.new method by making it a private class method. Then,
Configuration.instance method will just return the
use case is very much the same.
Constants and global variables
The key feature of a Singleton, beside the only-one-available-object is that the Singleton has to be globally acessible. That’s why constants and global variables can play well here.
One problem that global variables have is that it can get changed in runtime, without you noticing.
Singleton pattern can also be implemented by using class methods and variables. By using class methods we have are sure that we will have a single instance of the class.
Using it is, again, simple:
Simillar to the class implementation, a module can be a Singleton. Also, by default, instantiating an object from a module is impossible, which is a nice thing when it comes to the Singleton pattern.
Using the module is the same as using the class:
The good, the bad and the Singleton Pattern
There is quite a debate going on the internet about the Singleton pattern. Some are in love with it, others consider it an anti-pattern and despise it. What’s very crucial that you must understand is that every pattern has it’s use cases. Yes, each and every one of them!
In my opinion, the problem with the Singleton pattern is that if you fall “in love” with it, you might overuse it and then the coupling and the global state might hunt you for years. On the other hand, the best examples where you should use Singletons that come to mind are application Configuration and Loggers. So, like I said, it has it’s use cases but you should really think hard about it before using it.
When and where have you used Singletons? Is it that bad, or is it much better? What’s your opinion on using the Singleton pattern?