For some time now, one of the things that I’ve been considering writing about is the idea of refactoring.
Not necessarily in an incredibly specific sense – because each project is different – but in the sense of using some strategies that can help to take an existing project that’s running in a production server and slowly begin to refactor it so that its architecture changes but the functionality remains the same.
Anyone who’s worked in the software world knows just how nasty a codebase can get, and WordPress is no different. And I’m not talking about WordPress core – I’m talking about plugins, themes, apps, or whatever else it is that you may be building on top of WordPress.
For the most part, we start our projects with the idea that it’s going to have a great architecture, a pristine design, and that it’s going to basically be the best thing that we’ve ever worked with.
At some point, usually due to external factors, the thing devolves into a pile that we no longer want to touch, and we hope that it holds together to continue solving the problem at hand.
But it doesn’t have to be that way and even if the code you end up working with – be it your own, or someone else’s – has devolved into a big ball of mud, there’s still a strategy (probably multiple strategies) that you can use in order to refactor it into something far more elegant.
A Word About Design Patterns
When it comes to working with software, design patterns are one of those things that really are quite powerful. Sometimes, though, I can’t help but think we throw around pattern terms or pride ourselves on using a certain type of framework because it implements a pattern rather than actually know why a pattern may be beneficial or not, and why and when it’s a useful thing.
Maybe that’s just me.
But one thing that’s easy to observe, at least within the context of WordPress development, is that we’re not really big on patterns. Sure, we use the event-driven pattern that WordPress provides because we have to, and there are some people who look at Inversion of Control, Dependency Injection, and all of those other terms that sound more complicated than the ideas they represent (no, I’m not opinionated about that at all), but there’s not a lot of work involving patterns.
Instead, when it comes to working with object-oriented code, I think we see god-classes more than we see anything else.
That’s no good.
And there’s a lot that could be said about this. We could talk about the SOLID principles, we could talk about coupling and cohesion, or we could continue to ramble on about all of these things without taking a deeper look at something that’s actually applicable.
Design Patterns for Refactoring: The Façade Pattern
Everyone loves to have a single, prescribed solution for how to solve a problem. That’s why we love algorithms (and it’s why we love copy and paste more, isn’t it?), design patterns, plugins, and so on.
But there are actual strategies that we can follow in order to thoughtfully go about refactoring our code and improving the internal architecture. And though there’s no a single right way to go about doing something, I think that the Façade Pattern can be incredibly useful in working through a refactoring.
It Gets Worse Before It Gets Better
Before actually looking at the pattern, assume the following:
- You have n-number of classes, say, 5 classes, each of which are responsible for something else.
- These classes have high coupling, low cohesion, and could stand to be completely rewritten.
- The degree to which they depend on one another is so high that it’s hard to actually begin breaking things apart without breaking the program.
So how does the whole facade pattern thing fit into this? Think of it this way: The facade is an intermediary class that sits in between code that calls into the highly-coupled classes and then redirects all incoming requests to said classes, then directs all responses from said classes back to the caller.
So here’s a simple diagram straight form Wikipedia on the Façade:
It feels a bit counterintuitive at first because we’re basically giving one class all of the knowledge that exists in the other classes and then having it serve as a means by which data is passed and returned to the calling classes.
But I like to think of it this way: Let’s say this is your code sitting with the Façade (where Superman is the façade):
So what should the work look like once we’re done and the proverbial Superman has been removed from the situation?
Not bad, right?
Is This Not an Anti-Pattern?
I mean, is the façade in an of itself a god-class? In a way, yes, but the purpose that it serves is meant completely defy the anti-patterns that exist within the code itself.
During the time that the façade is sitting as an intermediary, we are free to begin breaking about the poorly designed classes that sit behind it into something that’s far more well designed. As we continue to make these improvements, the façade can then handle communication between the callers and the new class until eventually the callers can be made aware of the new class.
By the end of the refactoring, we’re able to remove the façade and then have the callers use the newly refactored classes (which should obviously yield a better design and easier maintenance over time).
Worth an Example?
Despite the fact that I’m more interested in showing a practical way to go about doing this – even if it’s using somewhat of a contrived example – it’s a harder topic to cover in a single post. If this is something you’d like to see covered in, say, a series of posts, then let me know in the comments and it’s something that I’ll look into doing.
If not, no big deal. Hopefully the post has given enough information and tips for you to research some of these strategies on your own so you can take that big ball of mud and making it something much nicer than what it currently is.
Those who use the product may not necessarily notice any of the changes, but those who are responsible for maintaining the project moving forward will definitely appreciate the de-coupling, greater cohesion, and so on.
Leave a Reply
You must be logged in to post a comment.