php[architect] logo

Want to check out an issue? Sign up to receive a special offer.

Static methods vs singletons: choose neither

Posted by on March 3, 2010

StopwatchA post by Doru Moisa, Static call versus Singleton call in PHP, compares the performance of a singleton class with that of a static method. This is relevant, of course, because popular PHP frameworks such as symfony and Zend Framework make use of the singleton design pattern for their factory registry. What’s the verdict?

As you see, for a relatively small number of runs (<1k), the Static code is significantly faster than the Singleton, and it stabilizes at around 15% faster than the Singleton as the number of iterations grows, as I expected.

But look closer. The difference between the two methods equates to about 2.5 milliseconds per 100 calls. In the world of PHP frameworks, this is a miniscule price to pay for the added flexibility of a singleton (which, however, suffers from a number of drawbacks that I discuss below).

In the real world, not something to worry about

To put this in more concrete terms, I ran a large symfony application through Xdebug’s profiler. Symfony’s main singleton, sfContext, was retrieved a total of only 35 times. For a large project on a full-stack framework, the singleton’s cost is extremely low. The point? Focus on the important areas of optimization and don’t sweat the small stuff.

Much more important than performance is the fact that both static methods and singletons suffer from major drawbacks. When it comes to deciding between the two, you might forgo the benchmark comparison and choose the third-party candidate: dependency injection.

The dark side of static methods

Static methods can quickly lead to inflexibility and other problems. Specifically, static methods are very difficult to override and therefore nearly impossible to test. Sebastian Bergmann addresses this very issue in a recent blog post: Stubbing and Mocking Static Methods. The quote from Misko Hevery is particularly meaningful:

Yes, static methods are easy to call, but if the static method calls another static method there is no way to override the called method dependency.

The dark side of singletons

The slight performance loss when using singletons versus static methods is NOT their biggest problem. Singletons themselves always work through a static method. This means that, once again, they’re difficult to test. Sebastian tackles this topic as well in a comment to Derick Rethans’s blog post in which he references the potential answer to both static methods and singletons: dependency injection.

Why we use static methods and singletons

Two words: global scope. Static methods and singletons give us a way to reference variables (e.g. factories) that have not been passed to the current scope. Take this example from symfony, where I access the user factory from a class I’ve created:

class myClass
{
  public function __construct()
  {
  }

  public function doSomething()
  {
    $user = sfContext::getInstance(); // singleton accessor
    $user->doSomething();
  }
}

Dependency injection

The next generation of PHP frameworks will introduce a technique called dependency injection at their core. This removes the need for a “global scope” by passing any necessary dependencies through the constructor:

class myClass
{
  protected $user;

  public function __construct(sfUser $user)
  {
    $this->user = $user;
  }

  public function doSomething()
  {
    $this->user->doSomething();
  }
}

Instead of looking in the global scope for necessary resources, dependency injection encourages the practice of providing these resources directly. Without the need or a global scope, the need for singletons and static methods fades away.

Not performance, but smarter code

When deciding between using a static method or a singleton, performance should not be a consideration at all. Instead, take a moment to see if you can solve the problem in another way. Both static methods and singletons are frowned upon because they are difficult to test (amongst other things). If you are forced to use a singleton or a static method, choose what works best for you. Unless your application is doing some very serious lifting, performance should not be a concern.


Ryan Weaver is lead programmer at iostudio in Nashville TN and an avid supporter of the Symfony framework and open source in general. He's passionate about readable code, unit testing and collaboration (don't reinvent the wheel). If you've written open source code, Ryan probably loves you, but hates your documentation.
Tags: , ,
 

Responses and Pingbacks

Great blog post! I would like to see dependency injection to become much more popular in the php world. Its so simple and powerful, for me it’s an essential part of developing object oriented software.

Sadly too many (blogging) developers care about such small performance differences, which are as you said not really relevant in the real world.

@Georg

Thanks! The problem is that graphs and percentages are easy to digest, but their context is not. A 50% increase in one area may mean less of a boost than a 1% increase in another, much heavier area.

Plus, it’s just plain difficult to give out benchmarks (even if you know they are a small piece of the bigger picture), without them being taken out of context. We love numbers – maybe too much 🙂

Richard Quadling on
March 4th, 2010 at 4:34 am

Hi.

Interesting article.

If you have a shared resource being injected into many objects (a registry for example), you may need to perform “dependency removal” so that the shared resource can be closed cleanly. I prefer a FILO approach (First In, Last Out). By destroying objects in userland (rather than allowing automatic cleanup to occur), you control what happens at the tail end of your code.

So, I would guess the code should look more like …

class myClass
{
protected $user;

public function __construct(sfUser $user)
{
$this->user = $user;
}

public function __destruct()
{
$this->user = Null;
}

public function doSomething()
{
$this->user->doSomething();
}
}

The order in which objects are freed is not made clear

Nothing new here but it’s always good to remind best practices.
By the way, no need to wait for 2.0 frameworks to use massively dependency injection! We can use a DIC right now thanks to Symfony Components.

Little error in the symfony example:
$user = sfContext::getInstance();
it should be
$user = sfContext::getInstance()->getUser();

What about loggers?

One of the prototypical cases for the Singelton pattern is for working with pieces of code that need to be available in almost all contexts. Logging engines are a great example. From anywhere within any part of my application, I ought to be able to send a message to the logger.

So let’s assume we need to build a logging system that takes messages and can determine (based on whatever factors) where to log the message. The suggestion above is that Singletons and static methods should be abandoned in favor of dependency injection (DI)

But here the DI method gets cumbersome. It is unrealistic to require every class in an entire application to have a facility for injecting a logger class. There are two reasons for this:

1. It makes for an awfully cluttered API. Either every class gets a logger, or every class has to expose a method to access something else that can do the logging.
2. It means that much work is done at the integration layer to get third party libraries integrated with the logging system.
3. In turn, this means that the call stack gets deeper and deeper, as more and more methods need to be put into place to accomodate the logging needs (and deeper callstacks are definitely costly in PHP).

Bottom line: Yes, “singleton mania” is bad (and if you want an example of how static methods can be absolutely horrible from an API standpoint, look at Drupal’s JavaScript controller). But judicious use of Singletons can solve certain problems very elegantly.

Richard’s post raises some questions I have about PHP’s garbage collection. If the sfUser is a simple object, i.e. is not holding any resources, shouldn’t the reference count on it decrement when myClass is destructed without setting it to null. With PHP’s copy-on-write shouldn’t the null assignment effectively be a NOP?

If the user object does have some associated resources, does the attempt to close them here represent a “contract violation”? The resources really belong to the scope that created them, not myClass so they should be destroyed in that scope. If, for example, two objects where constructed with $user, one of them would lose the ability to use those references after the other one closed them.

@Matt you use aop for loggers.. cross cutting concern.

@author I suggest you still look at the spring implementation of DI. The use of singletons are used within their implementation although it is hidden from end users. The applicationContext initializes beans as singletons that are injected. Would like to hear how you’re implementation will be different.

[…] versus static methods debate that seems to com up every once and a while with a better suggestion – dependency injection. Much more important than performance is the fact that both static methods and singletons suffer […]

I guess maybe this is the kind of thing that passes for “best practice” in PHP, but there are a whole host of concepts that apparently no one developing in PHP (or at least writing about developing in PHP) are aware of.

First, let’s be perfectly clear: there is nothing inherently wrong with static methods. Nor, in fact, is there anything inherently wrong with singletons.

The real problems are (mutable) global state and referential transparency. Things that rely on global state are mainly only problematic when that state is mutable. And DI doesn’t solve the problem of referential transparency at all, it just treats the symptoms, making it easier to live with.

Instead of spouting off about high-level design patterns, it’s better to learn about the underlying programming concepts that those patterns try to implement or solve. Then you can actually have a productive discussion.

Regarding the benchmarking: I smell… premature optimization.

While both singletons and static method calls are best avoided (generally speaking) I dislike static calls much more than singletons: A singleton has a getInstance() method of which a setInstance() counterpart can exist. Thereby it is possible to alter the getInstance behaviour to return an object of a different type (Ok, so it’s not a singleton anymore but then again, it shouldn’t have been in the first place). And if the application code doesn’t only accept instances of the singleton class but accepts an interface one doesn’t neccessarily have to resort to subclasses of the singleton class for the returned object…

Thanks for the comments – there are some really in-depth views here that add a lot of value. Let me address a few:

@Matt Butcher (on a logger)
Definitely a valid point, and a difficult one to solve. Certainly you don’t want to pass a dependency like a logger to everything in your application. That being said, you’ll also want to avoid hardcoding your logger while not overly-depending on the global state (because I like being able to use my classes independent of everything else). Most any solution here requires some sort of globally-available context.

@cease (on checking on DI in the spring framework)
I agree that singletons will still exist and should in some cases. After all, we ARE responding to one request: there’s something inherently “single” about that. In symfony 2, the service container, while not technically a singleton, is constructed just once and then is available where needed. The spring framework is precisely the model that most new php paradigms are following. In other words, my implementation probably wouldn’t be any different – spring is the model case. There’s some conversation about this very topic (specifically in the comments) here: http://fabien.potencier.org/article/14/symfony-service-container-using-a-builder-to-create-services

@Nate Abele (on nothing inherently bad with static methods, singletons, mutable global states, and referential transparency)
No, there’s nothing inherently wrong with them – you just have to realize what you aim to lose by using them. Namely, your class will have some sort of hardcoded dependency and may be difficult to use in isolation (e.g. testing) because the class looks for some global condition that may not be available. If you’re cool with that (and in a lot of cases you may be) then they’re fine.

Regarding the true problem being with mutable global states, that certainly makes sense. Since immutable globals are essentially constants, if a global constant is really what you’re after, then that’s fine. As an extreme, I certainly won’t stop using real constants (myClass::SOME_VALUE) any time soon.

On the referential transparency front – you’re right again. Hopefully with DI, at the very least, you’ll be less surprised when something proves opaque since scope is clearer. That being said, if your nesting level is deep (the objects in your scope have many objects in their scope), then you may still lose sight of the full “scope” of your actions.

Thanks for the comments!

Ryan, I have a question about something you said: “the service container, while not technically a singleton, is constructed just once and then is available where needed”. My understanding of what a Singleton is has always been that is constructed just once and then is available where needed. It appears that you are saying that is *not* the definition, based on your statement about the service container. Can you elaborate for me?

I’m all for using the right tool for the right job, but maybe I could be doing something ‘better’.

My main singleton class holds multiple instances of the PDO object (for multiple databases) – the idea being that I have just one instance of each connection class.

When wring my data management objects, these objects require one or more of the db connections. Passing these connections in the cobstructor would require the object invoking the data management object to have an instance of the connection ready – so where would that instance come from?

As for static methods I jsut use this so non-object fucntions can be called using the __autoload() function – maybe this is wrong too, but it suits me very well 😉

@Doug Boude
Well, you bring up a fine point between injecting a dependency and retrieving a singleton statically. What you quoted me on is taken closely from a comment made by Fabien in the above-referenced blog post. My definition of a singleton would be something that is retrieved via a static getInstance() type of call. You may have some resources that are only actually created once, but then are passed into your scope. It’s a subtle difference and what you gain or lose from one approach to the other may be subtle as well.

Here’s how I test, I load the page in the browser and bam. It either works or it don’t. Guess what, PHP will also tell me the problem. If you want to develop desktop Apps then go into desktop world. Every page request should not have to go through an oop system. PHP is not an oop environment like desktop and does not benefit because all those fancy objects don’t stay in memory for the next request. While total oop does not make sense in PHP, it makes perfect sense in JavaScript because JavaScript objects stay in memory and are reused after the page is loaded.

Donovan Walker on
June 24th, 2010 at 10:50 pm

This is a wonderful post, but I’d say it goes a bit far in it’s almost universal condemnation of Static methods and singletons. Your comment about ‘global scope’ may infer a frequent abuse of those programming patterns, but with responsible, restrained use in the correct contexts they can be successful, even desirable aspects of a solution.

But how are you going to accomplish dependency injection?
You can either insert code at run-time or require the introduction of a pre-processor or “compilation” step. Are you going to use annotations or some sort of registry (like XML) of objects to watch for?

Injection before run-time requires a preprocessor that gives you different code than you wrote, can see, or edit. Makes debugging difficult. If you have a run-time preprocessor or watcher, then you introduce massive overhead and make debugging virtually impossible, and testing in isolation even worse.

This kind of movement really continues to move PHP away from its origins which i’m unsure if it is a good or bad thing but all patterns seem to lead so strongly to OO mimicking java to a T. I personally will never be a fan of pure OO for php becuase it was never designed for it. It still at its heart is a scripting language which allows you to cut some corners “pattern wise” to get a project finished quickly and effectivly (that is why there is 500+ native function calls in the core). I’m still not convinced by anyone that you can’t test static method properly either. If you have a library with one public static method to test that calls 3 private static methods internally, the results of your unit testing and all parts that you test should be testing how those privates interact with whatever it is you are testing against (a DB usually). And now, i shall go off to write my new book “Alone in my Principals” 😛

Smarter code also means to know what should be testeable, really if for some uncanny reason, you must test a singleton, then why not test it first when is fresh? Im talking only about the problem Sebastian Bergman have with singleton and why he escuses himself to use DI (hope this didnt sound hardcore). Also Sebastian give you two alternatives, and the refresh() approach can be the way to go!. Dont want refresh() to be used outside testing? Just use a _IAMTESTING constant, and do somethig like this
class singleton{
…. //yadda yadda
refresh(){
if(_IMATESTING){
$this->self::$uniqueInstance = NULL;
}
else{
echo “Cant touch this”; //Who oh oh oh oh!
}
}//End of refresh
}//End of class

It’s that really too hard!?

But I don’t wanna pass configuration objects every time I instantiate a object.

[…] static methods vs singletons […]

Rather than having a large number of factory classes (one class per factory), Misko Havery talks about grouping them together using “scopes” at application, session, request and transaction level.

Can anyone explain how to do this in a “clean” way (possibly without statics), as I’m not sure what a scope is?

As far as I can tell, it’s an encapsulation at a outer level of the app that contains objects that are injected into scopes and objects at an inner level.

[…] Static methods vs singletons choose neither […]

Leave a comment

Use the form below to leave a comment: