views:

61

answers:

3

I had not done with any OO in the past in projects, as I kept it simpler (in fact using archaic mysql_query calls and my own filtering) so I wanted to start a new project, learning to use design patterns with my OO along the way.

I was looking to build a microblogging site for kicks, and found the Singleton design pattern class which seemed complete, and to use with PDO I could not see anything wrong with it (other than not being able to access two databases, which I am not sure I would need for this project).

On say a project like this, or a simple CMS software, would a Singleton be a good idea? What sorts of design patterns/database class type would "the big guys" be using for these things, would this be too restrictive later on if it were to be upscaled (concurrant connections/performance)?

I had also read about a factory Singleton to deal with dealing with extra connections later on as it is simpler to change the code in it, would this fix any of the negative issues and make it a more suitable design pattern for this?

+1  A: 

If I am not mistaken Singleton is antipattern. But depending on the task it can be used.

Evgeniy
+1 for AntiPattern
Gordon
That's pretty controversial. It's overused, and comes with significant caveats, but it fulfils a distinct function and I have a hard time saying it's always wrong.
annakata
It's not always wrong. When having more than one of something will cause things to blow up, Singleton is a good way to prevent disaster. But it's wrong in most cases, and it's too often misused/abused. It should never have been added to a list of common solutions to common problems (which, when you break it down, is what patterns were meant to be). Most people should almost never be using Singleton, and probably wouldn't if it weren't blessed by the GoF.
cHao
+1  A: 

The Singleton's purpose is to limit object instances to one and to provide global access.
Both are things you dont want or need.

Limiting your instance to one instance is rather pointless in PHP where this restriction only applies to the instances in the current request. If two requests hit your microblogging site at the same time, there will still be one instance each per request. If you want to make sure there is only instance, simply do not instantiate a second instance.

Global access is nothing you want either, because it breaks encapsulation. If you need a certain instance inside your objects, pass it in via Dependency Injection. That's clean and maintainable. It has the added benefit of allowing you to easily exchange dependencies with other implementations, like for instance Mock classes for your UnitTests.

Even Erich Gamma, one of the Singleton pattern's inventors, doubts this pattern nowadays:

"I'm in favor of dropping Singleton. Its use is almost always a design smell"

You are best off avoiding Singletons.

Gordon
A: 

As said before, the singleton doesn't help you with your blog application much. Just create a single database instance and use it.

Sidenode, what you see in PHP are often "fake singletons". If implemented as plain class, it usually involves using a ::getInstance() method which implements the singleton workaround. The existence of the class however allows to instantiate multiple items (new Singleton() && new Singleton()). Therefore I'd recommend a procedural singleton, which doesn't have this problem and is also much nicer on the eyes:

 function db() {
     static $db;
     if (!isset($db)) {
          $db = new PDO("sqlite:memory");
     }
     return $db;
 }

This way you can use db()->query("SELECT * FROM blog") and avoid to always import a global $db var.

mario
Functions are defined in the global scope, so using this within a class has the same coupling and encapsulation problem as `global $db;` or `DB::getInstance();`
Gordon
Also, since `db()` returns a PDO object, I can simply clone it to get multiple instances. Try `var_dump(db(), clone(db()));`
Gordon
Same as all objects in PHP. The OOP semantics don't allow for real singletons.
mario
Not true. You can do `private function __clone() {}` and `private function __construct()` to prevent multiple instantiation and cloning. [See the Singleton example in the PHP Manual](http://www.php.net/manual/en/language.oop5.patterns.php#language.oop5.patterns.singleton)
Gordon
Prevention ok. Though it would be a more proper singleton if __clone could just return $this. Or if there was a way to have `new Singleton() == new Singleton()` without helper methods and workarounds.
mario
No, *new* implies new instance and *clone* implies cloned instance. Even if you could (you cannot) make those return the same instance it would be semantically incorrect. It's not meeting expectations. The GoF book uses a static method to create and handle the instance, so the example given in the PHP manual is "proper".
Gordon
The GoF bible definition is not meeting my expectations then. If a singleton is supposed to only exist once, then I shouldn't be bothered to syntactically take care of that. Let's call helper method singletons for what they are: helper method singletons. ;}
mario
Actually, my personal favorite would be if PHP would automatically detect any Singleton patterns and throw a YagniException :D
Gordon
I'm not sure. There's the occasional use case. And if there was e.g. a language-builtin and -enforced SPL_Singleton base class, people could more easily add or remove it again. Or randomly disable it via php.ini, lol
mario