I'm gaining some insight into semver (Symantec versioning, aka 1.0.0) for the open source project didi.land
While attempting to understand smaller details for once, I am of course actually thinking about what it means to release software, a question that oddly I have managed to avoid in my job for many years, but as we are in a dev-ops world, it's time to dig in and try to understand.
3 little numbers which we might already be aware of, major.minor.patch as defined by the specifications, this is not a post about that, the semver spec does an ... Okayish job of that, perhaps il do a semver for humans post sometime?
Back on tangent, what the heck is a backwards compatible change, why do I want to go backwards? Can somebody spell it out for me.
My previous understanding of semver was, major, it's a brand new product, don't expect a piece of code to work with 1.0.0 or 0.0.0 my PlayStation 8 won't run disks from PlayStation 9?
Semver starts talking about API's and that is the most broad term, as a web developer, an API is a public set of endpoints 🤦♂️, but I can expect that on occasion it refers to library code yes, I'm struggling to contextualize it. API might also mean npm, given I replace the word API with npm, it kind of makes more sense.
Top comments (6)
Welcome to the restrictions of published software. All changes need to ensure they don't break existing installs. Meaning anyone who upgrades to the new won't have to change anything in their code. All results should be the same except for bug fixes. Here's an example.. you put a fix out on a library that was downloaded 5k times. You find out quickly that a single variable name change for a spelling error, broke hundreds of customers who were using that variable in some way. Now their project won't compile.
You can apply sem version to an application, in that context it is hard to define breaking change because you have to have clarity in what is your public interface. Consider adding a check box, all other components still exist, but now there location is positional different. If someone poorly automated interaction, you have introduced a breaking change.
This terminology is most useful with an API, something programs consume. Libraries expose an API so they are in the same boat.
To look at backwards compatibility, you look at what could have been developed against your public interface/contract, if all of those interactions will behave the same so that users will function the same without change.
Unfortunately bugs can be a public interface and that is why MS spends so much money recreating defects so older software still functions to this day.
Semantic versioning makes the most sense when applied to software that has a public API, which is why that's the very first clause of the definition: semver.org/#spec-item-1
But of course an API doesn't need to be a REST API. Libraries have APIs too; if a function that a user is expected to interface with changes in a way that would break their current code, then that's not backwards compatible.
For applications, the interfaces are mostly UI and not API - but perhaps changing the format of a config file, so configuration needs to be ported, would be a breaking change.
Given my software is a compiler backed and a cli or config based frontend, I suppose it's only the config based frontend I really need to worry about?
Basically, breaking changes (new required field or change of data type for a field in the request, complete behaviour change in processing on an endpoint, removing a field or changing its data type in a response) is a major / non backwards compatible change. Clients will have to make changes to how they consume the API before they can use this new version.
Minor is a non breaking change; new non-required request field, or loosening of a field from required to not required, new features that are off by default or only available on brand new endpoints, new optional response fields. Clients don’t have to change anything - the API will keep working regardless, but can use the new features or whatever if they want.
Patch is typically only for bug fixes or other small things that won’t break any client integrations and likely wont change any functionality but will fix functionality without breaking the API.
This example sort of makes most sense with something like a REST API, but if you think about it, the same concept works for something like a library too, except instead of calling GET /thing you call MyLibrary.thing() or whatever! So if you introduce a new parameter in thing()‘s signature which is mandatory, that’s a breaking change. But if it’s optional it’s a minor change - and if the signature stays the same but internally you fix something like tighten up security or speed up performance or whatever, that’s a patch.
Apologies for the lack of formatting - typing on my phone!! Hopefully it helps someone anyway :)
Check out this article which explains semantic versioning in detail.