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[ref]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.[/ref] Singletons are used all over.  Think of every time you’ve used the [cci]global[/cci] keyword when working in WordPress.  Not for Posts, which are atomic objects, but for framework-wide constructs like [cci]$wpdb[/cci] and [cci]$wp_rewrite[/cci].

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 [cci]new wpdb()[/cci] in your themes and plugins; instead you make a reference to the [cci]global $wpdb[/cci] object that WordPress set up for you.[ref]In reality, you can (and will) call [cci]new wpdb()[/cci] 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 [cci]new[/cci] keyword never appears in the context of the WP database object.[/ref]

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 [cci]WP_Rewrite[/cci] 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 [cci]WP_Session[/cci] 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 [cci]WP_Http[/cci] 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 [cci]WP_Session[/cci] 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 [cci]new WP_Session[/cci] 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 [cci]WP_Session[/cci] 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 [cci]get_instance()[/cci] 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 [cci]reset()[/cci] 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 [cci]Singleton::reset()[/cci] 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.