Hyrum's Law - Mon, May 2, 2022
The key point here is all behaviors. The behavior described in a contract (for example in an OpenAPI
specification) is in most cases incomplete. Even if you try to be as thorough as you can. One reason is that parts of a systems behavior is implicitly inherited from the programming language or dependencies. And you might not even be aware about it.
Consider the example given in the book Software Engineering at Google :
Hash Ordering. The order of elements in a hash-based set can not be guaranteed. But if your API returns an array of the elements of that set and the order is always the same, users may assume that the order of the elements follows a certain (implicit) behavior.
Another example would be runtime optimizations that lead to a performance increase API call processing. Users of the API might have sized their systems on a specific rate API calls have been processed so far. And the introduction of the performance optimization might lead to havoc because memory and queue sizes might be insufficient for the new processing speed. Even more subtile: The performance increase might just have been introduced by a regular dependency update of the system. Thus being totally opaque.
So how to deal with that in an environment where changes are introduced faster and faster ? API versioning and API deprecation should be common consideration during a software development lice cycle. Although it might not always prevent problems through implicit behavior changes.
It is not possible to describe all behavior of an API in the contract. But over time user will depend on that behavior. So changes to the system even though compliant with the explicit behavior described in the contract might cause problems for users.
API versioning and
API deprecation can help avoiding these kind of problems.