You won't want to miss out on the world-class speakers at TNW Conference this year 🎟 Book your 2 for 1 tickets now! This offer ends on April 22 →

This article was published on June 10, 2020

Developing on WordPress? Avoid these 5 common pitfalls


Developing on WordPress? Avoid these 5 common pitfalls Image by: Unsplash

As developers, we make different types of mistakes at different points in our career. In WordPress development, in particular, we make different types of mistakes as our familiarity with the WordPress codebase grows.

Some years ago I heard Matt Mullenweg declare something to the effect that most people repeat their mistakes, smarter people learn from their mistakes, and the smartest people among us learn from the mistakes of others. I rather like this, and I’d add a corollary: Everyone makes mistakes, humble people share those mistakes in private, and the boldest among us write them down and publish them in a blog!

But there’s time for musing later. You’re reading this article because you want to hear about a train crash, and I’m the engineer. Without further preamble, join me in a look back in horror at the five most embarrassing mistakes I’ve made as a WordPress developer.

The time I updated a hacked version of WordPress core

I was just graduating from doing highly obscure CraigsList coding gigs, to actually working in a real live agency. I had arrived! I was nervous to be working from somewhere other than my couch, in something other than my pajamas. But even then, I generally knew WordPress Right from WordPress Doing It Wrong, and I found it pleasantly self-aggrandizing to boast about WordPress best practices, like never “hacking core.”

My first WordPress development task at this agency was to resume a stalled project—a rather complex one for my skill set at the time. It involved a lot of customizations to the WordPress registration and login flow. The previous developer was reputed to have achieved significant progress by simply editing the core wp-login files.

I knew this was unsustainable, so my first order of business was to install a backup/restore plugin and replace WordPress core with a freshly downloaded version. I was confident that nothing terribly impressive had been performed as of yet in the project, and that I’d be able to mimic the existing feature set via filters.

Whatever coding ability I may or may not have had at that point quickly became irrelevant, as my new employer was boiling mad. She did not understand the significance of “hacking core” and I was not mature enough to explain it in a digestible way. The only thing that temporarily cooled her brow was when I assured her I could revert via the backup/restore plugin I installed.

Can you guess where this is going?

That plugin, as fate would have it, only backed up the wp-content folder. Whatever WordPress hacks were in those core files were gone forever. I still remember my email back to her (she had long since banished me back to my home office by this point):

Guys, I can’t do the backup.

I really was prepared to complete her desired feature set via filters and actions, but she wouldn’t hear it. She fired me on the spot, threatened to sue me, and never paid me for two weeks of very hard work. I was so humiliated.

[Read: Here’s what every developer should know about design]

There are many (now obvious) things that I could have learned from this experience. The general lesson, that a backup is not a backup until it’s been rehearsed and confirmed, is a good one. But the one that stuck with me more is a specific lesson about how exactly to go about backups in WordPress—particularly with WordPress core.

I’ve learned to really cherish managed environments like WP-Engine, with a robust backup/restore system. Many boutique hosts have various command line tools and other developer-focused features for performing backups, but WP-Engine’s is my favorite. It’s quite fast unless you have a very large network. The UI is simple. It has a UI, period: Anyone who knows how to use WordPress can work with this. I.e., in contrast with some CLI approach that’s probably way faster, or some obscure thing buried in Plesk, my clients can use this, understand it, monitor it, and verify that I’m using it. I’m a big fan.

The time I dragged out entire platform into its sibling directory

I was still fairly new to the professional workplace and had always been a Windows person. However, my new job was at a Mac shop and I learned to love everything about it really quickly. Well, almost everything. I seemed to be having a lot of trouble with the “magic mouse.” I had a tendency to lose my Bluetooth connection, leading to accidental and often frightening drag-and-drop actions once it reconnected. More than that, I was just clumsy with a new fine motor skill.

Back in these days, our WordPress development flow still included deploying to production via FTP. It was not uncommon for me to spend entire workdays writing code, chatting, answering emails, generally whirling to and fro via my new magic mouse, with Cyberduck open to production on my desktop. Gosh does that sound bad! But that’s how it was.

One day our entire platform was just gone. Our sysadmin was quick to assume it was some kind of DDoS or something generally at his level. As for us developers, we trusted his instincts and assumed he’d figure it out soon enough.

Hours went by. The day came and went. Still down.

By the next morning, things were restored, and our CTO gently asked me to join her in the conference room. Our sysadmin had identified the problem. He pulled the FTP logs and observed that my user had moved our entire platform into a sibling directory. That is, wp-content had become nested under wp-includes.

I was crestfallen, but our CTO was great about it. She could see that I was generally a helpful and accountable employee, but she challenged me to go beyond mere contrition and come up with ways to prevent this from happening ever again. I found two really helpful things.

The first was to locate a CLI command to prevent Cyberduck from allowing remote-to-remote file movements at all. This was a good safety measure and we adopted it as a company policy immediately.

The second was that I took a keen interest in deploying via Git. Eventually, I wound up writing a WordPress plugin to weave our Bitbucket versioning into the normal wp-admin update flow. Ever since then, we’ve had almost no reason to even have FTP access to production. This plugin is one of my favorite professional achievements. Of course, an affinity for Git is a prerequisite for developers today.

The time I removed all front-end content via add_filter()

I really thought I had become pretty smart with my WordPress practices by this point. The request was to append a “badge” to posts of a certain category. For some reason I had it in mind that only noobs would add yet another conditional to a template file for something like this, so with great pride, I implemented the following filter:

add_filter( 'the_content', 'myprefix_add_a_badge' );
function myprefix_add_a_badge( $content ) {

    global $post;

    if( ! has_category( 'sponsored', $post )  ) { return false; }

    $out = $content . myprefix_get_badge();

    return $out;

}

See anything wrong with this? I tested it quickly in staging to confirm that the requisite posts got their badges applied. Then I deployed it and left work for the day. As you might guess, the universe exploded.

Specifically, the result was that posts without the badge were rendering on the front end with no content at all! Can you see why? The issue was that instead of returning $content in my guard condition, I was returning false. But really there are many layers of mistakes here.

Why was I content to only test that posts received a badge? Why did I not also test that other posts remained unharmed? Why was I deploying to production so late in the day? Why was it that our quality control consisted entirely of me clicking around a little bit and refreshing the page?

The answer to all of these questions can be summarized as maturity. It just simply takes a while to get sick of making these kinds of mistakes, before we’re moved to invest in things like visual regression testing and unit tests. This particular mistake was a straw, among hundreds, that eventually broke the camel’s back and led me to become very invested in phpUnit and xDebug. In turn, those tools have taught me about writing testable code, which has probably prevented more bugs than the tests themselves.

The time I divided by zero inside of an infinite loop

The client request was to reformat the WordPress blog post byline such that the date would read “XYZ ago” as opposed to “10 November, 2011.” I wasn’t exactly sure how to achieve this, but I was aware that it was a date format that seemed to be growing in popularity, and indeed Dr. Google provided me with a snippet very quickly. It worked on my local! It had a lot of math, in particular, a lot of division. I wasn’t exactly sure why it worked—there were a lot of nested loops, remainders, rounding, and such. But it was on Google and it seemed to work, and I was happy enough to deploy it to production.

About 30 minutes later, I got an unfriendly Skype from our sysadmin. Production was down. Dead in the water. He asked me if I’d been dividing by zero lately and I had no idea what he might be referring to. Here’s what happened.

Believe it or not, the unreadable “worked on my local” snippet I found, given a large enough sample size, was capable of some aberrant behavior. Supplied with some unfortunate combinations of days, hours, and minutes, the Rube Goldberg loops would occasionally attempt to divide a number by zero. Recall from high school math:

In ordinary arithmetic, the expression has no meaning, as there is no number which, when multiplied by 0, gives a (assuming a ≠ 0), and so division by zero is undefined. – Wikipedia

So what does this mean for computers? Usually just an error message in the logs, but in my case, it was worse: The math error was interfering with my loop logic, causing my nested loops to run without ever completing—an infinite loop leading to a white screen of death. And it gets worse! Because each iteration of the loop was writing an error for dividing by zero, the error log grew to fantastic proportions and began to hamper our file system. This had the effect of a DDoS attack, albeit an absurdly self-inflicted one.

The bad thing about this mistake was that it took down a high-traffic site. The good thing about this mistake is that it dramatically changed my approach to work. More than anything, I was ashamed by my willingness to implement without understanding. I vowed to never again paste in a snippet without making every possible effort to understand every line, even following up with the snippet author if necessary.

More than that, I vowed to never again ship code that was not highly readable to novice developers. I became obsessed with the WordPress coding standards, text editor extensions, inline commenting and docblocks, and even tabs versus spaces, that classic rite of passage! In sum, I decided to care more about how easy it was to read my code than how easy it was to write it. This rebellion against pasting without understanding led me to take a deep professional interest in managing third-party dependencies, a topic that’s fueled various writing and speaking opportunities for me over the ensuing decade.

I decided to care more about how easy it was to read my code, than how easy it was to write it.
Oh, and the really funny thing about this mistake? WordPress core has a one-liner solution for it.

The time I let a project spiral out of control

I had landed a really fascinating project. I was to be the technical lead and WordPress development engineer, and I’d have an Amazon AWS Lambda developer and a deep expert in JavaScript reporting to me. This was the first time I’d had multiple people reporting to me, and it was by far the most complex project I’d ever worked on. To even refer to it as a WordPress project was greatly understating the matter, but WordPress was the glue that held the entire thing together, so it made sense for me to act as the tech lead.

Because my primary role was typically to be strictly a technician, and also because I have an affinity for minimalism, it never occurred to me to implement something like Jira or Basecamp or any real platform for task management. Things proceeded rather well for the first iteration of the project. We were able to work on our own individual components, refer to the client spec document as our product roadmap, and just ping each other via Slack when we needed to couple things together.

The trouble began when we began to showcase progress to the client and implement his feedback. What started as a three-person team instantly felt it had been taken to a new order of magnitude: It was unclear who was responsible for which bit of feedback, what the status was of implementing that feedback, or really even who was talking to whom. We exceeded Gmail’s limit of 100 replies per thread several times!

Things began to get uncomfortable. I think the client felt like he had lost control of the project direction, and equally important, he felt like he had lost visibility of the project status. My Amazon developer mentioned one day, “I wonder if we should use Trello.”

Huh, I thought. Does a three-person team need a platform like that? Again, my usual tendency is to prefer fewer tools, less overhead, less complexity. But the project was already dragging us all into the dirt, so what was the harm in trying it?

I combed through all of our emails, all of our spec docs, all of our disparate comment threads, and mapped them all out on Trello boards. Immediately, the project resurrected itself from its digital tomb because we could communicate with far less mental overhead. Instead of searching for text in my email inbox or a mostly obsolete spec document, we had lovely boards, lists, and cards. It was easy to see the status of any feature, to incorporate feedback, and to dole out new tasks. It felt like we’d gradually gone blind, so slowly that we didn’t notice it, and then suddenly could see again.

Granted, the code didn’t write itself, it was still a very challenging project, and we still had to employ every ounce of our technical skill. But that’s sort of the point: Because we finally had an infrastructure for understanding the project, we were now free to apply our technical skill.

I’m happy to say that that project was completed to the client’s full satisfaction. Nowadays, I consider Trello or Jira to be a de facto requirement for teams of two or more.

Go forth and learn from the mistakes of others

Here’s one of the smartest things I heard taught during my time in the military: “It’s okay for lieutenants to make lieutenant mistakes and it’s okay for captains to make captain mistakes. What’s not okay is for captains to make lieutenant mistakes, or for lieutenants to make private mistakes.”

In other words, it’s okay to make the common mistakes that are a matter of course for your current level of responsibility. What’s more important is how you grow from them.

I hope that we as developers learn to be compassionate with others when they make mistakes, as hopefully others have been with us. I hope to remain curious and accountable when I make mistakes so that I continue to innovate past them. I hope to always be surrounded by an inspiring community of WordPress experts—people whose mistakes I can learn from and avoid making myself. And not least of all, I hope that others can learn from my experience, like the WordPress mistakes I’ve shared here.

The Toptal Engineering Blog is a hub for in-depth development tutorials and new technology announcements created by professional software engineers in the Toptal network. You can read the original piece written by Scott Fennell here. Follow the Toptal Design Blog on Twitter and LinkedIn.

Get the TNW newsletter

Get the most important tech news in your inbox each week.

Also tagged with