WYSIWYCE: What you see is what you can extend (in APIs)

What you see is what you can extend in APIs is the mantra I live by while writing my own APIs and when evaluating others’.

In my career as a web developer, I’ve interacted with probably hundreds of APIs, even written a fair few. Through all of that experience, I’ve come to one very specific conclusion about what constitutes “good” even “delightful” API design: Public access is key.

Public vs private APIs

The one marker, for me at least, that makes an API stand out is just how much the actual API code can be extended. That is, how much of the API is public and how much is private? And how much of the public vs private functionality is the API itself using?

Now, obviously, this discussion is heavily focused on FOSS APIs. This is largely because you can literally see and interact with the internals.

When examining public vs private, often the best approach is to consider the rules of the API itself. What constitutes “extendable” and what doesn’t? Does the core use a bunch of stuff hidden behind barriers or can you extend the same code core does? What is the core’s policy on backward compatibility?

Once you’ve set a public vs private baseline, then deciding openness is usually pretty simple. I’ve always felt that open and public should nearly always be preferred. It almost feels a little bit lazy for an API to bake in special goodies for itself then mark it private like it’s unfinished or something.

Examples in practice

We’re right in the middle of a big project at Sandhills right now. We’re building a new pro add-on for AffiliateWP called Affiliate Dashboard. It introduces a portal-like experience for affiliates, largely intended as a premium replacement for the standard core affiliate area.

The standard affiliate area API is template-based. Themes can override core templates, even introduce custom ones. It’s a very free and open extension environment but also very difficult to enforce high standards in the long term.

On the other hand, Affiliate Dashboard API is control-based. This means first- and third-party developers register display elements through the API and the add-on itself controls rendering them.

A dynamically-built Statistics view in Affiliate Dashboard.

At the time of writing, approximately 95% of the add-on dogfoods its own public APIs to render itself. We register views, sections, and controls the exact same way any other developer would. This is in part to prove a point that amazing things are possible, and in part to provide a living example for best practice.

For instance, want to see how we did something, maybe make your own version? The add-on source code is your best, first reference.

To be fair, there’s still a very small percentage of functionality we haven’t yet converted from its MVP form. By the time we ship the 1.0.0 stable in a few weeks, we’ll be entirely rendering on our own public APIs. Pretty sweet!

Delight and deliver

I like to think that we’ve designed the Affiliate Dashboard APIs with an intent to delight and deliver. Within the boundaries of what the API itself allows, what you can see is what you can extend.

Moreover, we’ve gone to great pains to make it feel consistent from control to control. For instance, some controls output very simple things, others do incredibly complex things under the hood like rendering a table using REST and Alpine JS.

The main point is that in trying to delight our extension community, we’ve forced ourselves to think simply when it comes to writing extensions:

  • All controls have a similar entry point
  • All controls use the same structure of attributes and arguments
  • Pretty much all controls support Alpine JS directives
  • All controls support a limited set of TailwindCSS classes

This consistency begs the question, “What is the fastest way to get developers from A to B and promise a really high quality result?

After some reflection, I think it’s to write a whole lot of excellent example code that oh hey, by the way, happens to run the add-on itself. Surprise!

Accessibility in Gutenberg is not a one-more feature

Joe Dolson, one of the WordPress Accessibility team reps posted a letter on make/accessibility this afternoon that really struck a chord with me. In detail, the letter outlines the Accessibility team's perceived shortcomings of Gutenberg. the new block editor set to ship in a few weeks with WordPress 5.0.

In reading the letter, I was struck by a key theme that Joe so eloquently expresses: making something technically accessible doesn't automatically make it a good experience for the users it serves to assist.

He went on to detail several issues, but the one that really stuck out to me had to do with using keyboard navigation to access a block's settings to change the font size of some selected text (emphasis his):

1. Press Ctrl + ` four times to locate the block settings.

2. Press tab five times to reach the font size selector. Discover the usage of the non-standard selector dropdown (normal selector: arrow key down to desired value, press enter to select, tab through rest of document. This selector: Enter  to expand dropdown, tab key to choose desired value, Enter to select that value, esc key twice to exit selector.)

3. Press tab six times to locate skip link back to selected block.

4. Press Enter  to activate the selected block.

5. Press tab thirteen times to reach the editable text of the block.

The above navigation scheme required 34 separate keyboard stops in order to change the font size of the selected text and return to the previous position, and is aided in efficiency by the tester’s prior knowledge of how to navigate the process. (Tested in Chrome and in Firefox using NVDA.)

We want to be clear that the above example is not comparable to the options available in the classic editor – there is no mechanism for increasing the font size of a paragraph in the existing editor.

Joe Dolson, Report on the Accessibility Status of Gutenberg

Even with the final concession that there is no comparable feature for changing the font size of a paragraph in the classic editor, I'm not sure this is considered an improvement. Maybe for users who don't have to do it with a keyboard? Yikes.

As a core developer, I'll admit that I've been relatively silent on Gutenberg and the 5.0 release until now.

I don't hate Gutenberg. In fact, the idea of Gutenberg is awesome, even inspiring. This post was written using Gutenberg. It represents the opportunity for a giant leap forward for content authoring in WordPress, and frankly I don't think anybody really disagrees with that assertion when it's just an idea.

When Gutenberg becomes more than an idea, however, when it's real and out there in world, that means something to a lot of people who look to WordPress to set the example. It sends a powerful message to 32% of the web: "this is the new standard."

Please let's not make the "new standard" be that we're willing to ship technically accessible but perhaps not entirely usable-for-all features; let's not define it as one that sacrifices standards core to the WordPress experience in the name of perceived expediency; let's not define it as the new default authoring experience for all users when not all users can use it well.

The WordPress philosophy states deadlines are not arbitrary. That's fair, that's something we live by. Core standards are not arbitrary either, and accessibility is a not a one-more feature.

Clawing back into the zone

For those of us who seem to work best “in the zone”, I don’t think we place enough emphasis on the effect our lifestyle choices can have on our work ethic.

I quit smoking two weeks ago, and I also stopped drinking caffeine before noon. Ever since, I’ve had trouble getting back into the “zone” where I used to thrive.

My work was starting to suffer.

Finally, late last week, I took a step I was dreading: I just stopped trying to code. It felt like a defeat, like I’d given too much credence to my previous lifestyle choices and allowed them to determine when I could or couldn’t effectively work.

I had to stop trying to find the excitement to work, and let the excitement find me.

The caffeine decision was less about health more about productivity. Turns out that drinking a jolt of caffeine in the morning causes an early afternoon crash … who knew? Now I just drink caffeine in the early afternoon so the crash comes after I’ve stopped working 😜

In some respects, I feel like I just needed to get out of my own head and let go of the “old way” of getting in the zone. I had to stop trying to find the excitement to work, and let the excitement find me.

The good news is that the excitement slowly started to creep back in over the weekend. Following my friend John Blackbourn’s lead, I started an Ideas repo on GitHub.

The concept is simple: document ideas you don’t have time to work on now, but want to write down out in the open so you can maybe work on them later. And if somebody else decides to come along and “take” an idea and run with it, that’s OK too!

Ultimately I wrote a few things down. Ideas for things like I’d like to learn, an old project I’d like to revive, a framework I’d like to explore. There’s only four ideas in there so far, but I feel like that’s a pretty good start.

I even took one of the ideas and pitched it to the Plugin-A-Palooza contest hosted the last few years by WordCamp Orange County. If that gets accepted, that might be just the fire I need to take it somewhere I always wanted to – delivery deadlines have a way of inspiring movement.

So here I am, two weeks out and still finding my way back “into the zone”. I don’t how well this is going to go, but I do feel like I’m on the right track.

It helps that I have a support network in family and friends, as well as in my WordPress family and with my awesome coworkers at Sandhills Development.

I’ll likely need some encouraging and understanding along the way, but I know that these recent choices are directly related to my health and wellness, so it’s worth the initial bumps along the way.


Featured photo by Doug Wilsen, and used with permission under CC.