views:

85

answers:

5

Hi, I have been reading a bit lately about the singleton pattern. When readin the technical aspects of it, it appears to be ideally suited to managing a database handler or the likes. But after reading wider resources it appears that the developer community really does not favour the pattern.

I am struggling to find a better solution to such a problem - i.e. only a single handler can be initialised at a time - so why is the pattern so bad? Is it overused or is it just fundamentally flawed?

Php is the language that I am using.

+1  A: 

Some people follow this mantra that Singletons are evil because they are like global variables and make your code more hard-coupled and harder to test.

I for one don't think it's such a bad idea, and I think a Singleton works pretty well for a database handler. It's easy, intuitive, and you have more control over a Singleton instance than you would a global variable.

quantumSoup
+6  A: 

Singletons are glorified global variables. The design pattern was created for languages in which global variables are difficult or impossible, or where they are considered bad practice. (In fact, most of the common design patterns are designed for restrictive languages. A great number of them are simply unnecessary in other languages.)

PHP has global variables. PHP global variables are usually a bad practice, but they do exist if you need to use them.

However, there are a few reasons you'd want a Singleton in PHP.

Singletons are useful when the call to getInstance (the canonical name for the method that returns the single instance of the Singleton) might me made at any point in the script. Up until that point, the object doesn't need to exist. If the object was a global variable instead, either it would have to already exist, or the code trying to reference the object would first need to instantiate it. In fact, anywhere that it could be used, it would need to be instantiated correctly. By centralizing the creation of the single object in getInstance, you avoid having to create copy-and-paste boilerplate every time you need to reference the object.

Database objects usually get created very early on in the request lifetime, so that specific benefit of Singleton-ness would be wasted.

There are other alternatives to Singleton that can get the job done in other ways. One example is dependency injection, a fancy term for passing external objects that a new object would depend on (such as a database handle) to the object at construction time. However, this can be complicated or annoying. Doing it right might involve injecting a lot of the same objects every single time.

Another alternative is the Registry pattern, which is effectively a container for things that would otherwise be globals. If you don't like global variables, but don't mind them being effectively namespaced, this would be a solution that you'd like.

In the end, pick one way to do it, and stick with that one way throughout your codebase. Personally, I'm a fan of the database object being a global.

Charles
If you use some cache, it can happen that the database connection is not needed. Also, as the singleton is used on a class, it's possible to use the autoload. I don't believe Singleton are bad for database handling in PHP.
Savageman
Very true. If you have a comprehensive caching layer between your code and your database, it's very possible that you might never even need to open a connection at least some of the time.
Charles
The point about testing is very valid. The main issue with singleton is that it not only restricts you to a single instance (how about two separate db connections to separate dbs?) but also to to a specific implementation. If you want to test, you have to replace your db connection with something else. Abstraction becomes harder because it's not possible to extend your singleton. Registry addresses many of these issues.
igorw
ok, so what are the alternatives
Bill
Registry is a very worthwhile alternative, especially given the comments about testing.
Charles
A: 

There's nothing wrong with the Singleton pattern, I use it all the time.

As you say, it is ideal for resources you should only have one instance of and that are global to the application.

I think some developers don't like it due to dependencies that can be created through this method. Read up on Dependency Injection as I think it covers why Singletons are bad, but I can't remember exactly.

Stephen Melrose
A: 

I use a singleton database handler for most of my smaller web apps. When coupled with an external configuration file and PDO as the method of database access, it can still be very flexible moving from project to project, so long as the methods are not application model specific (ie, getRow or getAll instead of getThing or getBreakfast). I just try and make sure that all my access constants are defined separately.

A lot of the chagrin for singletons is derived mainly from languages more complex than PHP.

DeaconDesperado
im interested in how you link this with a config file
Bill
@Bill - Most of the applications I design gravitate towards the Front Controller pattern http://www.oreillynet.com/pub/a/php/2004/07/08/front_controller.html - So basically I can include a config.php file that has numerous define statements to make constants out of database access creds as soon as the front controller loads. Then all the models (the database handler itself as well) are included, so anywhere in the app I can perform my database queries by using that handler, as all parts of the app descend from that one point of entry.
DeaconDesperado
A: 

Apart from the global variable thing the community dislikes Singletons because eventually there's a chance you'll need an extra instance of the class. For example you may use a Singleton for your database connection and it works great up until the moment when you want to connect to 2 databases as once. At that point you either refactor your entire app or you copy-paste the singleton to a new class and use that. Either way you're up a certain creek without a paddle.

However the Singleton pattern is a design pattern, not an implementation. Nobody said that the code that restricts you to one instance has to be within the class. I have found that if you instantiate the class via a factory method you can put the singleton implementation in the factory method. Then if one day you need a new instance you can add a new factory method to do just that since the class itself doesn't have any restrictions. The price for this of course is that you always instantiate your singleton via a factory and not directly.

Manos Dilaverakis