So as not to bury the lede, I'll get to my point: Semantic Versioning is a meta-API, and maintainers who are cavalier aboutviolating it can't be trusted to created stable contracts. I've lostpatience for breaking changes making their way to my code bases withoutthe maintainers incrementing the major version of their projects,especially in language ecosystems where Semantic Versioning isexpected, and in such cases I'm going to begin exploring alternativeoptions so I can ban such libraries from my projects—personal and professional—altogether.
What Even Is Semantic Versioning?
When developers adopt an external library into their code bases, theydo so knowing they will be bound in their use of the library by theapplication programming interface (API). In this sense, an API can beseen as a kind of contract between a library's maintainer and itsconsumers. If a maintainer makes frequent changes to a library's API,then that API is considered unstable. In that situation, consumerseither use the library anyway, accepting the risk that things willbreak as a result of a change in the library, or they avoid it.
Semantic Versioning seeks to ease this picture by embedding notions ofbackward- and forward- compatibility into software version numbers. Ifa library maintainer adheres to it, then consumers are able to upgradeto newer versions of the library (say, to pick up bug fixes) withoutfear of breaking changes, provided they aren't moving to a new, majorversion. In terms of backward- and forward-compatibility, SemanticVersioning creates an expectation that a given version of a library isforward-compatible with any future version up to the next, majorrelease. A library is also backward-compatible down to the mostrecent, minor release (beyond which point consumers' code _might_break if they are using newer library features).
There are several benefits to using Semantic Versioning. One benefitis that it becomes easy to codify dependency requirements intoautomated dependency tools. By assuming Semantic Versioning, usersof tools like NodeJS's npm
and Rust's cargo
are able tospecify dependency ranges rather than hard-coded versions. So if anew release of a library comes out, these tools are able to decideautomatically whether or not they can be used in a given project. Inother words, Semantic Versioning creates an opportunity for downstreamdevelopers to easily decide whether or not to upgrade to a new versionof a library, potentially picking up important bug fixes in theprocess.
Semantic Versioning As A Meta-API
Let me go back and unpack what I mean by calling Semantic Versioning ameta-API. As I said above, API's represent a sort of contract betweenlibrary maintainers and downstream consumers. Semantic Versioning thenrepresents a sort of contract-about-the-contract. It's an agreementregarding when and how the API will change. In a situation whereSemantic Versioning is the de facto norm, as it is in the languageecosystems mentioned above, a maintainer who chooses not to follow itis breaking this contract, creating the risk of needless downstreambreakage.
Because Semantic Versioning requires more contextual knowledge thanany compiler or tool chain can boast, the process is largely manual.This means mistakes happen, and breaking changes are introducedwithout rolling the major version number. Responsible maintainers willown such mistakes and issue bug fixes to correct them, implicitlyacknowledging that the meta-API is as important as the API itself.
Other maintainers aren't as interested as Semantic Versioning, andseem to view it as a sort of straight jacket they would rather breakfree of than a tool to promote software stability. These folks fightagainst their tool chains, and indeed their entire language ecosystems,arguing that Semantic Versioning doesn't work for them and they shouldbe free to work however they want. Some of their arguments are likelystronger than others, but none of them will be ultimately compelling.
Conclusion
If you work in a language ecosystem where Semantic Versioning is the_de facto_ norm, where violating it can wreak havoc downstream, thenplease play nice and follow its dictates. Instead of viewing it as astraight jacket, try to see it as an algorithm to determine what yournext release number should be. We should all like algorithms!
If you refuse to be persuaded, then understand I will will not workdownstream from you 1. I'll find a different upstream to work withbecause I cannot trust you to create a stable contract. Yourwillingness to conform to the meta-API is something I will take intoconsideration in the future before adopting a library into any projectthat I work on. I wish you well; I hope you have fun; I'll be sure togive you a wide berth.
- 1
-
I'll note here that I'm more forgiving in environments where Semantic Versioning is not a de facto norm.
Top comments (0)