What lies behind this somewhat provocative headline? Over time, I have noticed something about certain WordPress plugins. What exactly, I will describe here.
First, I must admit, that I did not only notice that with plugins from other developers, but first and foremost with older plugins by myself. When I was developing my first plugins, I proclaimed with the utmost conviction at some point: "I now use object-oriented programming in my plugins!". Unfortunately, this was not the truth. My code looked something like this:
<?php
/*
* Plugin Name: Not object oriented
* Description: I'm not object oriented
* Author: Marcus Kober
*/
class MK_MyPlugin
{
public function __construct()
{
add_action('init', [$this, 'init']);
add_action('wp_enqueue_scripts', [$this, 'assets']);
}
public function init()
{
$results = $this->getResults();
// Some more code
}
public function assets()
{
// wp_enqueue...
}
private function getResults()
{
// Some code
}
// More methods
// ...
}
new MK_MyPlugin();
So what did I do? I have packed all functionality of the plugin inside one large class and then instantiated it directly.
The complete code inside a huge single class does not make it object-oriented programming
If all the code of your plugin resides within a single class, and this class is instantiated at runtime, this is some sort of programming inside a class, but not yet object-oriented programming.
All that is achieved with the code above is merely a better encapsulation of the code so that there is no need for prefixing your functions and variables to avoid name conflicts (more on that in the upcoming article about namespaces). Unfortunately, it's nothing more like that and certainly not object-oriented programming.
So, what type of programming do we have here?
Next to object-oriented programming is procedural programming. In procedural programming the code is organized in steps, to get a clear structure. Code fragments are often organized in functions and every step is represented by a code line. One step is, for example, a variable declaration, a function call, an if-query, and so on.
The code of our little plugin introduced above would look something like that in procedural programming:
<?php
/*
* Plugin Name: Not object oriented
* Description: I'm not object oriented
* Author: Marcus Kober
*/
function mk_myplugin_init() {
$results = mk_myplugin_getResults();
// Some more code
}
function mk_myplugin_assets() {
// wp_enqueue...
}
function mk_myplugin_getResults() {
// Some code
}
add_action('init', 'mk_myplugin_init');
add_action('wp_enqueue_scripts', 'mk_myplugin_assets');
The only difference to the first code example is that the various functions of the plugin were implemented as methods of a single class. Essentially, the problem is solved in the same procedural way in both versions of the code, only the arrangement of the code is different.
In the world of WordPress, you'll find many such examples of procedural programming. Many plugins and even large parts of the WordPress core are based or were based on procedural programming, and that is absolutely fine. Even though many parts of WordPress are now built as classes, these are obscured in the WordPress API by functions such as get_posts().
In the first article of this series, I already wrote: it is not absolutely necessary to use object-oriented programming and modern PHP for every plugin. However, especially for more extensive plugins, object-oriented programming helps enormously in structuring the code (alongside other advantages that we will get to know).
What does object-oriented programming solve?
Let's assume you are developing a plugin. At first, it's not very complicated. Procedural programming would not be a problem here and should be the way to go.
Over time, however, several things happen:
new functions need to be implemented
bugs need to be fixed
perhaps there are problems with other plugins and a workaround needs to be implemented
new WordPress versions are leading to problems that need to be addressed
and so on
This is where procedural programming quickly reaches its limits. Such issues indicate that something should be done about the general structure of the code:
Where should the new code be integrated?
Does the new code lead to conflicts with existing code?
Should the code be split into multiple files?
How should the new files be named?
How much code and which code should the files contain?
In what order should these files be loaded?
Now let's assume, we solved all those issues with procedural programming. We now have a large codebase, distributed over many files with more or less speaking file names. The code gets more and more complex and tasks such as bug fixing or feature integration become increasingly difficult.
But now a new problem arrives: a client is calling and wants you to develop a new plugin. You recognize that the new plugin needs some parts of your last plugin. The reusability of code that is so deeply entangled in your codebase is certainly not very high. You can indeed copy certain parts of the code, but you probably have to untangle many tight wirings first to really integrate the code into the new plugin.
That costs you time - and therefore either you or the client money!
That's where object-oriented programming enters the stage. In object-oriented programming, as small classes as possible work together to solve a problem in its entirety, while each participating class solves only a narrowly defined sub-problem. This not only increases the readability of the code and leads to a more orderly structure, but also facilitates the reuse of the code. In this way, certain classes can be used in different plugins without having to complicatedly extract them from the existing code.
Done right, object-oriented programming increases the readability, maintainability, reusability, and testability of your code, leading to cleaner code and - hopefully - lesser bugs. 😊
What exactly does a WordPress plugin look like, that is based on object-oriented programming? We will work that out together in this series of articles.
Conclusion
Of course, object-oriented programming brings its own problems, but it is precisely these problems that I want to address in this series and hopefully solve to some extent. By using object-oriented programming, as a developer, you have a wealth of often proven solutions for recurring problems at your disposal, the so-called design patterns. Autoloading relieves you of the agony of choice of when to load which file, and dependency injection takes away the question of which class to instantiate when. All of this we will discuss in this article series.