Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Why is singleton so bad in a PHP environment? [duplicate]

Possible Duplicate:
Who needs singletons?

i was wondering, what are the drawbacks using Singletons in php scripts. I use them alot and i sometimes can't understand criticism of developers. Some examples:

I have a Request class:

Sanitizing POST, GET, COOKIE inputdata and using it instead of the global arrays - strictly and globally. Like

$request = Request::getInstance();
$firstname = $request->post('firstname', $additionalFilters);

There is always only ONE request per request. Why is using singleton in this case a bad idea?

Same for $_SESSION:

I have a Session class (Singleton) which does represent the $_SESSION array because there is only one session and i use it globally.

Database

$mysql  = DB::getInstance('mysql', 'dbname'); //pseudo
$sqlite = DB::getInstance('sqlite', 'dbname'); //pseudo

For each type of database, i want only ONE object and never MORE. In my opinion there is otherwise a risk of chaos.

Unique rows

Also i often use classes to represent/use a unique row of a db table.

$article = Article::getInstance($id);
$navigation = Navigation::getInstance($id);

I see only benefits doing it this way. I never want a second object representing a unique row. Why is singleton such a bad idea here?

In fact, most (nearly all) my classes don't have a public constructor but always a static method like getInstance($id) or create() so the class itself handles the possible instances (which doesn't mean they are all singletons by definition)

So my question is: Are there any drawbacks i didn't realize yet. And which concrete scenario's the singleton-doubters thinking of when advise against Singletons.

Edit:

Now, you got a singleton that wraps around the $_POST, but what if you don't have $_POST, but want to use a file for input instead? In that case, it would be more convenient if you have an abstract input class, and instantiate a POSTInput to manage input through posted data.

Ok, valid advantages. I didn't realized that. Especially the point regarding the Request class.

Still i have doubts whether that approach. Assume i have a "Functionality" class which executes a concrete request (like a guestbook component). Within that class i want to get a sent parameter. So i get my singleton instance of Request

$req = Request::getInstance(); 
$message = $req->post('message');

This way, only my functionality object cares about a Request class.

When i use the non-singleton approach, i need somehow an additional class/function to manage that every request gets a valid request object. That way my Functionality class doesn't need to know about that managing class but in my opinion there still arises a dependence/problem: Everytime i create an instace of an Functionality object there is a chance that i forget to set a request object.

Surely i can define a non-optional parameter when creating a functionality. But that leads to a parameter overkill altogether at some time. Or not?

like image 290
player-one Avatar asked Aug 01 '11 16:08

player-one


People also ask

Why is Singleton considered bad?

The most important drawback of the singleton pattern is sacrificing transparency for convenience. Consider the earlier example. Over time, you lose track of the objects that access the user object and, more importantly, the objects that modify its properties.

What is common criticism of Singleton design pattern?

Criticism. Critics consider the singleton to be an anti-pattern that introduces global state into an application, often unnecessarily. This introduces a potential dependency on the singleton in all code it is visible to, requiring analysis of implementation details to determine if a dependency actually exists.

What are the consequences of applying the Singleton pattern?

Some consequences of the Singleton pattern include controlling access, permitting subclassing, and enhancing flexibility.

Should you use Singleton?

Use the Singleton pattern when a class in your program should have just a single instance available to all clients; for example, a single database object shared by different parts of the program. The Singleton pattern disables all other means of creating objects of a class except for the special creation method.


2 Answers

Singletons (and static classes, to which the same story largely applies) are not bad per se, but they introduce dependencies that you may not want.

Now, you got a singleton that wraps around the $_POST, but what if you don't have $_POST, but want to use a file for input instead? In that case, it would be more convenient if you have an abstract input class, and instantiate a POSTInput to manage input through posted data.

If you want to get input from a file, or even (for whatever reason) want to mimic (or replay) multiple requests based on input from a database table, you can still do this, without altering any code, except the part that instantiates the class.

Same applies to other classes too. You don't want your whole application to talk to this MySQL singleton.. What if you need to connect to two MySQL databases? What if you need to switch to WhatEverSQL?.. Make abstracts for these kinds of classes, and override them to implement specific technologies.

like image 194
GolezTrol Avatar answered Oct 14 '22 14:10

GolezTrol


I do not think singletons should have as bad press they do in a request-based architecture such as PHP or ASP.NET (or whatever you want). Essentially, in a regular program the life-time of that singleton can be as many months or years as the program is running:

int main()
{
    while(dont_exit)
    {
        // do stuff
        Singleton& mySingleton = Singleton::getInstance();
        // use it
    }

    return 0;
}

Apart from being little more than a global variable, it is very hard to replace that singleton with, perhaps, a singleton that might be useful in unit-testing. The amount of code that could depend on it, in potentially hundreds of source files tightly couples the use of that singleton to the entire program.

That said, in the case of request-based scenarios such as your PHP page, or an ASP.NET page, all your callable code is effectively wrapped in a function call anyway. Again, they are obfuscating a global variable (but within the context of the request) with safe-guards against being created more than once.

But still, I advocate against their use. Why? Because even in the context of your single request, everything is reliant and tightly coupled to that instance. What happens when you want to test a different scenario with a different request object? Assuming you coded using includes, you now have to go and modify every single instance of that call. If you had passed a reference to a pre-constructed Request class, you can now do cool stuff, such as provide mock unit-testing version of your class, by simply changing what gets passed down to the other functions. You've also de-coupled everything from using this universal Request object.

like image 31
Moo-Juice Avatar answered Oct 14 '22 13:10

Moo-Juice