All about OOPS-WP, a small programming library for WordPress.

This past Monday, I once again had the esteemed honor to participate in our monthly 5 for the Future day at WebDevStudios, a time when our entire team gets to shift our focus away from client work to instead work on open-source, personal, or internal projects about which we’re passionate.

My most recent personal project has been a new WordPress plugin called Into the Void, which I eventually intend to use an alternative to Twitter. Into the Void registers a private post type and a set of REST API routes for posting and receiving shouts. Not satisfied with the idea of using WordPress as my main method of content entry, my goal for Into the Void is to develop a companion iOS app so I can post microupdates to this site from my phone. Of course, that means I need to learn Swift development, and as part of that effort, two weeks ago I signed up for a subscription to raywenderlich.com and have been working through the tutorial series there. If you’re interested in app development, I highly recommend this resource – check it out!

Ultimately, on Monday I decided that my little iOS microblogging + WordPress platform wasn’t in the true spirt of 5 for the Future, so I instead spent time documenting and releasing version 0.2.0 of one of my other passion projects that I mentioned in my last blog post (and the basis for some of my WordCamp presentation submissions this year), OOPS-WP.

What is OOPS-WP?

As the GitHub description so succinctly states, OOPS-WP is “a collection of abstract classes, interfaces, and traits to promote object-oriented programming practices in WordPress.” I started developing this library awhile back when I realized I was setting up a brand new Hookable interface for every project I worked on, because I’d established a particular approach to scaffolding my projects, and I wanted my IDE to understand that the objects my plugin was using had a register_hooks method. Over time, I noticed other design patterns that I followed from project to project, and figured it’d be useful to not only create a collection of abstract classes I could pull into a project to speed up my own workflows, but figured others might get some utility out of it as well.

The first release of OOPS-WP came with a handful of interfaces – the aforementioned Hookable, as well as Registerable, and Runnable – and a couple of abstract classes I found useful: ServiceRegistrar, Service, PostType, and EditorBlock, the last of which was a result of my Block Study exploration in January as I continue to wrestle with learning how to create Gutenberg blocks in WordPress.

In release 0.2.0, I added new structural types for Plugin (itself just an extension of the ServiceRegistrar class, in an effort to address some feedback that the terminology might be difficult to grok for beginners to object-oriented programming), Taxonomy (which now extends the same abstract ContentType that PostType does), and Shortcode. Because shortcodes are always rendered in WordPress, I also created a new Renderable interface, to ensure that a render method is always available on an object.

Having this library available from project to project has greatly streamlined the amount of scaffolding I’ve needed to do to get a new plugin up and running, and I’m looking forward to adding new object types in the future.

How do I use it?

The real beauty of OOPS-WP is that nobody has to use it. That said, the concepts behind the library are not much different from other WordPress object constructs you might already use. If you’ve ever created a new API route in WordPress, you’ve likely created your own class that extends WP_REST_Controller; if you’ve created a widget, then you’ve extended WP_Widget.

What WordPress lacks right now due to its support of PHP 5.2 (which is coincidentally going away once WordPress 5.2 is released later this month) are some language features that have been introduced since PHP 5.2 was first released over 12 years ago. That, mercifully, is finally changing this month, so we can maybe start to have nice things. Can you believe we’re almost celebrating the 10th anniversary since namespaces were introduced to PHP, but not a single file in WordPress core yet has one? Perhaps now as a community we can finally gain some traction toward establishing some SOLID principles in the codebase and make the application as rock-solid behind the scenes as it is nice to look at.

SOLID is what I’m hoping to achieve with OOPS-WP. I strive to create single-purpose classes with clearly-defined structures, to use dependency injection, and to type-hint against an interface so that when my application needs change in the future, I can do so with as minimal effort as possible. Like all of us, I’m still learning every day about what that means in my own work, but my aim with this library is to help make it so we can all learn together in this brave new world of still-outdated PHP. :)

For real, how do I use it?

Okay, okay, I digress…

A Hookable Example

Let’s say you want to get your feet wet with OOPS-WP. You want to create a new class that contains some code for a plugin or theme. That plugin or theme is going to have to register some hooks, right? Let’s make it happen!

<?php
namespace JMichaelWard\MyAmazingPlugin;

use WebDevStudios\OopsWP\Utility\Hookable;

/**
* Class to power my amazing new plugin!
*
* @author Jeremy Ward
*/
class MyAmazingPlugin implements Hookable {
    /**
    * All the hooks my object sets up, right in one place!
    */
    public function register_hooks() {
        // Put your hooks here!
        add_action( 'init', [ $this, 'do_some_callback' ] );
    }

    /**
    * My init callback.
    */
    public function do_some_callback() {
        // Some thing you want to do on init.
    }
}

Then, when you go to create that object, you know you can call the register_hooks method because the MyAmazingPlugin class indicates “you signed a contract that says you have to have one!”.

<?php
/**
* Plugin Name: My Amazing Plugin
* Author: Jeremy Ward
*/

use JMichaelWard\MyAmazingPlugin\MyAmazingPlugin;

$plugin = new MyAmazingPlugin();
$plugin->register_hooks();

That’s simple enough, but perhaps there may be some things you need to do on the object before the hooks are called. Object __construct methods should only be used for object initialization, otherwise writing unit tests can be difficult. But also, you want to keep your plugin file clean and only call the methods that you need to get the whole process started. What if we added in the Runnable interface?

A Runnable Example

<?php
namespace JMichaelWard\MyAmazingPlugin;

use WebDevStudios\OopsWP\Utility\Hookable;
use WebDevStudios\OopsWP\Utility\Runnable;

/**
* Class to power my amazing new plugin!
*
* @author Jeremy Ward
*/
class MyAmazingPlugin implements Hookable, Runnable {
    /**
    * Run my plugin.
    */
    public function run() {
        // Your custom logic could go here before you register hooks.
        $this->register_hooks();
    }

    /**
    * All the hooks my object sets up, right in one place!
    */
    public function register_hooks() {
        // Put your hooks here!
        add_action( 'init', [ $this, 'do_some_callback' ] );
    }

    /**
    * My init callback.
    */
    public function do_some_callback() {
        // Some thing you want to do on init.
    }
}

The plugin file only has to change a little:

<?php
/**
* Plugin Name: My Amazing Plugin
* Author: Jeremy Ward
*/

use JMichaelWard\MyAmazingPlugin\MyAmazingPlugin;

$plugin = new MyAmazingPlugin();
$plugin->run();

Or we can do it one better and wrap that in a hook of itself, so that the plugin only runs after all the plugins are loaded:

<?php
/**
* Plugin Name: My Amazing Plugin
* Author: Jeremy Ward
*/

use JMichaelWard\MyAmazingPlugin\MyAmazingPlugin;

add_action( 'plugins_loaded', [ new MyAmazingPlugin(), 'run' ] );

The Service class b/w what’s a ‘registrar’?

Now that you’ve got a main plugin class, chances are you don’t want to put all of the plugin logic in that one file, because you know quite well that it breaks the S in SOLID – single responsibility principle – or in other words, a class should do only one thing and do it well. You also write a lot of plugins and themes and don’t want to have to remember to write that full set of implements keywords every time you make a new plugin. What you need is some kind of way to differentiate the responsibilities of your plugin – creating a standalone part of the plugin that other parts of it might use. You might think of each of these features as a component or Service, and the object that creates those Service objects is the ServiceRegistrar.

Good news! The ServiceRegistrar class already implements the Runnable method, and the Service class implements both Hookable and Runnable. So, if you wanted to set up those different features, your plugin class might now look like this:

<?php
namespace JMichaelWard\MyAmazingPlugin;

use WebDevStudios\OopsWP\Structure\ServiceRegistrar;

/**
* Class to power my amazing new plugin!
*
* @author Jeremy Ward
*/
class MyAmazingPlugin extends ServiceRegistrar {
    /**
    * My plugin services.
    *
    * @var array
    */
    protected $services = [
        ContentRegistrar::class,
        ApiRegistrar::class,
        Logger::class,
    ];
}

That’s it?!?

That’s it. You’ve now split your plugin into three distinct services – one to handle setting up your custom post types and taxonomies, one to handle setting up your custom REST API routes, and one to handle error logs.

A Service is just a part of your plugin or theme that’s responsible for something. Again, the S in SOLID.

A Registrar is just a fancy way of saying “something that registers something”.

With that new-found knowledge, what I can tell you now is that the Plugin class in OOPS-WP is just a ServiceRegistrar. But it’s set up with its own PluginInterface because we might decide upon some methods that we’ll need every single time in the future. So let’s make that change to the plugin:

<?php
namespace JMichaelWard\MyAmazingPlugin;

use WebDevStudios\OopsWP\Structure\Plugin\Plugin;

/**
* Class to power my amazing new plugin!
*
* @author Jeremy Ward
*/
class MyAmazingPlugin extends Plugin {

Now let’s take a look at an example ContentRegistrar service:

<?php
namespace JMichaelWard\MyAmazingPlugin;

use WebDevStudios\OopsWP\Structure\Service;

/**
* Class to set up my custom post types.
*
* @author Jeremy Ward
*/
class ContentRegistrar extends Service {
    /**
    * My post types
    */
    private $post_types = [
        BoardGames::class,
        Records::class,
    ];

    /**
    * Register hooks with WordPress.
    */
    public function register_hooks() {
        add_action( 'init', [ $this, 'register_post_types' ] );
    }

    /**
    * Register my post types.
    */
    public function register_post_types() {
        foreach ( $this->post_types as $post_type ) {
            $post_type->register();
        }
    }
}

There’s a bit more going on in the above Service, but it’s important to know three things:

  1. The Service class implements both Hookable and Runnable. The run method is defined in the class, and all it does is call the register_hooks method. It’s up to you as a developer to add that method to your class and define the hooks that you need.
  2. The register_post_types method is not part of the Service. It’s unique to this ContentRegistrar. You can add as much logic as you need to a Service – all it cares about is that you tell it what hooks you have, and that it has a run method that can be called by other objects.
  3. The post types that get registered by the register_post_types method all have a register method. That is by design – their classes all extend the PostType abstract class provided by OOPS-WP, and that PostType class implements the Registerable interface, which forces the PostType object to define that method.

Man.

I know. If you don’t write object-oriented coded on a day-to-day basis, it’s a lot to take in. It might seem like you’re creating a lot of files, too, but note that these are pretty rudimentary examples. The power of OOPS-WP is that you can apply any of the interfaces that the library provides to any of your objects. If you have a class that has a bunch of WordPress actions and filters in it, have it implement Hookable and then put them all in that function so future developers can easily glance at what your class does. If it needs to be triggered by another object to start off a process, implement Runnable so that you know it’ll have a run method.

The joy of using interfaces in WordPress is that we can define what classes need to look like in order to function properly. The joy of defining abstract classes is that we can re-use code to keep ourselves from having to write the same methods over and over again. OOPS-WP is not strongly opinionated; rather, it provides abstract blueprints for some common WordPress structures so you can get all the dumb stuff out of the way and get to writing your next amazing plugin or theme.

If this is your first time hearing about OOPS-WP, I hope you’ll install it on your next project and give it a try. If you’re familiar with it but just aren’t quite sure how it’s supposed to help you write better code, hopefully this article will help. If you love OOPS-WP and want to continue using it down the line on all your future projects, I hope you now have a better understanding about why some of the design decisions were made, and know that I hope to never negatively impact the code you extend from it.

Mostly, I hope we all learn something from this journey together into a new future for WordPress. I’m glad we can have nice things in our open-source plugins and themes, and not just custom client projects, and I’m looking forward to seeing where the next few years will take us.

Onward!

Life… life finds a way.

Well, here we go! It’s already mid-March – how am I doing on all those goals I set back at the beginning of the year? I’d say uneven.

The good news is that I submitted a pair of talks to both WordCamp Kent in June and WordCamp Sacramento in September. In my goals, I outlined that I wanted to submit to a non-WordPress conference, but at the time, I’d completely forgotten about the fact that I still haven’t spoken out-of-town, an Unconference session about Xdebug at Pacific Northwest PHP several years ago notwithstanding. I actually updated that post after I initially published it to reflect that change.

I’ve given one of the two talks previously at WordCamp Minneapolis-St. Paul last year – Modernizing Your Development Workflow Using Composer. Composer is one of those utilities that I use in almost all of the work I do, and still, I’m learning more and more about it every week. I’m looking forward to potentially having the opportunity to share what I know with folks at those two conferences.

I also submitted a new talk, titled return new Presentation( ‘Software Architecture in a WordPress World’ );. At WebDevStudios, we recently released the 0.1.0 version a package I’ve been working on called OOPS-WP, which is a collection of interfaces, abstract classes, and traits intended to improve the consistency and speed of scaffolding common data structures needed for object-oriented programming based plugin and theme development. With WordPress’s recommended version of PHP set at 7.3, and minimum requirements finally updating from 5.2.4+ later this year, it’s high time to start having some serious conversations about modern development practices, including use of namespaces, SOLID application design, abstract data structures, and more.

Coincidentally, coinciding with my OOP talk submissions, Carl Alexander released his new book, Discover Object-Oriented Programming Using WordPress. Which is to say, I think we’re going to start seeing much more of this in regular conversation, and I’m happy to help contribute what I can toward broadening the OOP skillset of WordPress developers.

Another goal I’ve succeeded at in a big way is working away from home at least 1 day per month. One day in January, I worked out of the George Latimer Public Library in Downtown St. Paul, and in February, I booked a last-minute trip to Albuquerque, New Mexico, and split time between working in my hotel and the FreeRange Co-Working Space. Albuquerque is a great town, and it was fun to spend a week in another city while working remote. I’m hoping to do it again later this year.

Other, smaller progress: I’ve worked a bit on my Gutenberg education, going through tutorials on WordPress.org and creating the example blocks, versioning that work in my Block Study repository. I attended some WDS growth calls the first week in January, but haven’t been back yet – I love my morning time too much. I started building the 2019 infrastructure for this site in December, but haven’t gotten back to it. Maybe that’s less of a win, but it’s a good reminder that I set the groundwork for that to happen this year. And, of course, I’m writing this blog post, so that’s 1/12. I’ll count it as development-related. :)

The rest of the goals, well, I haven’t gotten there, but writing out all my successes is making me realize that I’ve accomplished quite a bit in the past 2+ months. Hopefully I can keep this momentum going and close out a few of the tasks and start making progress in others.

The big news, of course, and something that I think will help be a catalyst for further progress: I deactivated my Twitter account yesterday. I’ve been wanting to do it for a long time despite knowing I would miss the lack of direct connection to people I respect in not just the development community, but also the indirect connections between those doing good work in the social and political spheres. That said, I didn’t like the way I was personally responding to the firehose of bad news, and felt it was better for my well-being to end my association with the service. As a new goal, I’m looking to find better, healthier ways to connect with the people and communities I care about. Submitting talks, traveling, and attending my local meetups will be one such way to make those connections. If you are one of the few people who reads this infrequent blog, I hope to see you around.

RIP 2018, You Were Kind Of a Bust

Lesson learned – fail to set goals, and you only fail yourself. I think that was the biggest takeaway of 2018 for me.

Despite everything, I did achieve some things. I gave a talk at WordCamp Minneapolis-St. Paul focused on getting WordPress developers introduced to Composer. I worked on the first data migration project of my career. I participated in the WP-CLI overnight hack-a-thon, where I got to write my first-ever behavioral test in Behat. I got in the habit of regularly adding topics to our backend engineering scrum at WebDevStudios, so that we always had interesting and fruitful discussions. I went to a couple of PHP conferences and bonded with people in the community. I joined a group of board game designers, which sparked an interest in designing my own, which I did (I even got to play-test it a few times!).

These are things to feel good about, but they were driven by a smattering of whims and circumstances, rather than focus on a collection of goals. In 2018, I often let whatever was immediately in front of me dominate my attention, and I didn’t carve out time for intentional growth. In the few places I did set goals, I failed miserably, such as the 25 books I was supposedly going to read (I read about half of 3).

Back when I joined a full-blown team of designers and developers, I was introduced to SMART goals (Specific, Measurable, Achievable, Relevant, and Time-Bound). Here’s a nice overview of what they’re about:

What I like most about this time of year is the opportunity to detox from the pressures of the day-to-day, and instead spend time with considering what it is I want out of my professional and personal life. I’ve largely avoided it for the past couple of years, and more and more, I’m starting to feel the repercussions. A fresh year is a good time to re-evaluate, to set some goals for myself, and figure out a plan for how I want to spend my time.

Goals for 2019

Here’s a list of the areas I intend to work on the upcoming year. It’s absolutely certain I’ll accumulate some of those unintended feel-good achievements in 2019, but I need to focus my attention on the things I want to accomplish in order to feel like I’ve made progress by the time December 31st rolls around again.

Professional Goals

In the past year and a half, I’ve noticed my skillset in certain areas of engineering slowly diminishing. In particular, I want to work to retain my knowledge of HTML, CSS, and JavaScript, because as much as I love creating backend logic for applications, I’m hugely passionate about user experience, user interfaces, design, and the interactions between them. With my professional day-to-day involving my server-side engineering skills, I don’t get as many opportunities to practice these skills, so I need to set aside time to do them for myself. Some goals to help me achieve that include:

  • Revisiting my knowledge about Webpack and Gulp
  • Building a new theme for this website
  • Finishing my rewrite of my Scorekeeper app in React
  • Learning how to make custom Gutenberg blocks in WordPress

The “measurable” part of the above goals involves a deliverable: a new theme, a new app, a new block (or set of blocks). In fact, one way I might handle the Gutenberg piece is by reimplementing my Dudley patterns framework, which would give me a much better understanding on how blocks are created, and how to integrate the old with the new. The frontend tooling piece (Webpack/Gulp) is related, because I’ll need these tools in order to accomplish the other goals.

From a backend perspective, I’m looking to accomplish the following:

  • Learning to build a personal blog site using Craft
  • Creating a mechanism for automatically updating a Satis package server on git push
  • Creating a Docker container from scratch
  • Building custom tooling for WebDevStudios to support client project development (this is measurable, but it’s as much as I’ll get into it here)
  • Learning about CI tools, and integrating one into my personal workflow

Unrelated to computer skills (or not specifically to frontend/backend), on a professional level, I’m also looking forward to:

  • Publishing 12 web development-related blog posts
  • Applying to speak at an out-of-town WordPress conference
  • Applying to speak at a non-WordPress conference
  • Participating in WDS growth calls

Personal Goals

I’m still sorting this piece out, but there are a few things I want to achieve, and a few I want to get back into the habit of doing:

  • Reading 10 books
  • Finalizing the mechanics of my first board game design
  • Connecting with my local community by attending 12 meetups or conferences
  • Working away from home at least 1 day per month

It’s going to be difficult to achieve everything above. But, by writing it all out, I’m given not only something I can refer back to in order to check on my progress, but I can ask others to help hold me accountable for my own growth. I want to retain my hard-earned skills, grow into my career, help others along their paths, and make sure I’m a better person at this time next year than I am right now. Putting it all down in writing is that important first step.

JavaScript vs. the World

Before I started my backend developer position at WebDevStudios, I needed to buy a laptop. Having worked exclusively on Apple computers since 2004, I bought what was at the time the latest and “greatest” offering, the late 2016 model of the MacBook Pro with Touch Bar.

It has come to be perhaps my biggest regret; I have had nothing but problems with the machine. Occasionally glitchy graphics, power control issues when running dual 4k displays, and start-up/shutdown issues aside, my biggest complaint has to be the keyboard. It’s gotten so bad, in fact, that just yesterday, I finally brought my laptop in to have the keyboard replaced, only to notice beforehand that the “Service Battery” message was displaying.

The tech at the Genius Bar told me I’ll perhaps get the battery replaced for free as part of the keyboard replacement, because apparently the keyboard, battery, and track pad are all one component in these machines. I’ll find out in 7-10 days, but in the meantime, I’ve powered up the ol’ Raspberry Pi that I won as part of a contest at Midwest PHP a couple of years ago.

Adventures in Computing

I’m on vacation until after the new year, and going from a powerfully unreliable machine to a reliably non-powerful machine is a shift. In fact, before I remembered that I even owned this Raspberry Pi, tucked away in a drawer as it was, I thought I might just have to miss out on the coding exploration I’d so looked forward to as part of this vacation.

Last weekend, I spent upwards of 10+ hours scaffolding out a new infrastructure for this site, wrestling with server configurations, learning how to properly register a subdomain, setting up a package server, and otherwise doing the sorts of modern dev-ops-ish sorts of things I do every day at work. Of course, I didn’t intend to spend my whole vacation that way, but I did want to do enough of it that I’d feel satisfied that I learned something new over break. Taking my laptop in for repairs and being told it would be 7-10 days before I saw it again was something I dreaded, but knew I’d deal with. I do, after all, have other devices I can use to browse the web, but nothing else I can use to make it.

After I rediscovered my Raspberry Pi, I dug out all of the things I needed to make it work: a power supply, a wired keyboard and mouse, and an HDMI cable. My first job was to figure out how to uninstall the RetroPie app I’d installed awhile back to play the SNES games I own at my desk. Thankfully, the developers included an uninstall script that did the job, and before I knew it, I was back online browsing in…the Epiphany Web Browser.

Let’s say that this was a less than ideal experience.

Fast forward a couple of hours, and I’ve installed the following on this tiny computer with 28GB of storage and just 1GB of RAM:

  • Git
  • PHP
  • Nginx
  • MySQL
  • Chromium

I’ve also read tutorials that suggest that the IntelliJ editor is installable on Raspberry Pi, and I’m going to give that a go next.

Still, the most fascinating part of all of this is just how unusable the web has become.

Browser Testing

The model of Raspberry Pi I own ships with two web browsers: the aforementioned Epiphany Web Browser, and something called NetSurf. Epiphany is functional, but appears to run an outdated version of WebKit where most websites will tell you you must update it to access their site. I was able to login to Gmail only after watching it crash a handful of times, and even then, I received an HTML-only experience that dates back to a much simpler time. NetSurf is a non-starter, as it doesn’t seem to have an ECMAScript engine to speak of, and of course, the vast majority of the web requires JavaScript to function at all.

After installing Chromium, I was at least able to get a modern web experience, though even writing this post in the new WordPress editor, I’m starting to notice significant lag as more and more blocks come into play. Amazon-owned sites like The Washington Post and Amazon.com both crash after trying to load all of their assets, so clearly they’re not designed for everyone.

It’s been a bit of an eye-opening experience, browsing the modern web with a modern (for educational purposes), but underpowered machine. As a developer who works in the WordPress sphere, it’s especially interesting to think about how “democratizing publishing” has changed so drastically, to the point where it may in fact be much less democratized when factoring in JavaScript rendering engines and accessibility. I hope these are some of the problems we start tackling in 2019, and that we’ll remember that not everyone is viewing our work using the latest and greatest technologies.

Getting Back to the Basics

First things first: I’m writing this in the polarizing new Gutenberg editor that shipped with WordPress 5.0. My site, as little as I update it, is extremely barebones – no metaboxes, no shortcodes, no real extended WordPress functionality to speak of. As such, I knew I could reliably update it without issue, the dangers of updating without first backing up my database be damned. Since I’ve been doing primarily back-end development work for nearly the past two years, I admittedly haven’t had a lot of cause to pay much attention to the state of where Gutenberg was until it actually shipped. It’s finally here, though, and I’ll gladly admit: in just typing this initial paragraph, I’m already enjoying it immensely more than the old TinyMCE editor. 

I never really got into blogging. And though I don’t think this new editor experience is going to change that, one thing that is immediately evident to me with this new WordPress experience is that it’s possible that I might start to do it more. The old experience, clunky as it was even with this minimalist install, felt like a chore. The window was small, even in “distraction-free” mode, and as a result, I could never get the words out even when I felt like writing them. Gutenberg, with all of its flaws, does at least seem to give me some space, to try and get out of my way so I can have fewer distractions between whatever it is I want to say and actually saying it. Kudos to the WordPress Core team for seeing the project through despite the challenges and legitimate accessibility issues. I hope future releases will come more quickly and iteratively address the concerns people have about it, so that over time we can move forward with further enhancing the CMS overall. There are some really big projects underway, and I’m especially excited about the work that’s being done to finally get the minimum version bumped, hopefully to what will eventually be a currently-supported version of PHP.

A Holiday Break

This coming weekend marks the beginning of the first substantial amount of time off I’ve taken since Memorial Day week: 11 consecutive, uninterrupted days of relaxation, spending time with friends and family, exploring personal projects, playing (and designing) board games, and otherwise recharging my batteries after what has felt like a particularly challenging year for me. 

I switched over to full-time backend development upon switching employers in March last year, and in many ways it’s been super rewarding. I’ve learned how to write unit tests in PHP which, in turn, has completely changed my approach to writing object-oriented code. I’ve dug in with Docker, improved my command of the terminal (see what I did there?), and have advocated for the adoption of modern coding practices. More and more, I’m using Composer in my day-to-day work, and this year I gave a presentation about it at WordCamp Minneapolis-St. Paul. Some folks even gave me very nice feedback about it.

I got to do a bit of work-related travel late last year and early this year. I took some vacation time in July to attend a first-year PHP conference in Detroit, where I bonded with great folks in the PHP community that I like and respect a lot. In some ways, I’ve paid it forward, too, having great conversations with folks at and outside of work about my philosophy and approach to writing software for the web, and hopefully giving back as much as I’ve been given. I need to do more  – there’s always more to do – but having the opportunity to bond with others in my community was kind of one of the reasons I got into this thing to begin with. I love talking shop and taking the information I’ve learned and applying it to the next project. In some ways, though, it hasn’t panned out exactly as I’ve hoped.

A Knowledge Gap

I didn’t notice it right away, but ever so often, a problem arises with the presentation of a site that I’m working on. It seems that no matter how much you try to isolate yourself onto one side of the system, in an agency setting, you always get pulled back into the front-end. 

I actually like front-end technologies quite a bit. Back when I did full-stack development in my previous roles, I prided myself on writing clean, semantic markup, making my stylesheets as extensible and reusable as possible, and learning the ins-and-outs of the latest JavaScript techniques. Well, to the best of my ability, at least. I loved the UX aspect of front-end: learning to make elements accessible, making interactions delightful, and making my components reusable. I didn’t care for cross-browser testing and the million media queries required to harmonize a broad collection of components at various viewports.

Still, a lot of those skills are required of me to this day. And, I’m finding out more and more, since I don’t do them on a daily basis, that my knowledge about how to do them well is slipping. I need to dedicate some time during my break and in the new year to catch up. 

I guess that’s a long, roundabout way of saying that I’m glad Gutenberg is finally here. I’m glad I have a vacation coming up, where I’ll have a chance to apply everything I’ve learned about unit testing and behavioral testing and continuous integration and apply it to my personal projects, but also revisit the front-end aspects I don’t get to spend as much time with. 

Into 2019

This next year is going to involve a lot of growth and adaption. I need to learn to set aside time to more regularly exercise the skills I have so I don’t lose them. I need to learn how to adapt to the changes the WordPress project is throwing our way, so that I can continue to be in a position to serve my clients well. I need to keep finding ways to learn from my colleagues and friends in the community, as well as step up to share with others all that I have learned. And, most importantly, I need to continue to grow and adapt and change and learn as much as I can about software development in general: learning new frameworks, new techniques, and even new languages, so that I continue to feel the spark of excitement about this field that I had when I was brand new to the industry.

Four more days. Or, if I change my perspective just a little – tomorrow. It all starts tomorrow.