Things That Matter Most

Things That Matter Most

  • Home
  • Business
  • Faith
  • Technology
  • Politics
  • Creative Writing
  • Email
  • GitHub
  • RSS
  • Twitter

Powered by Genesis

Singleton: Alternative to the Anti-Pattern

March 6, 2014 by Eric

I made quite a splash when I advocated the use of Singletons in WordPress development.

I still stand by Singletons as a valid design pattern – and my method for making them testable in PHP.  At the same time, I recognize that Singletons are considered an anti-pattern for a specific reason.

If you don’t, then what follows is absolutely important for helping you understand why not to use Singletons.

If you already agree, skip the next part and move on to the resolution.

The Dangers of Singletons

The entire point of a Singleton is to prevent multiple instances of your object from living together in the same context.  This is a valid concern when your object represents, say, a PHP header collection, the current request, or the final response being sent to the client.

Single-instantiation, however, breaks the ability to test the object as, even in your test suite, you can only create one copy of the object. 1  If you’re building a well-covered application – and you are building a well-covered application, right? – this particular limitation of Singletons will give you a headache.

Singletons are also inherently inextensible – you cannot subclass a Singleton.  As your application grows, however, the need to subclass an object can and will come up.

Take my example above – that a Singleton could represent the response object being sent to the client.  What if you decide to extend a JSON API for your application?  The easiest way is to extend your general response object to create a JSON-specific one; if it started as a Singleton, however, you can’t.

There are valid reasons for using a Singleton in your design – these reasons, however, are rare enough that many developers can avoid them entirely and still have a full career.  If you find yourself using Singletons often, you’re doing something wrong.

An Alternative

In the world of WordPress, developers will often use a Singleton to wrap some sort of god object 2 that wires in all of their actions and filters.  The justification behind this pattern is extensibility – other developers will need an easy way to get a reference to your original instance so they can remove, reorder, or otherwise manipulate your chosen hooks.

Kudos to developers wanting to make their code extensible.

Boo to developers using Singletons to do so.

Instead, developers should investigate and utilize a variation on the “factory method pattern.”  Thanks to static method variables in PHP, it’s fairly straight-forward to expose a uniform access method on your object that always returns the same instance of that object or creates one if it doesn’t exist.

For example:

class Example {
    public function __construct() {
        add_filter( 'the_content', array( $this, 'the_content' ) );
    }

    public function the_content( $content ) {
        return $content;
    }

    public function do_something() { }

    public static function factory() {
        static $instance = false;
        if ( ! $instance ) {
            $instance = new self;
        }

        return $instance;
    }
}

// In your code elsewhere:
Example::factory()->do_something();

remove_filter( 'the_content', array( Example::factory(), 'the_content' ) );

Just be sure that, in your code that include()s this file, you call Example::factory() rather than instantiate the object directly. Instantiating the object will not populate the factory’s internal instance container – production code should avoid direct instantiation and always defer to the factory.

To be even safer, you could move any hook wiring to a method other than the constructor – one that you invoke directly. Then subsequent, accidental instantiations won’t double-bind events.

How This Solves the Singleton Problem

Singletons are used in WordPress to provide universal access to an instantiated object without needing to pass a variable from one function to another.  The pattern above does the same.

Singletons prevent an object from being instantiated more than once, breaking the ability of unit tests to isolate state from one another.  The pattern above allows tests to create as many copies as they need by directly firing the constructor and bypassing the factory method.

Singletons prevent object sub-classing for new method implementations.  The pattern above allows subclassing both instance methods and the factory method being used.

Moving Forward

If you’re using Singletons in your WordPress code, I strongly recommend you reconsider.  The above example is but one way to achieve the same universal access and functional single-instantiation Singletons provide, but without crippling your code’s testability or extensibility.

If you aren’t convinced factory methods are better than Singleton accessors, I’d be interested to know why.

Notes:

  1. There are ways around this by using, for example, process isolation. ↩
  2. The god object is another dangerous anti-pattern that I will address in the future. ↩

Filed Under: Technology Tagged With: anti-pattern, factory method pattern, singleton, Singleton Pattern, WordPress

Like what you’re reading?

Consider pitching in to help cover the costs of maintaining this site and keeping my work 100% ad-free.

Close×

Comments

  1. GM says

    March 6, 2014 at 8:13 am

    Things such Pimple solves this problem in modern PHP frameworks. Using modern libraries in WordPress is what actually I’m trying to do daily and this: https://github.com/Giuseppe-Mazzapica/Brain is just an example.

    • Eric says

      March 6, 2014 at 8:18 am

      I’ve seen Pimple before, but I only recommend abstractions like this to people who truly understand dependency injection first. Like any pattern, if you fail to understand the benefits behind it, you’ll end up implementing it all over the place – even when it’s inappropriate. Abstraction layers like Pimple make it easy to forget you’re using a specific design pattern under the hood.

    • zanematthew says

      March 6, 2014 at 8:33 am

      Your repo does seem enticing/promising, but the big issue IMO is that WordPress should increase their PHP requirement currently its 5.2.4 😐 http://wordpress.org/about/requirements/

      • Eric says

        March 6, 2014 at 8:40 am

        I, and most professional WordPress developers, agree with you whole-heartedly there. The reason WordPress still supports back to PHP 5.2.4 is because of the sheer number of hosting companies that allow customers to run an older version in production.

        When a WordPress site does an automated check for version updates, it passes along some information about its environment (this is anonymous information and only used so the system doesn’t recommend an update that will crash an outdated version of PHP/MySQL). We aggregate these anonymous statistics on the WordPress.org site. Despite me and everyone I work with wanting to force a PHP version requirement update, 49% of WordPress end-users are still running PHP 5.2.

        As much as an update would improve the codebase (and make my live easier), we can’t just abandon nearly half of our customers – many of whom don’t even know what version of PHP their host is running in the first place or wouldn’t know how to update it even if they did.

        • GM says

          March 6, 2014 at 9:23 am

          > “49% of WordPress end-users are still running PHP 5.2” Statystics like that are misleading. If 49% of sites using WP are on PHP 5.2 means that a lot of hosting companies still provide plans with 5.2; end users (people that just want use WordPress) don’t know which PHP version their site runs, and don’t know which is the difference from 5.2 and 5.4, and really sometimes don’t know what PHP is. Sure is unimaginable that WP says “tomorrow our min requirement is PHP 5.4” but if WP says “with 1st january 2015 we require PHP 5.4” any hosting company on the planet will do everything to be ready on that date, because WordPress is so popular that no hosting company can ignore it (no hosting company that doesn’t want to fail soon, at least). That will be a great improvement for WordPress, for developers and primarily for end users: modern PHP versions are more powerful, reliable and secure, and those benefits are all for end users. In conclusion, If WP will require soon PHP 5.4 that’s not “abandon nearly half of our customers” but really “improve web experience of nearly half of our customers”.

  2. Alex Espinoza says

    March 6, 2014 at 8:30 am

    It is really not an alternative in the sense of the Singleton Pattern. It is an alternative implementation of the Singleton Pattern in PHP.

    We have been doing this in C# for a while:
    http://neonlabs.structum.net/blog/implementing-a-singleton-in-c-reloaded/

    But it is still a singleton. It is just a safer way of implementing. The implementation still suffers from the Singleton Pattern disadvantages.

    • Eric says

      March 6, 2014 at 8:36 am

      The implementation still suffers from the Singleton Pattern disadvantages.

      Um … no. This implementation might still expose hidden dependencies (whenever you have a global reference to an object inside a function rather than passing it as a parameter, you have a hidden dependency). But it doesn’t suffer the disadvantages of testability and intentional multi-instantiation – which are the specific points I’m aiming to address.

      • Alex Espinoza says

        March 6, 2014 at 9:47 am

        Yes it does…
        1) It still violate the Single Responsibility Principle.
        2) Your code is still highly coupled because of the global instance.
        3) And it still hides the dependencies.

        BUT it doesn’t mean you are doing it wrong. If you are going to use a singleton, your implementation is definitely the way to go. But it is still a singleton. Don’t call it different.

  3. Omegote says

    September 27, 2016 at 2:54 am

    Lol I came here looking for alternatives to the singleton and this article just offers the very same singleton implementation I’ve been using all along in C++. Wat.

    • Eric says

      September 28, 2016 at 9:11 pm

      Good to know somewhat hacky patterns exist in every language, I guess 😉

About Me

Eric is a storyteller, web developer, and outdoorsman living in the Pacific Northwest. If he's not working with new tech in web development, you can probably find him out running, climbing, or hiking in the woods.

Get the newsletter