3 ms·
I think that the solution to this problem is one of the few things that nodejs got right. Instead of declaring a global dependency on `require("D")`, you assign
by psadauskas 11y ago
I think that the solution to this problem is one of the few things that nodejs got right. Instead of declaring a global dependency on `require("D")`, you assign it a variable name. Then, each package can declare its sub-dependencies, and even when the versions differ, the different versions are kept in a different scope.
https://nodejs.org/api/modules.html https://nodejs.org/api/modules.html
// Package A:
import B from "B"; // A/node_modules/B/1.0.0
import C from "C"; // A/node_modules/C/1.0.0
// Package B:
import D from "D"; // A/node_modules/B/1.0.0/node_modules/D/1.0.0
// Package C:
import D from "D"; // A/node_modules/C/1.0.0/node_modules/D/2.0.0
- jasonwatkinspdx 11y agoI'm convinced this is the right approach: dependencies should be purely local to a module. The tooling should make it easy to detect you have a diamond, but let each module get what it needs. As generally everyone moves towards more continuous update and integration, at the end of the day it's all gonna be sha's anyhow.
- wtetzner 11y agoBut what do you do in a typed language? For example, suppose you have modules A and B, which depend on module C. Let's also say that module A has a function foo that return a value of type C.t, and module B has a function bar that accepts a value of type C.t. Now let's say that module A is depending on version 1.0.0 of module C, and module B is depending on version 1.5.2 of module C. Does B.bar(A.foo()) still work? Is type t the same in C version 1.0.0 and 1.5.2?
- eknkc 11y agoGood point. But if B.bar accepts an interface that C.t implements, then everything should work just fine and that should be the way to go on public APIs.
- wtetzner 11y agoBut what if the interface is defined in C? The interface has to live somewhere, and wouldn't it be versioned too?
- jasonwatkinspdx 11y agoI think the pragmatic approach is to just let that be a type analysis failure and force the user to deal with it. We don't need the module system to be automatically perfect in every imaginable extreme, we need it to be fundamentally safe, and then do sane useful things in the situations that are safe.
- sophacles 11y agoI think that this is a good approach - even better would be to include the version specifiers in the code itself... B = import("b", ">1.0") C = import("c", ">1.1 && <2.0") etc.