How (API) Languages Evolve
APIs are languages: they specify how providers and consumers of capabilities communicate. The things that can be “said” in an API conversation are determined by the expressivity of the involved language. Modern Web APIs always are composite languages, they combine a number of general-purpose Web concepts, and then layer domain concepts on top of it. An important aspect of API designs and their expressivity are the vocabularies that they support.
Language Design Patterns
The design of these building blocks follows certain design patterns. There is one design pattern that is very popular (and has proven to be very useful) in general-purpose Web concepts, but which so far does not see that much adoption in the domain-specific parts of API design.
This pattern is to use registries. Take for example HTTP and its concept of HTTP header fields. HTTP (in its various parts) defines a set of header fields. These form the core of “how to speak HTTP”. However, many other specifications define additional header fields, and there are currently close to 200 registered header fields (and many more that are used but never registered). What this means is that while HTTP defines the “grammar” of the “HTTP language” (header fields are one part of it), the vocabulary of usable HTTP header fields is an open and evolving set.
Registries are running the Interwebs
This design pattern is so common and successful, that IANA now manages well over 2000 individual protocol registries for a large set of protocols developed within IETF. In fact, just HTTP alone has a few of these registry-managed vocabularies associated with it, other popular ones include request methods and status codes.
In summary, for the Internet and the Web, it has become clear that separating API design into a stable (but extensible) foundation, and an evolvable vocabulary (that is managed in ways that seem appropriate), is a good design practice. (For the IETF side of things the draft about The Use of Registries may be an interesting read.)
API Problems which may benefit from Registries
In the general practice of API design, registries still are surprisingly uncommon. Problems that can be caused by ignoring this pattern include the following:
- If there is no extensibility, APIs can become outdated quickly when the vocabulary hardcoded into the API needs to be updated.
- If there is extensibility but no discoverability, then vocabularies can evolve, but there is no place where developers can look up the vocabulary that is currently in use.
- If extensibility is not part of the specification but managed through specification updates, unnecessary noise is created by specification updates that much effectively (and with less disruption of the API ecosystem) could be handled in registries.
How Registries Work
It seems clear that at least some API designs could benefit from splitting grammar and vocabulary. By following the Principles of Robust Extensibility (meaningful core, extension points, processing model), APIs can become extensible in an evolutionary way. By also managing the extension vocabulary in a registry, evolution can be harnessed in a way that is decided by the registry policy.
Using registries is not hard. In the end, a registry simply is a managed place where a vocabulary is managed, with some sort of management policy that is decided by those who create it. The main building blocks of running a registry are the following aspects.
Registries are intended for design-time usage. The idea is that at any point in time, developers (or managers of the API) can look at the registry and find out what the vocabulary looks like. To make this process more robust, it helps to have policies that guarantees that entries will never be removed, and entries will never change semantics (as detailed in The Use of Registries).
If that’s the case, then design-time usage effectively is a “snapshot” of the API vocabulary when a developer looks at it, and further evolution of it will not affect the developed component (but that is acceptable if the API follows the Principles of Robust Extensibility).
Designed for Humans
Registries are designed for humans. They are managed by humans through the registry management policy, and consumed by humans, often developers, who look at the registry when they want to understand the current status of a particular API vocabulary.
Developers may also consult the registry when they see that their component increasingly encounters a vocabulary term that it does not understand and support, but that seems to gain popularity. In this case, developers use the registry to find out about this new term, and they might consider updating their component to also support this new term.
In order to fulfill its role as being human-friendly, most registries have a very simple structure: They are a set of entries that associate a term with its documentation. In most cases, this is simply a link to whatever documentation may be available. It is the role of the registry policy to place certain requirements on the documentation, and this often ranges from the need for there being a formal and published specification, to very simple and informal entries in easy-to-use platforms such as wikis.
Managing the Evolution of Extensible Languages
The last important aspect of a registry is the appropriate language design. The effectiveness of registries is very much determined by the design of the language they are used for. We already mentioned the Principles of Robust Extensibility, which require that terms must be independent from each other, and that ignoring unknown terms must be a safe thing to do.
As mentioned above, another important aspect is the registry policy: what is the requirement for new terms to be accepted, and what kind of stability is built into the way how terms can be updated or retired. Getting the policy right is essential, or all the potential gains of using a registry are undermined by the way how it is managed.
API Design: A Long-Term Perspective
Of course, not all API design may need the longevity and open extensibility that registries can provide. On the other and, as organizations become more API-savvy and start building up API strategies and supporting infrastructure, becoming better at understanding registries and adding them to your general API design practice might be something to consider.
Personally, my goal for the next 6 months is design and implement a simple platform for registry management, so that API landscapes can take advantage of this design pattern more easily. The goal is to build something that
- can support any number of registries,
- makes it easy to add registries and registry entries,
- uses a simple GitHub PR-based workflow, and
- can be forked and deployed easily to setup and run registries in a variety of settings.
That certainly is an ambitious goal, but it may be the case that once there is an easy way to set up and run a registry, it may become much easier for API designers and managers of API landscapes to apply this pattern. My hope and goal is that this additional then helps to improve the quality of the API designs, and thus helps to make API landscapes more robust and successful.
(This post was originally published on my personal blog)