I recently walked through the process of using a class’ constructor to prevent a plugin from working if it an expected dependency isn’t loaded.
Though I don’t consider this particular strategy a problem for a one-off dependency or in certain situations, there are ways this can lead to code smells.
It also prevents us from using a native feature of Core called WordPress subactions:
— ʝ³ #wcus (@JJJ) January 20, 2017
But before looking at subactions, I want to make sure I’m clear around the problems using the conditional approach (versus subactions) can breed with code smells.
There are a lot of ways code smells can be explained, but my favorite way comes from Martin Fowler:
…smells are certain structures in the code that indicate violation of fundamental design principles and negatively impact design quality.
There’s another great page about code smells on Source Making that I recommend reading if you have a chance.
And the way that conditionals can lead to code smells is simple: It has potential to litter your code with a massive set of statements that include a lot of class_exists checks.
And that’s a problem.
Each time you introduce another dependency into your code, you end up adding yet another conditional checking to see if a class is present in the WordPress application.
I believe it’s okay to do this with a single dependency – maybe even two dependencies – and if you’re working up “high enough” in your architecture, but this is not how to properly handle this with many dependencies nor at a lower level in your plugin.
That’s where WordPress subactions come into the picture. You can see a list of subactions in the tweet via John above.
There’s an official definition of sub-actions in the bbPress Codex, too:
These internal actions can be thought of as “sub-actions” and allow you to add or re-order WordPress actions as necessary for plugins that depend on bbPress.
And you can see an example of it in this file.
Sure, this definition is specific to bbPress, but that doesn’t mean it’s not applicable to what we do in WordPress.
Case in point: If you’ve ever used do_action to define a custom action, or you’ve taken advantage of a hook provided by someone else outside of WordPress core, then you’re familiar with the strategy of implementing a sub-action.
In other words, WordPress subactions are simply actions that we can use to change the order in which our plugin depends on another plugin.
How this is implemented may vary within the context of your work, but the most popular and most “correct” WordPress-way of doing this is arguably taking advantage of the priority argument for when your plugin is loaded.
That is, take the priority of the dependency and make sure that it’s earlier than when your plugin is activated.
There are alternative methods that can be used, such as changing plugin behavior whenever they are activated or not, but this is outside the scope of this particular post, and it may negatively alter the user experience (of WordPress in general, no less).
Regardless, the point is that when it comes to using WordPress subactions, object-oriented programming, and managing third-party dependencies, make sure that the decisions you’re making aren’t going to damage the design of your code.
If it makes sense to check for the existence of a class, okay, but if it makes more sense to wait until a set of classes or plugins have loaded before your own, then WordPress subactions likely make more sense.