Live data from Hacker News

A strong commitment to backwards compatibility means keeping your mistakes

utcc.utoronto.ca

41–50 of 62 posts

Re: A strong commitment to backwards compatibility means keeping your mistakes

#41

Earlier quoted context omitted.

If it broke the exposed API, it should not be a minor. It doesn't matter if it's "by design" or not, people still rely on it and semver is how you communicate the breakage to them.

What if it counts as a bug fix?

It really depends on the bug? If it is a bug that causes your program to crash or return obviously invalid output then it's probably OK to fix it. But if the 'bug' does something useful that just happens to be undocumented or contradicts the documentation, then you need to be a lot more careful about 'fixing' it. Especially if it's clear that lots of people are relying on that bug as a feature.

Re: A strong commitment to backwards compatibility means keeping your mistakes

#42

Earlier quoted context omitted.

If it broke the exposed API, it should not be a minor. It doesn't matter if it's "by design" or not, people still rely on it and semver is how you communicate the breakage to them.

What if it counts as a bug fix?

I ran into this recently, I'm sure many others did too (I'm not the issue poster).

https://github.com/eventlet/eventlet/issues/702

https://github.com/benoitc/gunicorn/pull/2581

While the bug does seem pretty critical for websocket users, the patch-version-change ended up breaking any application that uses gunicorn with eventlet (even if you don't use websockets).

It feels slightly like my fault, because eventlet has been at v0.x.x for 9 years now. I used to be a bit hesitant about using anything that couldn't declare a version 1.0.0. I guess I've learned my lesson and just won't use any v0 library except in hobby projects now.

Re: A strong commitment to backwards compatibility means keeping your mistakes

#43

Earlier quoted context omitted.

https://medium.com/@xzyfer/why-node-sass-broke-your-code-and... What do you think of this example, where a library made a breaking, non-backwards compatible change, causing user code to throw fatal errors. They defended their point that this is only a minor version increment since the working user code was actually erroneously working and should have been throwing fatal errors the whole time.

If it broke the exposed API, it should not be a minor. It doesn't matter if it's "by design" or not, people still rely on it and semver is how you communicate the breakage to them.

Per hyrums law, this would mean that essentially all changes should result in a major version bump, which defeats the purpose.

Re: A strong commitment to backwards compatibility means keeping your mistakes

#44

Earlier quoted context omitted.

Python 2-3 is a great COUNTER example of what I'm saying. There was no intermediate release that could run both python2 and python3 code. It introduced new features AND removed the old ones all at once.

You could transform your 2.x code so that it would run on both 3.x python and also on recent 2.x python versions, using new features with appropriate `from __future__ import` statements; so in that regard the latest 2.x versions were those intermediate releases that could also run 'new style' code. I had a bunch of internal code that would run on both 2.x and 3.x python, and many libraries also did just that.

So why does the Python Wiki runs Python 2 with MoinMoin Wiki? You seem to imply it is easy and quick to rewrite software to match it to new versions, and resources for this are always available?

Re: A strong commitment to backwards compatibility means keeping your mistakes

#45
post #15
post #12

Earlier quoted context omitted.

Suppose you create an API that allows users to enter nonsensical data or do things that are very bad for performance. Later, you realize your mistake, create a new, improved version of your API, and deprecate the old API. However, as long as you keep the old API for backward compatibility, you will have to deal with nonsensical data and poor performance.

And not keeping the old API around incurs work, potentially a lot, for everyone using the thing - transitively. We've seen this with Python2->3 transition. If the new version isn't backwards compatible (requires non-trivial work to transition), what you've done isn't an upgrade: you've created a new product , and deprecated the old one. As we've seen from Google, people hate it when that happens (how many different e…

> And not keeping the old API around incurs work, potentially a lot, for everyone using the thing - transitively.

Not only that, but breaking backwards compatibility will cause dependency conflicts once a dependency graph is a bit larger, and this can easily completely stall transitioning of software to a new version.

Re: A strong commitment to backwards compatibility means keeping your mistakes

#46
post #2

IBM, on zSeries mainframes and z/OS, has even bigger commitment to backward compatibility than Microsoft. Yes, it might take a long time to fix some mistakes, but usually, you get another better API added that doesn't have the old flaws. Over time, system accrues a byzantine set of features. Unfortunately, end result of these policies is that nobody wants to develop for those systems anymore. So the (dharmic?) wheel…

> Unfortunately, end result of these policies is that nobody wants to develop for those systems anymore. Is that the main reason? I always assumed "I can't buy these machines for less than a year's salary" was the major difficulty onboarding.

> Is that the main reason?

I think it is mostly the effect of them being legacy systems. Old systems become legacy systems if they are developed further. They can be difficult to work with but the mere fact that the language or platform breaks compatibility does not make that platform any better.

Re: A strong commitment to backwards compatibility means keeping your mistakes

#47

Earlier quoted context omitted.

Most of what you touch on is covered by semantic versioning. ( https://semver.org ), and IMO should be mandatory reading by anyone in software development. It sort of looks like you are sort of aware of it, but maybe not entirely. What you called a minor version is typically called a "patch" version. So it goes. MAJOR.MINOR.PATCH Major version bump can change anything. Minor versions are generally safe to upgrade, bu…

I think GPs main point is not covered by semver at all - namely to not break anything out of the blue but have a transition period where API consumers can upgrade at their own leisure.

I do not know what GP is short for, apologies if I'm missing your point in my reply.

One, if not the most important part of semver is communicating the nature of the changes, and in particular, how that change affects the use.

I once used a library/tool that would detect vulnerabilities. The maintainers thought it would be a good idea to turn it in to a paid service, and a minor version upgrade caused it to fail silently due to lack of a token. When I noticed it by coincidence, I raised the issue of it not being communicated properly, and they said they had made every effort at raising awareness about the change through blog posts, twitter, etc. However, few people really subscribe or follow this kind of feeds. The change that came as an increment in minor version had IMO broken semantic versioning. If it instead had been followed, it would have communicated exactly that some care when upgrading was necessary, and allowed the API consumers to upgrade at their own leisure.

Re: A strong commitment to backwards compatibility means keeping your mistakes

#48

Earlier quoted context omitted.

Most of what you touch on is covered by semantic versioning. ( https://semver.org ), and IMO should be mandatory reading by anyone in software development. It sort of looks like you are sort of aware of it, but maybe not entirely. What you called a minor version is typically called a "patch" version. So it goes. MAJOR.MINOR.PATCH Major version bump can change anything. Minor versions are generally safe to upgrade, bu…

https://medium.com/@xzyfer/why-node-sass-broke-your-code-and... What do you think of this example, where a library made a breaking, non-backwards compatible change, causing user code to throw fatal errors. They defended their point that this is only a minor version increment since the working user code was actually erroneously working and should have been throwing fatal errors the whole time.

Versioning is always a little bit tricky. First of all, it depends what you are versioning. If it is an API (be that web-api or programmatic API through a public interface), then semantic versioning is exceedingly useful, and how to go about it is less ambiguous.

To address the issue you linked to, it really doesn't matter if it is a bug-fix or not. Semver 2.0 describes PATCH in the summary as

> PATCH version when you make backwards compatible bug fixes.

And the words backwards compatible are key. If it isn't, it doesn't matter that it fixes a bug or adds a breaking feature. If the code will break for your users unless they change their code, then you cannot fix it by bumping the PATCH version.

Now, semantic versioning isn't the end all be all. There are other versioning schemas that suit some developments. But, if there is a pretense of actually following semantic versioning, then the argument presented in defense really isn't relevant. Bumping the major version isn't something holy and beyond reproach. Just use it for what it is intended. Package systems very often rely on semver being followed. Does the new version break existing use? Then bump the major version. That's the responsible thing to do, and it should only be met with understanding.

To quote SemVer 2.0:

> 6. Patch version Z (x.y.Z | x > 0) MUST be incremented if only backwards compatible bug fixes are introduced. A bug fix is defined as an internal change that fixes incorrect behavior.

Re: A strong commitment to backwards compatibility means keeping your mistakes

#49

Earlier quoted context omitted.

The biggest problem I have with semver is that we don't have good enough tooling to reject minor or patch version bumps when major version bumps are actually warranted. I'm not sure it's possible to have that thorough of analysis in general. Semver is handy for understanding what the maintainer meant to do. I guess in a lot of circumstances that's not nothing.

> The biggest problem I have with semver is that we don't have good enough tooling to reject minor or patch version bumps when major version bumps are actually warranted. I'm not sure it's possible to have that thorough of analysis in general. The biggest problem with automated tooling is that there is a nontrivial subjective component to this. If you look at things strictly, any bug fix that changes externally obser…

If the change actually breaks existing use, then bumping the major version of every such release is *exactly* the purpose of SemVer.

One important note that is often overlooked, as it isn't part of the short SemVer summary, is that major version 0 is special. The rules for minor and patch versions do not apply, and anything can change at any time.

In other words, a project and library can explore its API freely and make as many wild changes as it pleases. Once it matures, it can be made 1.0.0, and the whole point of doing so is to communicate that the rules of major, minor and patch version bumps can be expected to be followed.

Re: A strong commitment to backwards compatibility means keeping your mistakes

#50
post #27

Earlier quoted context omitted.

Most of what you touch on is covered by semantic versioning. ( https://semver.org ), and IMO should be mandatory reading by anyone in software development. It sort of looks like you are sort of aware of it, but maybe not entirely. What you called a minor version is typically called a "patch" version. So it goes. MAJOR.MINOR.PATCH Major version bump can change anything. Minor versions are generally safe to upgrade, bu…

You have to define the notion of "backwards compatible" though, as this is the core of semver. To be strict, a bugfix is not backwards compatible. You explicitly change the behaviour of a function or interface. There's an interesting paper on checked semantic versioning [1] and you will get a new MAJOR version if you don't explicitly add the NOCOMPARE-pragma to a bugfix, as the prover (obviously) can not show the ori…

I think the underlying assumption here is that this is versioning for humans (and package managers). It isn't 100% ironclad and fool proof. It really only tries to make the job better/easier for those who rely on other libraries by baking in an educated answer to the following question:

> If I upgrade the library from X.Y.Z to A.B.C, what can I expect to have changed, and to what extent do I need to do anything after I make the upgrade to make my code work the same?

I don't find it interesting that, technically, any observed change to the library can potentially break code. If I use reflection to branch on number of methods available, a bump in minor version can introduce a method to the API, and thus break my code. Making an observation of this is one thing, naming it after one self is a tad on the egotistical side.

Other than that, I agree completely that the difficult part is defining what "backwards compatible" really means. However, to be clear, changing behavior is not the same as being backwards incompatible. I expect bugfixes to make my code function more correct and more reliably. I can reasonably expect minor versions to add functions or features that don't get in the way, and I can expect nothing from major version upgrades, so those will always need to be done with some extra care.

Post reply on HN