4 ms·
One thing I've never been able to figure out about these package management systems: why do you specify a version range, and not just always specify a precise v
by nulltype 11y ago
One thing I've never been able to figure out about these package management systems: why do you specify a version range, and not just always specify a precise version? I don't like dependencies randomly upgrading themselves, and then you don't need "pub upgrade" or "pubspec.lock".
- munificent 11y ago> why do you specify a version range, and not just always specify a precise version? To handle shared constraints. Let's say myapp uses foo and bar, which both use shared_thing. To solve this, we need to pick a single version of shared_thing that both foo and bar work with. If foo and bar have narrow-to-the-point-of-precise constraints like shared_thing 1.2.3+bug-fix, then it's very likely that no version of shared_thing makes both foo and bar happy. The end result is no solution. To accommodate that, packages are strongly encouraged to semantically version themselves. Then, when you depend on a package, you use as wide a range as you can. If foo wants shared_thing ">=1.2.3 <2.0.0" and bar wants ">=1.3.0 <2.0.0" then the solver can pick, say, 1.5.3, and both are happy.
- nulltype 11y agoThanks for the explanation! I'm not sure I personally want to rely on semantic versioning, but if you have a hierarchy of dependencies like that I see how that would be pretty useful.
- tene 11y agoHow do you arrange to never have any transitive dependencies?
- nulltype 11y agoI use specific versions of libraries in my app. If two libraries depend on some third library it's rarely an issue, and when it is an issue I often have to resolve it manually anyway. Ideally I think each library would have its own internal copy of any dependencies, but there are some issues with doing that at least in go.
- TheDong 11y agoIt's very easy to do that in go by just import path rewriting, ignoring legal consequences, and vendoring. Perhaps what you want is npm where what you describe is built in, first class, and looked down upon by much of the sane world.
- nulltype 11y agoWhat are the legal consequences of path rewriting? And why would the sane world look down on npm?
- TheDong 11y agoPath rewriting means you're distributing modified copies of code, which puts you under significant legal obligation in some cases. npm is amazing for javascript, but terrible for compiled languages and is especially terrible for security updating; the giant mess of transitive dependencies of the same dependency of varying versions can get messy fast.
- garthk 11y agoMany correlate "sane" with "statically typed". [1] JacaScript can cope perfectly well with modules A and B relying on different versions of C. It'll often cope even if A calls B with an object it got with C, or some other module broadly compatible with C. Static typing proponents aren't comfortable with the idea, so it's not "sane" to them. Sane or not, many argue it's not just not slowing down the Node community, but actively contributing to its explosive growth. In C#, you get MethodMissingException if A.DLL and B.DLL refer to different copies of C.DLL and A calls B with an object it got from C, even if the copies of C.DLL are identical. 1: Perhaps I should contrast with strong typing, not static typing. Meh.
- munificent 11y ago> Ideally I think each library would have its own internal copy of any dependencies That works if and only if the library never exposes the use of that dependency, but it can break in horrible ways otherwise. For example, let's say library foo uses some hash_table package to define some hash table data structure. Foo returns hash tables from its public API. Now imagine your app uses foo, gets one of those hash tables, and passes it to bar. Bar also uses the hash_table package, but--since dependencies are encapsulated--has its own copy of a different version on hash_table. How is that hash_table code going to handle being given a hash table that was created from a different version of itself? In a dynamically-typed language like JS, it may work, but this seems super sketchy to me, which is why I think an app should only have a single version of any given dependency.
- viraptor 11y agoOne is the shared versions as mentioned in another comment. The other one is security updates. If you release Widget that needs Gadget =1.2.3 that needs Tool =2.3.4 that needs ssl-wrapper =3.4.5 and you find out that ssl-wrapper 3.4.5 has a security issue (fixed in 3.4.6), then you can't just upgrade Widget. I would have to wait for 3 different projects to update their dependency lists to get a secure system again. Provided that everyone does anything even resembling semver, you could just use Gadget 1.2.>=3, Tool 2.3.>=4, ssl-wrapper 3.4.>=5 instead and still be fairly sure the api won't suddenly change to something incompatible.