WordPress plugin design is not something that we often read about explicitly, is it? Instead, we often talk about functionality, performance, and things like that (not that they are unimportant, but they are just one part of the conversation).
When it comes to WordPress plugins, the functionality one offers may range from very small to incredibly large. And this is how it is with almost any type of product, isn’t it?
Sometimes, I think we have a tendency to want to say “focused, and lean” with smaller plugins as if a larger plugin can be described as such simply because of its nature.
But that’s not true.
There are very small, well-built plugins that offer one or two features. And there are large plugins that are also well-built that offer a plethora of features. On the flip side, either type may also be unfocused, cobbled together, and may be anything but what we’d like it to be.
When you look at the landscape of all that’s offered regarding WordPress plugins, it raises a few questions (at least from a developer’s perspective).
I’m going to cover them all in this post, too! Or not.
But seriously, one of the things I’ve been thinking about is this:
At what point do you begin organizing your code, so it includes namespaces, autoloading, dependency management, and other such features that take it beyond a collection of classes or functions?
This implies a lot about a given hosting environment and a developer’s level of familiarity with PHP and experience with other tools, but that’s secondary to the question (and I’ll cover all of that momentarily).
WordPress Plugin Design
According to the requirements page on WordPress.org, they recommend at least the following:
Features such as namespaces and autoloading have been available in versions of PHP prior to 5.6, and dependency management can be handled with tools such as Composer.
So arguments against using any of those three things aren’t something I’d entertain as part of this post. And yes, there are more advanced things we can do with newer versions of PHP. But, all the same, they aren’t things I’d entertain for the point of this post.
Though they aren’t required, I find using namespaces helpful when working with object-oriented code. I try to make sure my namespaces (which can form a virtual path to a class) mimic the directory structure (or the physical path) to a class.
I don’t know if this is the prevailing strategy or not, but it’s what works best for how I conceptualize the organization of my code.
Are namespaces something we should bother introducing in smaller plugins?
Though some arguments against using them can be made, I tend to favor using them (though this hasn’t always been the case). No, I’m no fan of the whole architecture astronaut mentality, and I try to be as pragmatic as I can when creating solutions for others – be it for fun or profit.
But if there’s one thing I’ve learned when working on plugins – especially for profit – is they are likely to change (and by change, I mean grow).
Laying a well-organized foundation and structure from the outset can help guide decision-making later in a project. And this is the main reason I favor using namespaces as early in a project as possible.
The same argument can likely be made for creating interfaces, abstract classes, and the like but those are outside the scope of this post.
There are a couple of different ways we can use autoloading. That is, we can write our own and include it with our plugin or we can use something like Composer (or we can even do both, but that’s not the point).
How you opt to include autoloading is secondary to whether or not you opt to use autoloading or not. And just as with namespaces, I ask:
Is autoloading something we should use in small projects?
For a long time, I wasn’t necessarily sold on it for smaller plugins. Sure, you can use the same argument as with namespaces in that it helps guide future decision-making. But I don’t consider autoloading part of the architecture decision-making process.
Instead, autoloading is a utility. It provides us a level of convenience that prevents us from littering our code with including or requiring various files from all over the plugin’s directory structure.
Instead, we include an autoloader and then let it take care of the rest regardless of if we have existing files or files yet to be introduced.
Ultimately, it allows us to write a single function we can use from the beginning of a project and have it scale with our work as we introduce more namespaces and, thus, more classes. And this is the main reason I like using autoloaders as early as possible.
Again, regardless of how you opt to employ an autoloader doesn’t matter so much as whether or not you use them. And it doesn’t matter if you’re using them for just a couple of files or a more complex plugin, they pay dividends the larger your project gets.
Two of Many
There are many other things worth asking about when we should introduce certain features, tools, or strategies. Sometimes, it’s easy to anticipate what a project may require. Other times, it’s not (especially since we usually know the least about a project at the beginning).
But there are things that can make architecture and productivity a bit more efficient regardless of how much we know or how much functionality we’re building at the beginning of a project.
That is, we generally have an idea of how we’re going to organize our directories, files, assets, etc. And if we know that and we want to move forward with adding additional files to our projects with as little friction as possible, why not get started with that as early as possible?