Net API Notes for 2021/09/08 - Issue 174 - Design Is A Process

Net API Notes is a regular, hand-curated digest of impactful news and analysis for busy API practitioners. Are you reading this on the web and not subscribed yet? Sign up today and be the first to get ad-free, actionable info delivered weekly to your inbox.

I had a version of the notes, and then a series of events crystalized something that had been disjointed in my mind. So I bumped those posts to next week for some pontificating. Let's get to it.

NOTES

BOOLEANS, DESIGN COMPLEXITY, AND REVIEWER OPINION IMPACT ON API GOVERNANCE

STRAT / DESIGN / DOC / DEV & TEST / DEPLOY / SECURITY / MONITOR / DISCOVERY

Arnaud Lauret published a blog post this week entitled "An API Design Review Is Based On Facts, Not Opinions". It immediately set my spider-sense tingling. I do readily agree with Arnaud that those privileged to provide feedback on a design should do so with rational, well-articulated intent. Comments akin to "This is a mess" or "this is uninspiring" aren't helpful. That kind of negative, unhelpful comment immediately nets a defensive response (I described this antagonistic phenomenon in a previous blog post).


I differ from Arnaud, however, in what issues "facts" cover. Arnaud describes five attributes of a successful API design:

  • Fulfill a Need
  • Be Easy to Understand
  • Be Easy to Use
  • Be Easily Evolvable
  • Conforms to Guidelines and Common Practices

These are similar to the gold standard for "Good API Design", defined clear back in 2007 by Google's Joshua Bloch. He detailed that a good API design is:

  • Easy to Learn
  • Easy to Use, Even Without Supplemental Documentation
  • Hard to Misuse
  • Easy to Read and Maintain Code that Uses It
  • Sufficiently Powerful to Satisfy Requirements
  • Easy to Evolve
  • Appropriate to the Audience

An API may be created differently than how the reviewer would have done it. Arnaud suggests that as long as a design factually fulfills the obligations of good design, above, "there's no need to argue".

On this we differ. Whether something is, for example, "easy to understand" is in the eye of the beholder. Someone immersed in the domain space may view a design's intuitiveness very differently than someone seeing it for the first time. These are subjective cases. And when we talk subjective, we're talking opinions, not facts.

For illustration, let's talk about Booleans.

BOOLEANS AND THE SLIPPERY DESIGN SLOPE

Evolvability is a key tenant of good API design. So how do Boolean properties inhibit it? As Hany Elemary points out in his post, "Why You Shouldn't Use Booleans in REST APIs", these true/false, on/off values create all sorts of corners a design can paint itself into.

Suppose we have an ecommerce API. Over time, some customers' accounts will be marked as inactive. In our API response for the customer resource, we might model the customer's account status as:

HTTPS Request: GET /customers/{123abc}
{
 ...
    "isActive": true,
 ...
}


A Boolean property is a natural place to start. Over time, however, our business use case grows up. Rather than an "active" and "inactive" state, our accounts could be "prospective", "delinquent", or "under-review", to name a few.

Breaking changes are bad, and we wish to remain consistent. As a result, we might continue the previous Boolean approach as our API ages, leading to:

HTTPS Request: GET /customers/{123abc}
{
 ...
    "isActive": false,
    "isProspective": true,
    "isDelinquent": false,
    "isUnderReview": false, 
 ...
}


The Booleans have begun springing up like acne on a teenager. We've lost some of our intuitiveness; can someone be "active" and also "under-review", or are these states mutually exclusive? We don't know without reading documentation. Further, while we avoided an immediate breaking change, client logic still needs to be programmed to use these additional fields.

If these states are mutually exclusive, we should have modeled a single "accountStatus" string property, clearly enumerating the values. Not mutually exclusive? Then use an object in your API description the can support multiple properties.

Suspecting that account status might grow beyond "active" and "inactive" is an opinion. No one can see the future; we can't say with factual certainty that the API will need to reflect five different account statuses a year from now. It would be great if we could. Sticking to just the facts ("you can't submit a body on a GET request", "don't invent your own authentication scheme") isn't value-adding activity in a design review. The weighty, impactful design decisions emerge after reconciling the differing perspectives (the different opinions), from a diverse set of stakeholders.

WHAT IS AND IS NOT COMPLEX IS... OPINIONATED

Earlier this year, Stephen Mizell shared an excellent series exploring design complexity. The gist, to oversimplify things, was that the more optional things were included in an API schema, the more complexity is introduced. This isn't just client and producer codebases with all the if/then/else statements; it is also the number of test suites to be created and maintained, the variety of data to be sandboxed, etc.

He cites an example from the Stripe API:

These are four properties, but they produce 81 different variations—each property can be an integer, undefined, or null. Four properties with three options means we calculate 3^4 to get 81. Adding another optional and nullable integer field would make it 3^5 or 243 variations.

Complexity is bad. What's worse, it grows at an exponential rate. So does that mean we should only create API designs without any optional fields? Of course not. What is the factual limit between a design that has just enough variability versus one that has too much complexity? Is it two optional properties? Ten? A dozen? There are different opinions on where that line needs to be drawn. And that is O.K.

Cue the software architects:

I've belabored the APIHandyman's point. He was trying to point out we shouldn't reject a design just because it isn't how we might have done it. That's laudable. To summarize, I'm adding on that we shouldn't demonize having architectural opinions. In fact, we should celebrate them. We'll never have enough information to make purely fact-driven designs. We'll forever be trying to design the best we can with imperfect information. Therefore, we must embrace our differing perspectives on what the future might hold. We should strengthen the means for sharing, comparing, and reconciling those. If we do that, we'll get to the desired place where API design is no longer a thing but a process.

MILESTONES

WRAPPING UP

I added a handful of new meetups to Net API Events. While meeting in person remains dicey due to new Covid-variants, several enterprising community leaders have online events. The upshot is now anyone with an internet connection can sample the conversation anywhere it is happening. And if there is an event missing? Let me know, and I'll add it.

Finally, thanks to my Patreons. You are the reasons this newsletter is free of advertising, information selling, or paywalls. Thank you.

Till next time, Matthew

@libel_vox and matthewreinbold.com

While I work at Postman, home of the kudos Slack channel that slaps, the opinions presented above are mine.

Subscribe to Net API Notes

Don’t miss out on the latest issues. Sign up now to get access to the library of members-only issues.
jamie@example.com
Subscribe