3 ms·
The biggest issue with semver is that it encourages compatibility breakages under the false promise that increased major version number saves the users from the
by avodonosov 3y ago
The biggest issue with semver is that it encourages compatibility breakages under the false promise that increased major version number saves the users from the dependency hell.
https://github.com/semver/semver/issues/771 https://github.com/semver/semver/issues/771
SemVer is a product of Ruby community.
In 2000s Ruby library authors were breaking compatibility left and right, neglecting elementary compatibility practices. If you were working on an application, every time when you update dependencies, the application would break.
So (in 2011 ?) they came out with this "manifesto" (Why such a big name? This scheme of versioning was well established in linkers and sonames of Unix-like systems for decades - it goes back to at least 1987 paper "Shared Libraries in SunOS").
It's a good thing SemVer acknowledged finally that compatibility is a serious matter. Only that it's better to discourage compatibility breakages. An in cases when it's really needed (I agree such cases exists), there are things to take care of in addition to simply increasing major version num.
- lloeki 3y agoFrom your issue link: > Then commons-logging changes its API incompatibly and is released as commons-logging 2.0.1. Authentication adopts commons-logging 2.0.1 while other libraries still depend on 1.1.1 > Now my-application is broken, because the dependency tree includes two versions of commons-logging which share packages, class / functions names, and thus can not be loaded simultaneously. I absolutely don't see how this is a problem with semver, it is not the responsibility of semver to tell a language how packages should be isolated and loaded. That is a problem of a) the language and b) dependency resolution in the package manager. > SemVer is a product of Ruby community. Bundler, by design, does not allow the above, instead having a flat, consistent vision of dependencies. NPM though, allows that, allowing nested dependencies, by virtue of the ES6 module system importing to a variable in a lexical scope. Go also allows that, by virtue of its imports being scoped to a package (or file, I can't recall). Ruby has side-effectful load/require decoupled from the open class system - which is what bundler is designed around -, but can do that kind of isolation too! In fact, I've done it: https://github.com/lloeki/pak https://github.com/lloeki/pak Unless packages leak to globals each version is oblivious to the one next to it. Unless package dependents communicate with one another using objects from the packages they can happily live in their own little isolated world. Now if they do, then it's like hitting a HTTP /api/v1 with an HTTP /api/v2 client and somehow wishing things will work. Either the package (which should not leak globals / disallow cross-version communication) or the language (which should not allow leaking globals / detect incompatible communication). None of this is the responsibility of semver. In fact, semver would help the language provide tooling to detect that kind of "hey this instance is from foo-1.0 but you're trying to consume it in foo-2.0".
- avodonosov 3y ago> I absolutely don't see how this is a problem with semver, Strange to not see it. SemVer promises to solve dependency hell. In the example everyone correctly followed the sevmver and the app is broken by a dependency hell issue. > it is not the responsibility of semver to tell a language how packages should be isolated and loaded. That is a problem of a) the language and b) dependency resolution in the package manager. So semver only works for "good" languages? > Bundler, by design, does not allow the above, instead having a flat, consistent vision of dependencies. Ok, so what happens with the app when packages managed by Bundler get fragmented into sets depending on incompatible versions of sub-dependency (commons-logging 1.1.1 vs 2.0.1 as in the example)? Also note, even for languages and tooling supporting multiple library versions loaded side by side, there are scenarios where things break. For example, the "libc apocalypse" situation in Rust https://github.com/rust-lang/libc/issues/547 https://github.com/rust-lang/libc/issues/547 Here after the "libc" module released a major version, the definition for the `void` C type in two versions of the lib are considered by the compiler as two different types, resulting in breakages everywhere around the library ecosystem. There are also scenarios for dynamic languages / runtime errors. > None of this is the responsibility of semver. In fact, semver would help the language provide tooling to detect that kind of "hey this instance is from foo-1.0 but you're trying to consume it in foo-2.0". And what's next after it detected the dependency hell? It's too late and the person suffering is not in the position to fix it. You have to upgrade to "authentication 1.1.2" for security compliance, because the version 1.1.1 has known vulnerabilities. But that breaks the application, because the maintainer of the lower level dependency "commons-logging" happily breaks compatibility, proud of himself following the engineering best practice SemVer and increasing the major version number. What would you do? Leave the vulnerable lib in the app? Patch the libraries? The promise was to prevent dependency hell, not to detect it. Quoting the ticket and reiterating the point of my first comment above: > Once again, the point of this ticket is to: > 1. Remove the false promise that SemVer solves dependency hell by simply increasing major version. > 2. Discourage unnecessary compatibility breakages, when it's trivial to maintain compatibility. > 3. Several sentences of advice for the cases when comparability breakage is really needed.
- lloeki 3y ago