Wordpress: a fractal of bad design

Everyone knows about WordPress, and everyone knows WordPress is just awful. If you happen to think WordPress is awesome, hopefully your mindset will change by the end of this post. I'll just state this now — I hate WordPress. I despise its popularity but I understand why it is so, I want to shoot myself when I look at the source code, and I try my hardest to avoid any WordPress related projects. But the worst problem of all is it breeds ignorance (e.g., "WordPress developers"), promotes backwards standards and implements inefficient design patterns.

Inspired by eevee's post on PHP: a fractal of bad design, this post will attempt to do the same about WordPress. Any point eevee made about PHP, double that for WordPress. I'll try my best not to bash everything, but it's really hard not to. I've literally revised this post 4 times to tone it down.

I've worked with WordPress through the years, even way back in 1.x days. I recently had to maintain a few 3.5 and 3.6 installs for my previous employer, as well as interact with their VIP service (but that's a whole topic in itself). I've written plugins, widgets, modified the admin, yadda yadda. I'd say I have a good grasp on WordPress as a whole, and that's why I'm writing this post. I always get asked by other developers why I hate WordPress, so here's a definite list of the largest problems with the WordPress codebase, but I'm also not the only one who thinks so.

Before I begin, I would like to state that popularity does not equate to quality. Stop using that as an excuse to use WordPress.

Please read the post before bashing me or trying to defend. If I can tell your comment was posted before reading it, I will delete it, else have at it!
Globals variables are good right?

No, they are bad and should rarely be used. WordPress uses them everywhere for everything; the loop for example. The problem with globals is that they are mutable, which permits them to be modified and overwritten, which in turn will cause problems in other unrelated areas of the application. Another issue is determining the original source location, as it's near impossible to deduce which part of the application created the variable nor what overwrote it during the interpretation cycle. I could easily disrupt the loop by writing the following code:

global $post;
$post = null;

And voilĂ , the whole application is useless. Honestly, I cannot wrap my head around the thought process on thinking this was a good idea. Globals (whether variable or state related) have a use case, WordPress obviously doesn't know which case that is.

Is database abstraction really necessary?

Yes, it definitely is. WordPress has no concept of models or entities (or very poor ones like WP_Post), nor does it use an ORM or ActiveRecord type of pattern. All database access is divided up into separate query objects, like WP_Query and WP_User_Query, all of which have insane amounts of inefficient logic to handle paging, filtering, sanitizing, relations, etc. To top it all off, each time a query is made it modifies a global object (refer to the point above), wtf? The codebase provides functions like query_posts() and get_posts(), all of which call WP_Query internally. Like honestly, why would a query need to be global?

function query_posts($query) {
	$GLOBALS['wp_query'] = new WP_Query();
	return $GLOBALS['wp_query']->query($query);
}

Database queries are used on a case by case basis, they shouldn't persist. Each query class and function may do something slightly different, but redundancy much? This problem would not exist if a proper DBAL was in place. WordPress does have a wpdb class that tries to mimic a DBAL, but falls short.

The biggest issue (in my opinion) with their system is that it doesn't allow for custom database tables. WordPress for some reason wants to store any and all data in their tables, most of which is handled through custom post types, meta tables, or options tables. One could create custom database tables through a series of actions and callbacks, but there would be no admin interface, how stupid is that? Furthermore, there is no direct database access since WordPress doesn't support an abstraction layer (this again?), so you're stuck with literal PDO and MySQL calls.

Throwing everything in a custom post type or a taxonomy is not the solution, it is the problem.
At least routing is done with mod_rewrite!

Using mod_rewrite isn't a bad thing, but modifying mod_rewrite rules through the PHP layer is. WordPress updates an .htaccess file anytime the core system or a plugin adds or modifies rewrite rules — only after you click a generate permalinks button within the admin (a source of many debugging headaches). Routing libraries like Horde, Symfony and even my own Titon have been a concept around for a very long time, so I'm not going to really delve into them. However, there's many issues with WordPress's routing system, too granular for me to get into, but most if not all of the issues would be solved by a decent PHP layered router.

All of the "necessary" functions like is_page(), is_single(), and is_category() would be obsolete as the router would handle all of the mapping, scoping, parameters, and arguments. For an idea on how bad rewriting is, just look at the docs.

What about the file and namespacing architecture?

I'm on the edge about this issue, seeing as how the WordPress codebase is quite old. Since WordPress was released 10 years ago (yeah, sadly), the concepts of MVC and proper data modeling weren't widely known or used, so the default PHP standard of laying out files was implemented. This primarily refers to themes in that each page is represented by a corresponding PHP file — index.php, archive.php, single.php, etc — instead of routing (point above) to a class instance that represents the state and behavior of a page. So for legacy reasons, I will leave this as a non-issue, but mention it anyways.

However, the rest of the codebase is poorly architect-ed. The first problem is that most functionality is handled through global functions (which is bad, point above) and not packaged into classes. Why things should be packaged into classes or namespaces is already a pretty common standard, so I won't get into that. To continue, WordPress has been slowly adding more classes with each version, like WP_Http and WP_Object_Cache, so kudos to them, but the organization of files and classes on the file system is still rather poor.

Every class and function can be found in wp-includes, which attempts to organize them into some random file based on their behavior, functionality, and scope, so at least they tried?

Well even with a poor file system, the templating works fine

Heh, templating in WordPress? What. This was the worst part of integrating any theme, by far. All I can do is face palm at the fact that WordPress has no templating system. But PHP itself is a templating language? Well yeah, but it's not utilized in a way where it can be considered one. There is no template hierarchy, no layouts, no wrappers, no re-usable elements (also called partials), no automatic escaping, no helper libraries, no compilation or caching (albeit a proper one), no proper data model, and the list goes on and on. I've seen too many projects where I would see the same few lines of code repeated over and over 30 times... when this problem could of been solved by a single re-usable template.

WordPress has been around for 10 years. Smarty has been around for 11 years. Twig has been around for 3 years. There's not a single excuse why a third-party library, or even a custom built library isn't part of WordPress core. The very fact that templates require get_header(), get_sidebar(), and get_footer() is pathetic.

The action and filter hooks seem pretty powerful

Yes, powerfully dangerous. Let's ignore the fact that actions and filters are nearly the same exact thing, just with different verbiage.

function add_action($tag, $function_to_add, $priority = 10, $accepted_args = 1) {
	return add_filter($tag, $function_to_add, $priority, $accepted_args);
}

Let's also ignore the fact that these are events (and should be called as such), or that the propagation cycle cannot be stopped. Even Symfony, Zend and my own Titon have a proper event handling system.

The major problem is that these hooks are used anywhere and everywhere, which allows every little part of WordPress to be altered or modified. Any part of the application, whether it be a plugin, a library, or user implemented, can set a hook that modifies data, alters logic, or causes a problem later on in the execution cycle. Another major problem is that arguments are filtered (refer to $accepted_args above) unless strictly defined otherwise. In what case would I not want all arguments? None. Both of these issues lead to a debugging nightmare.

The hook system would be used scarcely if WordPress was architect-ed correctly. Hooks shouldn't exist in this magnitude.

What about error handling?

Get this, instead of using the built-in PHP error and exception handling, WordPress wrote their own! Ridiculous right? Instead of throwing exceptions and allowing the developer to catch and handle it (like any sane application), WordPress returns (not throws) an instance of WP_Error — a class that implements messages and codes, you know, like an exception.

What's even more ridiculous is that some functions can toggle a flag that either returns the WP_Error or returns a falsey value instead (I'm looking at you wp_insert_post() and wp_update_post()). This feature is so terrible, it speaks for itself.

But plugins and themes are where the magic happens

Take everything I said above, and everything I will continue to say, and double that. That's what those are. With their awful and inconsistent file architecture, no consistency between each other, their abuse of actions and filters, their inefficient database access, their backwards standards, and overall shoddy code, plugins and themes are an even greater problem then WordPress itself. When a problem arises from either core or another plugin, they believe throwing another plugin at it will fix the issue. The fact that so many plugins exist for such little things, and how different themes are from each other, just shows how poorly written WordPress is to begin with.

Anything else?

I haven't written about everything that irks me yet, so I will summarize a few more points below. I'm positive there are many more issues, but these should suffice for now. Feel free to send me more and I will append them to this post.

  • Class Abstraction and Inheritance - Very poorly done or simply not done at all.
  • Debugging Tools - There are no WordPress specific debugging tools to solve the problems listed above. And before you say anything, the Debug Bar is not a tool; displaying environment data isn't debugging.
  • Backwards Standards - Instead of following the rest of the PHP world with PSR or PEAR standards, WordPress decided to write their own standard which is quite opposite.
  • Asset Handling - JavaScript and CSS is handled through some kind of queuing and packaging system. Yet in the end, the source is just littered with script blocks and link tags. No compression, no concatenation, no optimization.
  • Deprecated Code - WordPress triggers deprecation errors for outdated code. Either it should be exceptions or they should require developers to do a hard migration.
  • Echo vs Return - Functions should never echo code, it should always return. This isn't as bad as the WordPress 1.x days, but it's still on my list of issues.
  • Pseudo Cron Jobs - Instead of using actual cron jobs, WordPress implemented a PHP layered cron job system. Which basically saves callback references in the database and triggers them from the PHP request at certain events. Lol what?
  • Over-zealous Escaping - Let's throw escaping and filtering functions around everything!
  • Security & Uptime - My friends over at MediaTemple would disagree. Most of their support issues or server problems are WordPress related.
  • Option Autoloading - The "autoload" of wp_options for the core and all plugins is extremely inefficient and slow.
  • Data Storing - Throwing all post related data in wp_postmeta or non-post related data in wp_options. You'll eventually end up with MBs of data when in actuality it should be far less. Can become terribly slow to sort through and read from.
  • Featured Images - One can define multiple image sizes for the featured image. However, all of those sizes are generated regardless of which ones you want, with no way to choose.
  • Menus - Creating hierarchical menus work well enough. But trying to render the menus that veer from the original implementation is complicated. What is this terrible Walker class? Give me templates.
So what's the solution?

WordPress has dug themselves into a pretty big hole, one that's not possible to get out of unless they do a complete rewrite of the system. It's been 10 years, and honestly, I don't ever see that happening. They continue to shoot themselves in the foot by expanding the system outside the scope of a blog, ala trying to make it a CMS. So what are the alternatives?

Personally, I'm pretty excited for Ghost, a blogging platform built in Node.js. Besides using Node.js as the backend, they utilize Handlebars for templating, SQLite for database storing, NPM for packaging, and localization with Polyglot.js. Already 5 reasons why it would be better than WordPress.

However, here are a few systems that are currently available. Craft is a popular up and coming CMS powered by the Yii framework. Serendipity also seems to be a popular PHP powered alternative. MovableType if you don't mind using Perl instead of PHP. Or SquareSpace if you prefer using a service.

Secondly, how about learning more of the language you are developing in? Throw together a few Laravel bundles, Symfony bundles, Titon modules, or one of the many other PHP frameworks out there. Honestly, will someone do this already and wipe WordPress off the map?

Don't let WordPress breed you into an incompetent developer.

10 Comments

  • I did not read your entire post for the very reason I hate 'user-friendly' Wordpress. Unless you know something about the stuff you talk about in this post, you will not be able to solve the DAILY problems that a wordpress website presents you with.
    Bonnie Marie
  • +1

    Something worse than the ecosystem of shitehawks surrounding Wordpress is the common belief by agencies and individuals that its possible to build anything for nothing using a bazillion plugins. If you ever have to pick up a botched project like this you have my deepest sympathies.
  • Nice new site miles. good job : )

    Totally agree with all of this, but an alternative utility CMS for the kind of small- midsize client sites that is easy for clients to use with a decent set of plugins & themes is hard to find. WP isn't just momentum. They are doing well what a lot of people want. The problem is corporate clients ask for it for completely inappropriate projects (big budgets, long term scope, sensative client data etc) Do we try and patch it with things like: http://jarednova.github.io/timber/
    ? tempting, but like you have pointed out there is so much wrong with it. We prefer to use Silverstripe for anything that deserves a really robust solution and keep an eye out for something light & capable for smaller clients - maybe statamic for eg.
  • Any resources you'd care to point us toward to help us avoid making these same mistakes ourselves? A primer on the fundamentals of good code, for those of us who learned by doing.
    • A good place to start would be here: http://www.phptherightway.com

      The best way to learn to write good code is to look at other projects, mainly frameworks like Symfony, Zend, Composer, etc (not Wordpress). The fundamentals behind those projects extend outside of PHP itself and is used in other high level languages like Ruby and Java, so it's best to understand and follow it.

      I would also suggest learning about design patterns, since they are used extensively to solve everyday problems. http://en.wikipedia.org/wiki/Software_design_pattern
  • I love posts like these. The angry, unjustified ad nauseum rant works like a resume that says "Do not hire me".
    angrycoder
    • Angry and unjustified? Not at all, did you bother reading the post? You on the other hand sound exactly like that. Especially considering you hide your name and email.

      If anything, these "rants" keep me away from those awful WordPress related jobs. Which in itself is fantastic.
  • Hi there,

    +1

    Thanks for this post.

    Alas, this is a technical point of view... Even if it is totally true, the clients, yours, mine, don't bother with so precise stuffs. They want colors, sentences that they can understand, words that a communication agency would tell them... And that's the awful part : even if you tell them they are going to hit the wall, they won't ear that, or they won't understand that.

    But I second you in this noble way to educate people and to elevate them!
    I guess we will, at a given point, suffer from this Wordpress supremacy.
    • Can't disagree with that. I really hope something comes along (that is written properly) to overthrow Wordpress' reign that satisfies developers and clients.
  • This is a nice blog post. I've been thinking of writing a similar blog post, but I've been a bit lazy recently..

    I'm always annoyed the way I have to solve things in Wordpress.

    My additional points:
    - It's so easy to make Wordpress sites completely bloated. With all plugins/themes people recklessly install, it's easy to make it very unstable, dozens of queries are made that are not needed.. It's very wasteful.
    - I really dislike the way meta data is stored. PHP serialization always bothers me, especially because I have to manually change URLs when I change from staging/production environments. They should use json_encode in stead.
    - I'm still very annoyed with the echo vs return. Even in Wordpress 3.5
    - It's quite some work to setup a proper localhost / staging / production installation.

    I did a small attempt to make it bit more structured. I created a little framework for Wordpress that we use in almost all of the Wordpress sites we have to maintain at the company I work at. I included some View class with elements (partials) to make a little more WTFV style (Still can't call it MVC). Also included some debugging functions to make it a bit more easy to debug.

    The main issue why it's not redesigned is probably because there are so many themes and plugins, that it's almost impossible to change without making an entire community angry.

    Why we still work with it? Because clients still demand it.
    My own blog is changed to Octopress, I love it.