I'd say nonsense. Backwards compatibility is better than any other option. From time to time you need to provide new, clean versions of old APIs and that's it. Things get deprecated (as in "best not to use this unless you are aware of the consequences". Aggregate over time, don't replace. Garbage collect when not reachable. This works for APIs as weel as for functional programming data structures. Clojure(script) app…
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.
A strong commitment to backwards compatibility means keeping your mistakes
21–30 of 62 posts
Re: A strong commitment to backwards compatibility means keeping your mistakes
#22Earlier 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…
Re: A strong commitment to backwards compatibility means keeping your mistakes
#23The reality is that you have to be sensible and balanced. You can't keep BROKEN functions "because people rely on them", but you can't suddenly make a minor release (e.g.: from 2.3.4 to 2.3.5) completely changing the semantic of a feature you expose. You need to: - Avoid changing APIs just for the sake of change. - Announce breaking changes. - Document how users are intended to migrate from your old API to the new on…
There are many projects that are relied on by thousands, but they keep pushing breaking changes on a regular basis without providing tangible improvements. This is especially true for tooling, frameworks etc. for web development.
Re: A strong commitment to backwards compatibility means keeping your mistakes
#24The reality is that you have to be sensible and balanced. You can't keep BROKEN functions "because people rely on them", but you can't suddenly make a minor release (e.g.: from 2.3.4 to 2.3.5) completely changing the semantic of a feature you expose. You need to: - Avoid changing APIs just for the sake of change. - Announce breaking changes. - Document how users are intended to migrate from your old API to the new on…
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, but will change the api in a backwards compatible way. Patch version updates make no change to the api.
One of the worst things to deal with is libraries for which maintainers have broken the semver contract.
Re: A strong commitment to backwards compatibility means keeping your mistakes
#25Earlier quoted context omitted.
> This gives consumers of the API plenty of time and margin to experiment with both and move on. It's not a silver bullet though, as we saw with the move to Python3. It annoyed people with large Python2 codebases, giving them the choice between: • Laboriously reworking their code to transition it to Python3 (a language with only limited advantages over Python2) • Using an unsupported language for a significant codeba…
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.
Right, but would that have helped? Transitioning a large codebase from Python2 to Python3 is a significant undertaking, there's no way around it.
As I understand it there are dedicated tools to help migrate Python code, but it's still no small thing if you're dealing with a large codebase. Perhaps it would have been helpful to have an interpreter that supported the union of both languages, but I don't see that this would have changed things from significantly costly down to no big deal. It would make the process more incremental, but it would still represent significant work. There are legitimate reasons people don't want to have to modify large stable codebases.
(To be clear, I haven't had to do this personally, but that seems to be the sentiment of people who have.)
C++, on the other hand, goes to considerable lengths to preserve backward compatibility, at the cost of accumulating complexity.
Re: A strong commitment to backwards compatibility means keeping your mistakes
#26The reality is that you have to be sensible and balanced. You can't keep BROKEN functions "because people rely on them", but you can't suddenly make a minor release (e.g.: from 2.3.4 to 2.3.5) completely changing the semantic of a feature you expose. You need to: - Avoid changing APIs just for the sake of change. - Announce breaking changes. - Document how users are intended to migrate from your old API to the new on…
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…
Binary compatibility is guaranteed as well so that an application compiled against 5.0.0 will dynamically link against 5.15.2 and run fine unless it relied on clear bugs.
There are exceptions for things like input method plugins, for which one needs to explicitly opt in to using internal API with build sysem flags. Without the opt-in, the corresponding private headers are not accessible.
Re: A strong commitment to backwards compatibility means keeping your mistakes
#27The reality is that you have to be sensible and balanced. You can't keep BROKEN functions "because people rely on them", but you can't suddenly make a minor release (e.g.: from 2.3.4 to 2.3.5) completely changing the semantic of a feature you expose. You need to: - Avoid changing APIs just for the sake of change. - Announce breaking changes. - Document how users are intended to migrate from your old API to the new on…
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…
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 original function and the bugfixed function to be equal (usually they are not for some input).
Backwards compatibility is hugely in the eye of the beholder (Hyrum's Law). So this is not a cut-and-dry issue.
Re: A strong commitment to backwards compatibility means keeping your mistakes
#28Earlier 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.
> There was no intermediate release that could run both python2 and python3 code. Right, but would that have helped? Transitioning a large codebase from Python2 to Python3 is a significant undertaking, there's no way around it. As I understand it there are dedicated tools to help migrate Python code, but it's still no small thing if you're dealing with a large codebase. Perhaps it would have been helpful to have an i…
The main issues with the upgrade is that:
1. Libraries needed to maintain both versions (or code compatible with both.
2. Projects couldn't upgrade until their dependencies did.
If Python 3 could run old code (for example you needed to write `import py3` at the top of a file to switch) then all projects could have updated their code in parallel, there would be no (or minimal) work to maintain support for old versions and everyone can update to py3 the day it came out. The workflow then looks like this:
1. Everyone updates to Py2.9 which supports the old features and the new features.
2. Everyone migrates their code to use the new features and remove deprecated features independently.
3. Py3 comes out and drops support for the old stuff.
1 is not trivial, but it is equivalent to any other time that you drop support for old versions, this happens regularly and isn't a huge event.
Compare that to the nasty wave of updating dependencies and requirement to continue supporting old versions, especially since the code to support multiple versions was fairly awkward for a lot of projects.
Re: A strong commitment to backwards compatibility means keeping your mistakes
#29Earlier 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.
> There was no intermediate release that could run both python2 and python3 code. Right, but would that have helped? Transitioning a large codebase from Python2 to Python3 is a significant undertaking, there's no way around it. As I understand it there are dedicated tools to help migrate Python code, but it's still no small thing if you're dealing with a large codebase. Perhaps it would have been helpful to have an i…
I got to experience both and the Ruby 2 migration was much smoother than the Python 3 one.
EDIT: To be clear, Ruby did not make it literally possible to run both 1.8 and 2.0 in the same code base but with just a few conditional statements and avoiding to use non-backported 2.0 features it was easy to write libraries which could run in both 1.8.6 and 1.9.
Re: A strong commitment to backwards compatibility means keeping your mistakes
#30Earlier 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.
> There was no intermediate release that could run both python2 and python3 code. Right, but would that have helped? Transitioning a large codebase from Python2 to Python3 is a significant undertaking, there's no way around it. As I understand it there are dedicated tools to help migrate Python code, but it's still no small thing if you're dealing with a large codebase. Perhaps it would have been helpful to have an i…
I haven't migrated from python2->3 however I've worked on projects in both. I think a "python2+3" version would have helped. With both APIs in place new code can be written the new way and old code can be migrated as it is touched. Having the ability to incrementally change code I think encourages the transition since you won't end up with a pile of broken code.