The Case for Singletons in WordPress

Please also review my follow-up post, Making Singletons Safe in PHP.

There has been a lot of discussion this week regarding the Singleton pattern and whether or not it has a place in modern software development.  Mike Schinkel wrote a tutorial about a Singleton factory.  I wrote one about using Singletons as a WordPress plugin scaffold.  Then the conversation bled over to Twitter and people questioned whether or not it was a sound development pattern at all.

I would argue that Singletons are not just useful, but are necessary for robust software development.

The Singleton Model

To understand why I claim Singletons are necessary, we first have to agree on a definition of “Singleton.”

A Singleton is a class for which there can exist one and only one instance during the life of the application.,

In practice 1 Singletons are used all over.  Think of every time you’ve used the global keyword when working in WordPress.  Not for Posts, which are atomic objects, but for framework-wide constructs like $wpdb and $wp_rewrite.

These objects don’t actually implement a Singleton design pattern, but for all intents and purposes they fit our definition.  These are objects that are (typically) only instantiated once during the lifetime of a WordPress request-response cycle.  You never call new wpdb() in your themes and plugins; instead you make a reference to the global $wpdb object that WordPress set up for you. 2

The Singleton model exists to protect you from memory bloat.  In most cases, you never want more than one connection to the database open at any given time – so there’s only one instance of the database object during the request.  It also protects you from instantiating multiple copies of objects that are expensive to construct – it makes no sense to have multiple instances of the WP_Rewrite class lying around.

Why All the Hate?

Still, Singletons are considered an “anti-pattern” by many developers.  They claim it’s an overused pattern that’s misused by too many developers.  True, it can be misused, but so can Axe body spray and words like YOLO.  Overuse doesn’t make them wrong per se, you just need to be very judicious in when, where, why, and how you use them.

In some applications, Singletons are a horrible idea.  They introduce the idea of a global state into the application – and that state can bleed across threads in multi-threaded, persistent applications.  This means one request can inadvertently affect another.  For stateless (REST) web services, this can lead to many a sleepless night.

As a result, most developers will see “Singleton” and immediately think “bad.”  They’ve been trained to avoid the pattern and will summarily reject it if you suggest using a Singleton.

When It Makes Sense

As I’ve already pointed out, WordPress already uses singly-instantiated objects that are placed in the global scope.  So apparently it makes sense to at least a handful of people.

I’ve also used a Singleton as the backbone for my WP_Session object.  It’s instantiated lazily (meaning only when you actually access it rather than when the class file is included by WordPress), and lives for the entire request.  This is an object I’ll used as a great example of why the Singleton pattern makes sense.

I work on WordPress, but I’m not the only developer.  My code touches a few aspects of the application, like the XML-RPC system, the WP_Http class, and certain other tiny elements.  But WordPress itself is a huge application, with hundreds of contributors and maintainers.  We have a few set of coding guidelines, but there’s no guarantee everyone will write their code exactly the same time.

So while I might only instantiate WP_Session once, there’s no guarantee other developers will respect that.  Not in core, and certainly not in plugins.  If the class could be instantiated multiple times, all it would take is one extra call to new WP_Session to muck things up.

Also, once I’ve instantiated the class, since it’s an object I intend for other developers to use, I have to place a reference to it in the global scope so their code can access the same instance.  So, ultimately, there are two patterns I can follow to set up a single instance of WP_Session for the request:

class WP_Session {
  // Pray that this is only ever called by me
  public function __construct() { }
}

// Heavily document that this var shouldn't be abused
global $wp_session;
$wp_session = new WP_Session();

Or using a Singleton – a static get_instance() method will return the current instance, and the private constructor cannot be called outside of the class.

class WP_Session {
  private static $instance;

  public static function get_instance() {
    if ( ! self::$instance ) {
      self::$instance = new self();
    }
    return self::$instance;
  }

  private function __construct() { }
}

$wp_session = WP_Session::get_instance();

What About Dependency Injection?

This is the single greatest argument against Singletons that I’ve heard.  On Twitter, over email, and even on Stack Overflow I’ve seen people arguing that dependency injection is a suitable replacement for the Singleton pattern.

They’re wrong.

Dependency injection is a pattern that encourages you to abstract your dependencies so you can substitute mock objects in your code.  Consider the following pseudo-code example:

class Logger {
  var $persist;

  function __construct() {
    $this->persist = new FileSystemWriter( 'log.txt' );
  }

  function write( $event ) {
    $this->persist->save( $event );
  }
}

$logger = new Logger();

This kind of code would run just fine.  However, you are stuck between a rock and a hard place should you need to change your code.  If you want to change your application to log in a database rather than to the filesystem, you need to rewrite both your business logic code and your data persistence layer.  Consider instead the following code:

class Logger {
  var $persist;

  function __construct( $engine ) {
    $this->persist = $engine;
  }

  function write( $event ) {
    $this->persist->save( $event );
  }
}

$fileEngine = new FileSystemWriter( 'log.txt' );
$logger = new Logger( $fileEngine );

Now, when you change your application, you just change the data persistence layer since you’re passing the persistence object directly to the logic layer.  Your code is highly decoupled and you can move forward with blissful flexibility.  Dependency injection is truly an amazing paradigm to work within, but it does not solve the problems solved by Singletons.

Unit Testing

The biggest argument against Singletons – and where the misguided rants about dependency injection come from – is rooted in unit testing.

When you’re unit testing an application, each test should be completely isolated from every other test.  Singletons make this difficult, since they introduce a global state for the application that must be managed in between each test.  When you’re working with other stateful objects in a testing environment (i.e. a database), you use dependency injection to introduce a mock object that implements a similar interface, but with stateless behavior.

Basically, the mock object allows you to start every test with a clean slate.

To unit test with Singletons, you have to do two things:

  1. Have the Singleton implement a standard interface that you can mock in your tests, then use dependency injection to inject the Singleton inside the application
  2. Implement a reset() method within your Singleton that flushes the stored class instance

The first step allows you to test your code that depends on the Singleton object without actually using the Singleton itself.

class User {
  var $session;

  function __construct( $session ) {
    $this->session = $session;
  }

  function save_meta( $key, $value ) {
    $session[$key] = $value;
  }
}

$user = new User( WP_Session::get_instance() );

The second step allows you to test the Singleton in isolation – just call Singleton::reset() at the beginning of your test to ensure you’re starting with a null state, then call it again at the end of the test to clean up after yourself.  It’s not the prettiest way to do things, but PHPUnit doesn’t currently have per-test setup/teardown functionality.

Conclusions

Singletons are one of the most misunderstood constructs in software development.  In most modern (read: multi-threaded) environments, their overuse has resulted in almost universal disgust for the pattern.  However, in single-threaded, multi-developer systems – like WordPress – they serve an important and necessary purpose.  Singletons allow you to maintain global, singly-instantiated objects in a particular request, keeping memory clean and optimizing your application through heavy operations (i.e. database or filesystem access).

Singletons can be tricky to use in a unit test environment, but it’s not impossible to test code that uses the pattern.  Don’t jump the gun and assume, just because hoards of developers on Stack Overflow dislike something, that it’s a bad thing.  Singletons have their place; you just need to learn how to use them properly.

Notes:

  1. By “practice” I mean in WordPress development in particular.  WordPress is written in PHP, and PHP is by nature runs as a single thread.  If you’re dealing with a more dynamic, multi-threaded environment, the practices will differ significantly.  I will rarely ever argue that a Singleton is the right use case in a multi-threaded .Net application, for example, but there are still situations where it’s a useful pattern.
  2. In reality, you can (and will) call new wpdb() if you are trying to connect to a new database. This is rare, though, and I was trying to find an example of a class most people use that already follows a Singleton pattern. In the majority of cases, you aren’t connecting to a new database, so the new keyword never appears in the context of the WP database object.

Comments

  1. says

    Singletons are a anti-pattern for a reason. Once you go down the road of making something a singleton, you’re screwed the moment you EVER find need of a second one. Sure you might only need one now, but down the road, who knows, and once your code is peppered with all those getInstance() calls, good luck digging that back out again. Singleton is the OO equivalent of a global variable, and to argue that it isn’t an anti-pattern is to argue that a global variable isn’t an anti-pattern, and I think most people can agree at this point that that case has been more than proven.

    • says

      Singleton is the OO equivalent of a global variable

      PHP applications like WordPress are written in a single-threaded, request-response pattern. Having a global scope is useful, and having instantiated singletons available in that scope is also useful. It’s rarely a pattern I will use; my argument isn’t that you should use singletons everywhere but that singletons do have a use.

    • says

      @orclev – WordPress is architected differently than MVC solutions and Singletons make sense in the context of WordPress. I have enough experience with WordPress that I can say so confidently but I can’t argue for Singletons in any other context simply because I lack experience in those contexts. So I expect you are correct in most contexts, just not in all.

      @eric Excellent post! I agree with everything you said plus your post is extremely well written. Kudos! And thanks for the reference to my post.

      I do have one nit to pick with you though; the pattern I’m using in my post you referenced is not a multiton and I can’t see how you could confuse the two. The code I shared in a Twitter DM with you from my company’s GitHub account (which I’m not ready to promote publicly before we finalize our interfaces) does appear to be like a multiton but upon closer examination its clear it is not a multiton.

      A multiton limits to one instances based on not only class but also properties of the class such as the example in the link post where the properties were IP address, username, password and port. For the example use-case those can be used together to create only one connection for unique sets of those properties, which makes sense in that context.

      Review None of my published use-cases to date have more than one instance per named class name, ignoring abstract base classes which don’t apply, of course. So since most people will read your posts and not all the comments it’s be really nice if you would update the post to remove the multiton reference, or at least help me understand how many I’m viewing it wrong? Thanks in advance.

      • says

        I referred to your implementation as a multiton because it fit the pattern:

        The multiton pattern expands on the singleton concept to manage a map of named instances as key-value pairs.

        Your factory class seemed similar enough to that concept to qualify since, really, it contains an array of singleton instances rather than a singleton instance. But since the reference is just one of the many things that could confuse people in this article I’ve removed it. We can discuss later, but on a quick glance (and I might have been confusing it with other code that Mike Bijon was sharing with me ay the same time) the code you shared with me on Twitter looked very similar to a typical Multiton pattern.

    • says

      That will keep you from instantiating a class that doesn’t exist, but it won’t prevent you from instantiating a class twice. If you can have one and only one instance of, say, WP_Session, calling new WP_Session() more than once will cause serious problems in your application.

      The if ( ! class_exists( 'Class_Name' ) ) checks for class definition, not whether or not you’ve instantiated it.

    • says

      It won’t guarantee one instance, but If someone declares a new instance of your class when they don’t need it, they didn’t look closely enough at the code.

      • says

        When you’re working with a large project (i.e. WordPress), you might not always be aware of other instances of the class. Also, new modules can be introduced that need to instantiate the class earlier than you originally did.

        For example, if I introduce My_Class and instantiate it halfway through the request lifecycle, things are great. The next developer comes along and needs to call My_Class->do_something() at the end of the request. Great, he can do that just fine by grabbing my already-instantiated object and just using it. Then another developer writes a module that needs to call My_Class->something_else() at the beginning of the request. My version isn’t instantiated yet, so she creates a new instance.

        Now we have two instances floating around where I, as the original developer, only ever intended to have one. You could argue that I should just place my instance’s creation at the earliest point of execution, but what’s the point? Now I need to create an object in the global scope (so I can find it again later when I actually need it) far sooner than I actually need the object just to prevent others from creating multiple instances. That’s the entire point of a singleton, particularly one with a lazy instantiation as in my example. Anyone can call My_Class::get_instance() at any time after the class is included, and they’ll have access to the same instance.

        • says

          “Then another developer writes a module that needs to call My_Class->something_else() at the beginning of the request.”

          That’s a good point. I would think that this is a very rare circumstance. For a class that only needs one instance I would think that in most cases, filters in the appropriate places would avoid the need for a new instance.

          If you’re class can/would be useful in so many different places, maybe it shouldn’t really be a singleton.

          I can’t argue that in very rare circumstances singletons are useful, but I think they should be avoided if possible.

  2. says

    The problem with Singletons, and your proposed solutions, is that you are coupling WP development and design with it.

    There are several problems that you do not attempt to tackle, or are unaware of. For starters, Singletons are hidden requirements. Using a singleton, or even a global $var in your code is not something that is exposed in the API. I cannot simply take your class and use it because it assumes you have an open DB connection. This also, as it happens, makes it difficult to Unit Test. But the reality is, it’s a hidden dependency. These are bad from a maintenance and code portability POV.

    Moving on, Singletons also violate the Single Responsibility Principle. In short, each class should have on responsibility. By tacking on Singleton awareness, suddenly the singleton is managing it’s own instantiation and lifecycle. SRP is the S in SOLID http://en.wikipedia.org/wiki/Solid_(object-oriented_design).

    As you mentioned, singletons enforce coupling. It’s really as simple as that. You mention this is bad as well, but don’t really address in any meaningful way.

    Finally, you mention state, and your solution is a reset() method, that is public, that resets the state of the class. This is not only bad for reasons mentioned above, but it’s also dangerous.

    One of your arguments was regarding the use of Singletons by WP as an expression of support. Singletons in WP aren’t there to support Singletons, it’s there because of history and backwards compatibility.

    I’ll go on to add that your DI example is primitive. I highly suggest reading up on the topic of DI. There is a lot written on it. You seem to be trying to argue against something that you do not fully understand yourself. (At least, if you did, you’d have used a better, more complete example).

    • says

      Hi @Jason,

      I’m curious if you specialize in WordPress/PHP, or if you use develop on/in another platform/language? Your comments make great sense from a purist software architecture design standpoint but don’t seem to ackowledge the specific aspects of plugin development for WordPress, which is effectively what this post was about.

      For example in a WordPress plugin you always assume a single open database connection; you won’t be loaded otherwise. And WordPress is filled with hidden dependencies, you can’t get around them, you can only do your best to know about and work with them. And the complexity that WordPress brings throws the Single Responsibility Principle out the window for at least the main class used by a plugin. Plus Dependency Injection creates complexity that many WordPress developers prefer to avoid; Decisions not options is often the mantra, and the way most plugins handle the need to exchange dependencies is via global hooks. Archaic yes, but in practice they work well.

      And yes all of these things make the purist software architect weep, rightly so. But on the other hand this shoddy architecture has managed to capture over 17% of the web with almost 23,000 published open-source plugins, many of which work compatibly with each other. Those facts alone cause me to wonder if the conventional wisdom really is as wise in all cases as it proports to be. So with respect to developing plugins for WordPress I close by simply saying: “When in Rome…”

      • says

        I’ve never done any work with WordPress, though I’ve been doing PHP development since PHP 3. I also work in a number of other languages, like Obj-C, Java, C, Erlang, and JavaScript.

        As for the topic of this post, you’ll forgive me, but if the article is specific to WordPress development, it wasn’t made clear, at all. In fact, the article suggests otherwise. FTA:

        “I would argue that Singletons are not just useful, but are necessary for robust software development.”

        Unfortunately, just like how a Singleton hides dependencies, the topic wasn’t made clear to the public.

        > And yes all of these things make the purist software architect weep, rightly so…

        This isn’t about purist software architecture, it’s about real architectural problems. (And frankly, using the word purist is almost insulting. You are trying to frame the idea that singles are bad as some form of elitist programming. It’s not.)

        That isn’t to say that these architectural problems can’t be overcome. But to assume that they aren’t there merely because of success ignores history. After all, is popularity really indicative of completely quality? I suggest that WP was successful, not because of architecture, but rather, due to a few other things. PHP, being easy to deploy, was one of them. MovableType’s license changes were timely, and caused a move from MT to WP. And WP’s UI was easy enough. And, because PHP was so easy, eventually plugins as well.

        Regardless, if popularity was indicative of quality, then we’d still be using IE6.

        > Those facts alone cause me to wonder if the conventional wisdom really is as wise in all cases as it proports to be.

        That’s like suggesting that iOS is popular because it uses Obj-C. Or better, that iOS is popular because it uses an MVC design pattern. It doesn’t. But the quality of the software is better, and that leads to better quality software.

        > “When in Rome…”

        What you are saying is “We’ve always done it this way.”

        http://www.jeffbridges.com/because.html

        Listen, I’m not suggesting that WP Plug developers need to suddenly shun the singleton. I’m not even saying using a Singleton makes you a bad developer. Rather, what I’m saying is, if you don’t understand the problems of a Singleton, and you don’t understand real DI (and if you consider the example in the article as sufficient DI, you don’t), then you really don’t know what you are talking about. You just don’t know. And that’s alright. It’s fine. But I’d highly suggest you learn. At least then, when you use a Singleton, you can say “Yes, it’s bad because, but for our requirements, it solves these problems right now, which is better than what not using them provides.” You are, in effect, breaking the rules without knowing what you are breaking.

        I’ll highly recommend “Dependency Injection in .NET.” (http://www.amazon.com/Dependency-Injection-NET-Mark-Seemann/dp/1935182501) It’s an excellent resource that goes into things a lot better than I ever could, and while it says “.NET” in the title, the lessons can really be applied to PHP as well. And while I don’t imagine you’ll want to employ ever solution or suggestion offered, it really does an excellent job of making you think and understand the problem of DI.

        • says

          “As for the topic of this post, you’ll forgive me, but if the article is specific to WordPress development, it wasn’t made clear, at all. In fact, the article suggests otherwise.”

          I can’t speak unequivocally for Eric but I’m pretty sure his post relates almost exclusively to WordPress. Eric please correct me if I’m wrong. And I agree, Eric could have made it more clear that his post was WordPress-specific.

          “And frankly, using the word purist is almost insulting.”

          You found an insult where one was never intended. I was using the word to describe architectural ideals that did not need to be concerned with constraints of a given platform. If you can think of a word that better encapsulates what I was trying to imply then I’ll be happy to use it instead in the future.

          “That isn’t to say that these architectural problems can’t be overcome. But to assume that they aren’t there merely because of success ignores history.”

          No I do not ignore history, please don’t imply that I do. Seeing from your Linkedin profile I’d say I have lived through ~15 more years of development history than you, and yes I paid attention along the way. That doesn’t make me infallible, but it does mean I am experienced and that I have been aware.

          “After all, is popularity really indicative of completely quality? I suggest that WP was successful, not because of architecture, but rather, due to a few other things. PHP, being easy to deploy, was one of them. MovableType’s license changes were timely, and caused a move from MT to WP. And WP’s UI was easy enough. And, because PHP was so easy, eventually plugins as well.”

          I agree all those things were important. Not sufficient, but very important. I actually thing many of the techniques that enterprise software architects consider anti-patterns have had a lot to do with it’s success including global variables, event-driven architecture, and simplified function-driven APIs. But I digress.

          I’ve worked with WordPress for 3+ years and Drupal for 2+ years prior to that and both platforms do things that violate tenants that most software architects hold dear yet both are extremely successful platforms, and by successful I mean they are platforms people can and have successfully deployed, extended and maintained over many versions and with many installations. So I’ve spent a lot of time thinking about the actual benefits of those tenants so many developers assume to be postulates and I’ve come to believe that things are very rarely black and very rarely white but in-fact most often are very gray.

          I myself was one of those staunch believers back in the early 90′s with respect to object orientation. And also for strict typing. And then later for MVC. Yet fast forward ~20 years and I’ve come to realize that OOP has it’s issues with the fragile base class being a big one, that dynamic languages can be much more productive than strictly typed languages causing me to realize that strict typing optimizes for one idea to the compromise of others, and that MVC itself has the same fragility issues of OOP. Which all summarizes to me believing there is no one single “right” position on any given aspect of development, they are only varying degrees of optimization for any given set of criteria, and the criteria set one developer values are most likely different from the criteria valued by others.

          > “When in Rome…”
          “What you are saying is “We’ve always done it this way.””

          And that I find insulting. That is not what I was saying. What I was saying is that different techniques work better in different contexts. Don’t try to use the same techniques that work for WordPress when developing for .NET or Rails. Nor vice-versa. And if you are not experienced in a platform then it would be gracious to acknowledge that your opinion, though valid for your area of experience may or may not apply in areas for which you don’t have experience.

          “Rather, what I’m saying is, if you don’t understand the problems of a Singleton, and you don’t understand real DI (and if you consider the example in the article as sufficient DI, you don’t), then you really don’t know what you are talking about.”

          What makes you so sure Eric doesn’t understand those? And respectfully, what makes you so sure that you do? (I’m bringing this latter up not because of your comments but simply because I think it’s a trap a lot of people get into: assuming they know what’s correct and that the other guy doesn’t. Maybe it’s they themselves who don’t know what they don’t know?)

          One final comment. It’s very easy when you know nothing about someone other than reading their blog post or their comment on a blog to presume ignorance or even malice; I find myself falling into that trap too. So I will say I found your comments more than a bit aggressive in that they seemed to presume you were more educated on the topics than Eric and myself. Rather than explore the issues Eric raised, it seemed you preached to him and me. And to Eric’s credit he has not responded though I have in his stead. But I’m going to assume that all of this was a misperception on my part because it very well could be the case. I’m just hoping that when this comment thread ends it won’t end how it feels it like started but instead I hope we can end it with mutual respect where all of us have learned something.

        • says

          As for the topic of this post, you’ll forgive me, but if the article is specific to WordPress development, it wasn’t made clear, at all.

          You’re reading an article written by a core contributor to WordPress, on a site that talks almost exclusively about WordPress, that makes several references to WordPress, and that references two separate tutorials about singleton design in WordPress in the opening paragraph. Yes, I can forgive you for missing that this article is specific to WordPress development, but since so many others caught that fact I didn’t see it as important to state explicitly.

          So to clear up any remaining confusion, this post is specifically about WordPress development. I’ve also added “in WordPress” to the article title.

  3. idont says

    If I understood Misko Hevery (Clean Code evangelist in Google) correctly, you are actually right AND wrong. Actually you are mixing 2 different concepts:

    a.- Singleton: a design pattern.
    b.- singleton (notice that there is no more capital “s”): a single instance of a class.

    What is usually critizied is Singleton (a) because of testability (global states are evil).

    But singletons (b) are, in many cases, usefull and not evil (Think database connexion, class, Session class, etc.).

    The thing you miss is that you can have singletons (b) without Singletons (a) if you use correctly DI (they are lots of frameworks for that).

    If you want solid arguments and watch eye opener videos, I strongly advice you to search for “clean code misko hevery” on youtube: http://www.youtube.com/results?search_query=clean+code+misko

    You can also check his blog: http://misko.hevery.com/

    Enjoy! :)

    • says

      Right comment to this blog post. Also the Singleton suggested here is not a properly implementation of the Singleton Pattern in PHP. Just saying, I have the feeling that the arguments in this blog post are overly theoretical only anyway, practically this all does not play much of a role in wordpress plugin developement. However if somebody comes here to improve, learn to not use the Singleton pattern. Most people who advocate it have the tendency to over-use it and when they realize they need to refactor a lot of their code. Better know how to decide when to use which tool properly. And that starts with using the right terms as just has been commented.

        • says

          Well, I bet you would love to hear that, however I wonder why you were not able to find that in the literature so far. From what you describe a Singleton is for you seem to follow by the book, however, you didn’t read up the rest? Well, then I think it’s of more use to you if I don’t spoil it and I’ll leave this as an exercise for the moment. Let me know if you run into real problems to learn more.

          • says

            I wonder why you were not able to find that in the literature so far.

            Did it ever occur to you that I wasn’t writing this based on something I read in a book? I’m falling back on my experience in various programming languages and years of reading in-deployment code written by other, very talented developers as well.

            I think it’s of more use to you if I don’t spoil it and I’ll leave this as an exercise for the moment.

            No, that’s dodging the question and quite a bit insulting, really.

          • says

            I don’t understand what’s so wrong in not spoiling, however, your Singleton does not care about clones and serialization. See as well: https://hakre.wordpress.com/2012/06/10/the-missing-patterns-of-the-php-manual/#p2 – And by the book I mean the greenfield implementations, as you’re blogging I at least thought you were searching about that topic in the internet (or at least my comment would motivate you to). It was not meant as an insult just to not spoil it as I’ve written. Sorry if that didn’t get through.

  4. says

    Hi Eric – I’ve written a response to this, but it’s too long for a comment, so it’s on my blog: http://www.toppa.com/2013/the-case-against-singletons-in-wordpress/

    I’ve made point to keep my disagreement civil, as I’m excited to see these kinds of discussions happening around WordPress code design, and I respect your efforts. But as you’ll be able to tell from my post, your solution to the challenge of dealing with global state is very different from the direction I’m hoping WordPress core development will take.

  5. says

    I mostly agree with your article and Mike’s comments, but one thing I’m curious about is the practical need for singletons in a WP plugin.

    Have you ever seen a plugin instantiated twice? I know that it’s possible for some other plugin to do it intentionally, but I don’t think WP ever will, or that it would happen accidentally.

    So, if the only time it would ever happen is if another plugin intentionally does it, then is it really necessary to implement a singleton? I’d be tempted to just say that the other developer is doing it wrong.

    On the other hand, implementing it is fairly simple, so maybe it’s worth the minor effort to protect against the 1% chance of a problem.

  6. says

    Given that singletons are implemented using classes, there should be some way to facilitate subclassing to extend the base singleton class with custom behaviors. This can’t currently be done using the common singleton boilerplate shown, where the constructor is private and there is no way to override the $instance variable. If, however, the constructor was protected and there was an extend(BaseClassName $subclassname) method which replaced the $instance with the subclass instance, then the base singleton class could remain as the primary interface but the methods could be located in the subclass.

    • says

      See, the whole point of a Singleton is that it can’t be subclassed. In most languages, a static variable is automatically inherited by every class that extends the one that declares it. So if BaseClass declares a static (even protected) instance container, any class that extends BaseClass will have access to the same static variable. Now you have multiple classes talking to the same container and walking all over one another.

      You can alleviate this problem by abstracting it into an array of indexed instances, but at this point you’re getting much closer to a factory pattern and should just go the whole way to a factory.

      Singletons are specifically single-use objects that are specifically intended to not be extended or overridden. It’s this inherent flexibility that makes so many people hate them and why, in the majority of cases, they’re the wrong choice for an object pattern.

    • says

      @Weston – Even though @Eric likes the factory pattern better we think Factories are too abstract for most of WordPress development so we’re doing exactly what you mention.

      We are using a base class that you can extend to create a Singleton. The instances are stored in an array keyed by class name and it works extremely well for the using a Singleton as a code wrapper for a plugin’s hooks. We haven’t blogged about it yet but plan to as soon as we have the time to do it justice; when we do you’ll be able to find it here.

      Note there is one unfortunately aspect of it and that is PHP 5.2 does not support get_called_class(). The upshot is you can’t have your base classes implement static methods that need access to their own Singleton instance without simulating get_called_class() with some very hacky code. Fortunately we’ve found we only need to call those methods in rare cases so it’s not the issue it sounds like it would be, and in PHP 5.3 it works fine.

      That’s what I mean about having the time to do it justice; we need to explain all this in code with good examples. Still, if you want to see what it looks like this is the base class we are using for client projects.

Trackbacks

  1. [...] Eric Mann wrote a thoughtful and detailed argument for using the Singleton pattern in WordPress deve…. Given the particular nature of the WordPress development environment, his reasoning is understandable and clearly comes from experience. The criticisms I’ve seen so far in his post comments, and in Hacker News, don’t make good counter-arguments. They are coming from people who either aren’t familiar with the constraints of developing in WordPress, or who are just looking for any opportunity to bash PHP developers. [...]

Leave a Reply