3 ms·
Let's address your main concern first. You see the ability to install multiple versions of a gem as a flaw. Let's analyze this viewpoint in detail. First a few
by FooBarWidget 16y ago
Let's address your main concern first. You see the ability to install multiple versions of a gem as a flaw. Let's analyze this viewpoint in detail.
First a few axioms we must agree on:
1. Libraries eventually have to break compatibility, otherwise progress is impossible.
2. There must be some way to deal with incompatibilities, either socially (release and compatibility guarantee policies) or technically (package managers).
Your point of view: social ways to deal with incompatibility are superior to to technical ways to deal with incompatibility because the latter encourages developers to be lazy about compatibility guarantees.
I have a few objections about that point of view.
1. It assumes a perfect world.
Although it doesn't happen often, an app can break due to reliance on library bugs or unformalized/undocumented behavior/internals. Sometimes a newer version of a library has a regression that isn't found until it's released.
Yes we all know things like these ideally shouldn't happen, but they do. Is it a good idea to ignore the reality that things like this happen from time to time?
According to the logic that supports your point of view, we should abolish protected memory as well. Protected memory allows programmers to write apps that don't bring down the entire OS when they crash... it makes programmers lazy!!
2. It assumes that DPKG/RPM don't make life hellish for sysadmin and end users.
For the most part, DPKG/RPM works fine. For Ruby stuff, not so much. Suppose there's an app called frobnicator, and it works on foobar 1.0.x but not on foobar 1.2.x. Thanks to the fact that DPKG/RPM only supports installation of single versions, your distro can only package foobar 1.2.x but not 1.0.x. Now the user cannot use frobnicator at all because you insist on DPKG/RPM. How exactly is this better for the end user?
- FooBarWidget 16y agoOh and this. 3. It inherently excludes some valid compatibility cases, unless the developer is forced to hack around the package manager Suppose 'foo' depends on 'bar'. bar consists of features A, B and C. Furthermore bar has made the guarantee that it will never break the compatibility of feature 'A', ever. It also has a compatibility policy that states it will increment its major version number every time it breaks B and C. foo only uses feature A in bar, so we know that foo is compatible with every version bar that will ever be released. foo also depends on 'libcat'. libcat depends on bar, but uses all its features. The current release of bar is 1.0.0, so we know libcat depends on 1.0.0 <= bar < 2.0.0. Suppose that 'frobnicator' depends on bar. It uses feature B and it uses the interface provided by bar 2.x. This seems like a completely reasonable case. Developers aren't being lazy about compatibility guarantees here. The only way to solve this problem is by versioning bar on the filesystem level. That is, while bar 1.x requires developer to type require 'bar/feature_a' require 'bar/feature_b' bar 2.x requires the developer to type require 'bar-2/feature_a' require 'bar-2/feature_b' You have to rename the entire library directory. In my opinion this is an ugly hack around the fact that your package manager doesn't support multiple versions. I think this is solved much more elegantly if the package manager allows you to switch the version on-the-fly... in other words, what RubyGems does.
- regularfry 16y agoThis is one case that rubygems handles well, but I think your specific example is broken. If libcat requires 1.0.0 <= bar < 2.0.0, foo requires libcat, foo requires 2.0.0 < bar, you've got conflicting requirements - foo requires both bar < 2.0.0 and 2.0.0 < bar. Rubygems will barf at that. > You have to rename the entire library directory. In my opinion this is an ugly hack around the fact that your package manager doesn't support multiple versions. I think this is solved much more elegantly if the package manager allows you to switch the version on-the-fly... in other words, what RubyGems does. It may be an ugly hack, but it's fairly traditional at this point.
- FooBarWidget 16y ago> Rubygems will barf at that. Only if you activate gems linearly. Bundler solves exactly this: it looks at all dependencies then figures out a combination that works. Bundler will only activate bar 1.x because it sees that foo is compatible with all versions but libcat is only compatible with 1.x. > It may be an ugly hack, but it's fairly traditional at this point. I argue against the notion that being traditional here equals being good. There's no good reason why the developer should do this manually instead of having some system do it for him. RubyGems actually implicitly does this. By installing each gem to its own directory it separates the versions on the filesystem level.
- regularfry 16y ago> Only if you activate gems linearly. Bundler solves exactly this: it looks at all dependencies then figures out a combination that works. Bundler will only activate bar 1.x because it sees that foo is compatible with all versions but libcat is only compatible with 1.x. You're absolutely right, I misread your example. > I argue against the notion that being traditional here equals being good. There's no good reason why the developer should do this manually instead of having some system do it for him. It's a trade-off. Either the developer has to do it manually (once, which will then work with every sane distro), or the sysadmin has extra work to do (many times, once for each language-specific package manager). In an ideal world, the language communities would gang up on Debian and Red Hat and improve dpkg and rpm to make this issue go away. I don't see this happening.
- regularfry 16y ago> Your point of view: social ways to deal with incompatibility are superior to to technical ways to deal with incompatibility because the latter encourages developers to be lazy about compatibility guarantees. Not quite. Social ways to deal with incompatibility are superior to the specific technical way that rubygems encourages. > Although it doesn't happen often, an app can break due to reliance on library bugs or unformalized/undocumented behavior/internals. Sometimes a newer version of a library has a regression that isn't found until it's released. > Yes we all know things like these ideally shouldn't happen, but they do. Is it a good idea to ignore the reality that things like this happen from time to time? I'm not ignoring that reality at all. I'm specifically encouraging point releases with backported bug-fixes. These happen all the time in dpkg-land. > According to the logic that supports your point of view, we should abolish protected memory as well. Extrapolation to extremes will destroy any rational argument, so I'll ignore this. > 2. It assumes that DPKG/RPM don't make life hellish for sysadmin and end users. > For the most part, DPKG/RPM works fine. For Ruby stuff, not so much. That would be the point. I'd also point out that it's not just a question of dpkg vs rubygems here. From a sysadmin's point of view, it's dpkg vs (rubygems + CPAN + PEAR + cabal + virtualenv/pip + maven + ...). > Suppose there's an app called frobnicator, and it works on foobar 1.0.x but not on foobar 1.2.x. Thanks to the fact that DPKG/RPM only supports installation of single versions, your distro can only package foobar 1.2.x but not 1.0.x. Now the user cannot use frobnicator at all because you insist on DPKG/RPM. That specific case isn't a problem, because you'd just package foobar 1.0.x and ignore 1.2.x completely. The problem comes when something else comes along that depends on 1.2.x but won't work on 1.0.x at all. That would be a case of either foobar's author not following version numbering convention, or a bug which can/should be patched. > How exactly is this better for the end user? If it's not, foobar's author is responsible. However, for the distro to be able to turn around and say "We value stability over all else, and we cannot provide this combination of packages while supporting a stable system, so we're not going to" is actually fairly awesome.
- FooBarWidget 16y ago> That would be a case of either foobar's author not following version numbering convention, or a bug which can/should be patched. Suppose we substitute "1.2.x" with "2.0.x". foobar now is following version numbering convention but the problem didn't change. Now what would you do? > We value stability over all else, and we cannot provide this combination of packages while supporting a stable system, so we're not going to This is clearly false. Package both versions and have apps load the version they're compatible with. Now the user can have all apps without compromising stability. RubyGems supports exactly this, DPKG/RPM doesn't support this without filesystem-level renames. Why do you think the latter is superior?