Hacker News new | ask | show | jobs
by rmattes 3452 days ago
What do you mean by risk? How would you quantify it?

As I understand it, all semver is trying to tell you is when backwards-compatible changes happen, and when backwards-incompatible changes happen.

If the project developer wants to add some sort of indication that "this package contains changes that are alpha quality, and may not respect semver for the next few releases" then that developer can append a pre-release identifer to the version, as described in the semver spec. Once that identifier goes away, the risk that a package violates semver should be gone, and you should be free to update based on the semver relation to the previous release.

Ultimately, it's up to the project to verify that their releases don't violate the semver spec by being diligent with respect to their public API. If you find that a project isn't disciplined in documenting API changes (semver or otherwise,) then coming upw ith new rules to convey the information they're already not conveying isn't going to help anything.

2 comments

Well, backwards-compatibility is sometimes a probability.

For example, a change in the public signature of a function to accept a wider class of arguments might be considered backwards-compatible since the previous calls to the function will still work.

But if your language has type inference, now the previous calls have to actually specify the type of their arguments since the type inference algorithm can no longer resolve all the types.

So you can break SOMEONE'S build by accepting more types of arguments. It will be a one line fix, but if that fix has to be made upstream...

That's an interesting point. If you're using a language that adds more rules to the API compatibility than the language that a module is released in, it's probably not possible to rely on semver in the general case. Unless the author is aware of those issues and versioning accordingly, any minor release could be breaking.
Even in the same language, how do you prove that your changes didn't break things like type inference? Any change to the signature of a function (even accepting MORE types than before) can potentially break someone's code.
If you can't definitively prove that a class of changes won't break things, then you probably have to treat that class of changes as breaking and version accordingly, no?
Risk is simply an integer expressing how likely the project is to work if you use the previous release. Anything else is left up to the project to determine what things get a specific amount of risk. Or another way of putting is that the only requirement is that the risk number be correlated to the probability of running into issues running that release over the previous. Risk can even go negative to signal that the previous release had a showstopping bug that was fixed and that the new release should be used in all cases over the previous.

Also, some of the risk calculation can be pushed down onto tooling and the community. As an example, if more than the normal amounts of issues are reported against a release, the risk for the release can be automatically increased without anyone needing to be diligent in updating it and things can get automatically rolled back if the change was found to be too risky.

Semver requires a project to be more diligent than many projects are willing/able to be, and requires all changes fit nicely into the semver categories. Too many changes don't fit neatly into semver, especially when libraries are used cross platform and in different programming languages. Say a project switches from GCC to Clang, semver has no official way to express that. Release.Risk can handle it by assigning a amount of risk to the update and pretty much any other unforeseen corner case too as it doesn't try and categorize the risk. Also different projects have different risk profiles which semver completely ignores the concept of (glibc is more risk adverse than the JS library of the day). Semver also doesn't indicate any difference between a new feature that is self contained or one that touches a core piece of code, the former is much less risky than the later.

So it sounds like you're trying to quantify the runtime stability of a library with the risk metric: e.g. if I update this package, what are the chances that the foobaz function I'm using in that package will start giving me the wrong answer, or start crashing with the inputs I'm providing. You're right that semver does not try to solve this problem: by design it is only concerned with how to quantify changes to a public API.

If there's a risk that a package's functionality could break between releases it can be signaled through other channels. For example, you can keep unstable code in an "experimental" module, or hide unstable functionality behind a compiler flag. The binary compatibility (ABI) of a compiled package can be signaled with a SOVERSION or with symbol versioning.

I guess I would hope that the packages I use that do publish a public API don't go changing the guts of the package in possibly unstable ways, at least not without lots of testing and maybe a few alpha/beta releases to let the experimental changes stabilize with early adopters. If I was using a library where core functionality was breaking every few releases for unclear reasons, I would argue that it's probably better to just find a more stable library to use than to put the effort into quantifying instability somehow.