WordCamp Kent Announcements and Additional Feel-good News

The One About Announcements

The cat’s finally out of the bag: I’m going to Ohio in June! My presentation, Modernizing Your Development Workflow Using Composer, has been accepted by the fine folks at WordCamp Kent. I’m looking forward to sharing my love for the best command line tool in PHP with the WordPress community, hanging out with old friends, and getting to make some new ones. The event is happening at the Kent State University Hotel & Conference Center on June 15th and 16th, and I have the honor of following my friend Steve Grunwell‘s talk about PHP namespaces, something I’m especially glad to see being discussed in the WordPress community now that the minimum requirements have finally been bumped to PHP 5.6.

I mentioned it briefly in my last update, but I’ve also submitted a pair of presentations to WordCamp US (the same Composer talk, and another about object-oriented programming concepts), as well as one to WordCamp Minneapolis-St. Paul about building custom apps with WordPress as a back-end. I’m still awaiting word on those (as well as WordCamp Sacramento), but if everything gets accepted, I’ll be spending quite a bit of time behind the podium this year!

The One About Feel-good News

OOPS-WP got a mention on the latest Post Status newsletter! We’ve been having a lot of discussions about the open issues on the repo at work, and two of my wonderful WDS colleagues dedicated some of their 5 for the Future time this month working on contributions for those tickets. My hope is that this library can help WordPress developers better understand object-oriented programming concepts like SOLID, namespacing, and package use, while also giving them experience on working with third-party libraries. It feels great to see something I created as a way to make my own work a little easier gain a little traction within the community, and I’m grateful to Post Status for sharing the excitement about it.

Celebrating Two Years at WebDevStudios

I thought this blog post today might be about a number of things I’ve been up to in the past month: how I submitted two talks to WordCamp US (and a separate new one to WordCamp Minneapolis-St. Paul), the multiple projects I’ve been working on (Into the Void, Board Game Collector, OOPS-WP, and a framework for migrating data into WordPress), a recap on this year’s great Minnebar unconference, monthly engineering-related calls I’ve been having with friends, and more. As I started writing about WDS, rather, it seemed evident to me that I wanted to reflect on my time here and what I’ve learned about myself since becoming a full-time backend engineer in 2017.

I celebrated my second anniversary with WebDevStudios back in late March. Officially, it’s the longest I’ve remained at a company since becoming a web developer back in 2013. Early in my career, I looked for new opportunities for variety of reasons: to earn more money, to find better kinship with colleagues, to continue to grow and be challenged, to work on interesting projects, and importantly, to feel that my voice is heard and that my contributions matter.

Each new position I took improved my quality of life in one way or another, and I’m thankful that I’ve never had a bad job. Room 34 gave me my start, providing me with lots of interesting projects and the chance to learn as much as I could about WordPress. I forged some of my best friendships while at Westwerk. 3five taught me how to work from home and to power through challenging projects.

Two weeks ago, 25 of my colleagues and I flew down to Georgia for WebDevStudios’s annual retreat, WDS Camp. It’s a week-long opportunity to spend time together in person, learn more about each other, and – to echo the theme of this year’s camp – collaborate, learn, and plan.

At WDS Camp, Brad Williams and Lisa Sabin-Wilson (our executive leadership, for those who don’t know them) gave their “State of WDS” presentation, where they reflected on the recent past and what’s in store for the company in the coming months. This year, as they discussed the contributions of our current and former colleagues, Brad expressed something that resonated with me, which was along the lines of “the good old days are right now.”

Those who know me know that I don’t always pause to reflect on all of the positives, and if anything, the frequency in which I moved on to new companies earlier in my engineering career was a symptom of this personal shortcoming. There is opportunity in patience, in perseverence, in kindness, in asking for help, in helping others, in showing gratitude, and in trusting others.

WebDevStudios has been a great place to work. I have friends here. I’ve been involved in projects that have led me to grow both as an engineer and as person. I’m learning to be more patient, accountable, and humble. Our company culture is outstanding, and the breadth of knowledge across our team continually reminds me just how much there still is to learn.

Agency work can be frustrating. Clients can be difficult, project scope can turn on a dime, and imposter syndrome can get in the way of trusting yourself enough to get that project to the finish line if you let it. These qualities aren’t unique to any one company. The culture of a company is what gets you over those hurdles, and that company’s ability to provide you with the things you value most will keep you there. It’s been an extraordinary run so far at WDS, and I’m looking forward to seeing what opportunities the future will bring us.

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.