WordPress and The Single Responsibility Principle

I love the fact that people are working to bring more advanced object-oriented programming techniques to WordPress-related development.

That is, I’m really glad to see others are pushing for people to write more truly object-oriented code rather than using classes as a “poor man’s namespace” (ht to Franz for that nickname), or doing things like setting up hooks outside of a constructor.

To be fair, he had more than one responsibility.
he had more than one responsibility.

To be fair, I’m as guilty as the next for not always writing very good object-oriented code in the context of WordPress (though I’m slowly working to change that – hopefully the Plugin Boilerplate is proof-positive of that), and I think it’s something that we should all be striving to get better at doing.

The Single Responsibility Principle Defined

One of the things that we often here is that classes and functions should do “one thing and do it well” and, many times, people attribute this to the Single Responsibility Principle. The thing is, although the idea behind what are our classes and their functions should do is great, it’s not really what the Principle states.

From 8th Light:

The Single Responsibility Principle (SRP) states that each software module should have one and only one reason to change.

Furthermore, Uncle Bob himself has said the following:

Martin defines a responsibility as a reason to change, and concludes that a class or module should have one, and only one, reason to change. As an example, consider a module that compiles and prints a report. Such a module can be changed for two reasons.

And I think there’s difference between saying that a module should “do one thing and do it well” and “have a single reason to change.” Sure, the different is subtle, but let’s contextualize this idea to WordPress.

Let’s say that you’re writing a plugin that’s responsible for adding a custom post type. Along with the custom post type, additional scripts, styles, meta boxes, and data validation, serialization, and retrieval code must be written.

I think we’re able to convince ourselves that our class does “one thing” by saying “This class is responsible for creating a custom post type.” Literally speaking, the class:

  • Registers several actions (and maybe some filters)
  • Loads JavaScript files and their dependencies
  • Loads stylesheets
  • Creates additional views for meta data
  • Handles serialization and validation for the post type and its meta data

Obviously, this is more than one thing. Instead, it looks as if we need to have classes for:

  • Coordinating hooks with their callback functions
  • Loading JavaScript files
  • Loading stylesheets
  • Displaying the custom post type administrative view
  • Displaying the custom post type public view
  • One class to represent each meta box
  • A class to handle validation
  • A class to handle serialization
  • …and so on.

Yes, this looks a little daunting at first, but the first two objections to this approach are usually easy to put to rest:

This is creating a lot of classes to do a simple thing.

If it were a simple task, then it wouldn’t necessarily warrant the need for a discussion about it. Instead, just because we know how to do something doesn’t mean that it’s simple. It still requires work to make common things happen; software has moving parts and each part should be easily identified.

Secondly, this is also an issue of maintainability. Having a lot of small classes make it much easier to maintain a codebase over time. This is significantly better than having a monolithic class – or god-class – that “creates a custom post type (and does some other stuff, too).”

All of this code spread across so many files rather than the code in a single file?

Absolutely – and that’s really the crux of the Single Responsibility Principle. No matter how you look at it, you’re likely going to have a significant amount of code – it’s either going to be in one large file that arguably results in poor maintainability, or you’re going to have it spread across multiple files each of one has a clear purpose and responsibility.

And when it comes down it, I think we’d all really prefer the latter.

Ask It Another Way

Anyway, this is clearly not a very in-depth discussion about the Single Responsibility Principle and much, much more could be said, debated, shared, and argued. The main takeaway that I’m sharing (primarily for myself, to be honest) is this:

Rather than ask:

Is this module doing one thing and doing it well?

We should be asking:

What would require this module to change? Or, rather, under what conditions what this module need to be changed?

Until we have a single, definitive answer for each function and its class, then we’re not properly employing the Single Responsibility Principle.

12 Replies to “WordPress and The Single Responsibility Principle”

  1. I am not a developer – more like a super-duper reverse engineer.
    I recently encountered 2 plugins that are doing similar things and one IS monolithic while the other one is just as ambitious is not. From the outside it doesn’t seem they do different things but I have read through the code of both.
    1. Monolithic: Pressbooks
    2. Not: wp-fullpage

    The benefit of #2 has been great as I have been able to integrate it into a code base that has completely different functionality.

  2. Best way to understand if you are following SRP is answer the question: “What does this class do?” if you use the word “and” while answering, then No, you are not following SRP.

    1. I almost wrote nearly word for word in the original post, but I ended up changing it to the last quote that you see:

      What would require this module to change?

      Not because i like it anymore or less, but because I think it gets you to think about fringe cases from the outside in.

      Anyway, yours still is a prime example of what we should be asking, IMHO.

    2. The idea of “and” can be a bit limiting if followed too closely (e.g. plugin_manager takes in X and does Y.). SRP is about the job it does. Its responsibility as a class. It should be in charge of one. That’s where the “and” question is brilliant.

      If you use “and” when describing its responsibility then it’s doing too much. It might seem like an obvious distinction, but it’s not so obvious when starting out.

      Using SRP with WordPress brings with it a lot design issues. One responsibility per class leads to a lot of classes. How to wire, load, interact with all those classes becomes problematic.

      I wrote this article about it when Nathaniel (at Pressware) asked about it on SO. You can see a bit of what designing WordPress classes with SRP in mind looks like.

      1. If you use “and” when describing its responsibility then it’s doing too much. It might seem like an obvious distinction, but it’s not so obvious when starting out.

        I agree. I also think that we do a really good job of convincing ourselves that multiples things are just smaller parts of one thing so we end up circumventing the very practice we want to employ.

        Thanks for the comment the link, Carl – much appreciated!

  3. I have been working on a plugin that used your plugin boilerplate as the foundation.

    Everything was neat and tidy…
    …in the beginning.

    I have reached a point where I need to split things up to make things more manageable.
    It’s tiresome to be scrolling through a massive file to find, fix, remove, or add things.

    This is solid reinforcement.

    1. It’s tiresome to be scrolling through a massive file to find, fix, remove, or add things.

      Exactly. And over time, I want to add much more complete documentation and examples for the Boilerplate to help explain the rationale behind things, too.

      At any rate, the whole SOLID stuff is something that – although is not always easy to follow or consistently employed – is something that I think is worth trying to include in our work.

  4. Great article. I had a chance to read Martin Fowler’s article a while ago and became a fan of this approach. Developers very often rush with designing their applications and that’s how poorly designed classes and object graphs come to existence. From my experience spending extra more time in the beginning to design is far better than refactoring later.

    1. Agreed.

      Big fan of Martin Fowler (his writing on refactorings are stuff that I refer back to a lot). And yeah, I think spending time panning things at the beginning helps with maintenance, but it’s also easy to even rush.

      Good development takes times from beginning to end.

  5. My big “gripe” with articles like this is, they slow down my development as I then go back and refactor tonnes of code! :P (It’s one of the reasons I don’t read your blog too much – too much sound advice.)

    I’ll never get my plugin out the door coz I’m always trying to refactor it to follow best practices! And yet, after more than a year, it’s still terrible code! :S (Yep, it’s a big bugger this one)

    Is it worse to release a plugin with poor coding techniques and (intend) to fix it later? Or is it worse to never get it out the door?

Leave a Reply