Mind the specifications
Mind the spec
The first month of the year has gone by. I still feel like the year hasn’t started. For some reason, everything has been very slow-moving lately at work. Or so it feels, perhaps I’m no longer in the right rooms?
For the past few months, between the end of last year and this year, I’ve been deep into the weeds of gathering all the existing API specifications available in my organization. Having a heterogeneous set of APIs altogether puts a lot of the organization’s “personality” into perspective.
Collecting these API specifications has been a journey and showed me the lack of guidance and standardization over the years. By reading the auto-generated specifications, you start noticing the personalities of the different teams that built the APIs.
I like being able to recognize the “ubiquitous language” from the domain and being able to see the seams. But also how it evolved organically, meaning that the popular cases are effectively visible, but once you stray away from that, you’ll start noticing the inconsistencies or disconnect between teams.
APIs are a product in themselves, even if the teams don’t think about them that way. Unintentionally growing an API makes it harder to evolve and analyze and use them to report facts about your organization.
In a sufficiently large organization, there’s probably an API program, a directory, or a methodology by which every API specification gets reviewed, approved, etc.
Teams (and orgs) should not go about their APIs unintentionally; over time, you’ll end up maintaining weird or complex behaviors, creating corner case after corner case, or worse, keep putting out significant versions of your API to the demise of your consumers.
APIs sometimes are forever, and the more time passes and consumers you acquire, the more Hyrum’s Law will prevent you from deprecating that field, or making that operation asynchronous, changing that error code to another one (e.g., a “more accurate” one).
While developers like to generate or automate many things, I feel that with the spec, they’re doing a disservice to themselves, tying the implementation and working the documentation from that.
This scenario generally creates a tight coupling between the API and its implementation. In the worst cases I’ve seen, some API responses effectively mirror the DB structure.
I prefer APIs to live by themselves, allowing them to evolve at their own pace without the restrictions imposed by the current implementation. Generating their artifacts will involve more work as these need to be plugged into your service and consumer (if you create clients).
Given the relatively small number of APIs I oversee, I have them all under a mono repository. The build job lints them, reports missing fields or expected patterns for responses, errors, etc.
My current experiment generates artifacts (i.e., libraries) from these specifications for developers to create services or mocks. We can generate statistics about each of the capabilities exposed from this repository.
APIs should be treated as a product of your team, organization, and business. They should have their lifecycle well defined, as well as rules and guidance to create the best with the current knowledge available and think about the future.
Happy coding!
Interesting Links
- Hyrum’s Law: What It Means for API Design and Management
- The Allison Keyboard by Alexotos
- Joe Beda on complexity
website | twitter | github | linkedin | mastodon | among others