-
Notifications
You must be signed in to change notification settings - Fork 229
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Support "friend dependencies"? #3051
Comments
Hmm interesting concept! |
You don't want to add a real dependency where you don't actually use it, because that adds bloat for anybody using your package but not the other package. For instance in the linked example (dart-lang/sdk#46687), adding
I agree it isn't going to be incredibly common, but it could be very useful and beneficial for users when it is used. This comes both in terms of:
|
We have plans for a mechanism allowing one to mark package-versions 'broken' in the pub.dev interface. We would then teach the pub solver to avoid broken versions altogether (unless explicitly demanded). Would that work for solving issues like: dart-lang/sdk#46687 ? Then the versions of analyzer that conflicts with meta could be marked broken, and patch-releases could be published that would always allow solving within the same ^-ranges. That seems to me to be a more general solution - and carrying this information outside the pubspec, means that things can be solved as they are discovered. One possible downside compared to the "friend dependencies" is that it only works when you control the other package... cc @jonasfj might have opinions? |
Years ago npm had something called A crazy idea in this space might be to allow package authors to publish incompatibilities for a package version long after it has been published. It's probably way to complicated to actually do. But a fun way to think about the problem. IMO the downside to adding complexity might outweigh the benefits. Especially if we introduce simple measures like retraction / broken. |
Allowing you to mark broken versions isn't directly related - if you didn't realize the issue in the first place you would be unlikely to add the "friend dependency" either. It is a good way to fix this problem when you accidentally cause it, but it doesn't allow you to actually release a change like what was attempted in dart-lang/sdk#46687 safely. In most situations like this today you would either just decide not to go ahead with the change at all, or do a breaking change to safely release it. But this feature would allow you to move things from one package to another without a breaking change in either package, which would be nice (especially for "core" packages). Consider also the case where you have a package that defines some abstract classes, but where all implementations of that class are known, and you want to add a method to that class. This would simplify the versioning of packages in that case, allowing the "core" package to have fewer breaking changes, and instead just have friend dependencies on the versions of all the packages that implement that class, requiring the version that is compatible. This is the case for |
I think the complexity should be pretty minimal, although things are never as easy as they seem :). But essentially you just collect a list of all the non-friend dependencies. Then you throw away all friend dependencies not in that set and only keep the ones that do exist in that set, and treat them as normal dependencies. So there would be probably an extra pass somewhere early on, and the rest of the code should be unchanged. |
@jakemac53, am I right, that what you really want to do here is specify incompatibilities with non-dependencies?
I tried pitching making namespaced imports the default for the new import-syntax, effectively encourage everybody to do: I think it was @lrhn who made the reasonable argument that the compatibility promise in semver only covers the API offered by the package. So it follows that if two packages introduce the same top-level symbol neither of packages needs to bump major version, as no breaking change has happened. The fact that code using both packages might have hard to debug problems is an acceptable limitation of semantic versioning. I think it's fair to argue that semantic versioning has limitations. Which also implies that sometimes upgrade experiences will be painful. If we wanted to mitigate this problem, we could:
I think (A) has limitations because you are likely to only discover incompatibilities after publishing. (B) makes the constraint graph dynamic, and could possibly lend itself to abuse -- but it is nonetheless interesting. (C) probably requires some non-trivial engineering, and most likely has limitations too -- but it might solve problem. |
Sounds like what you really want is to be able to add upper bounds on dependencies on your package to specific versions of other packages. That is, package That makes sense because the two packages are tightly coupled. It's probably rare otherwise. It's a kind of inverse dependency (aka., not a dependency). More like an extra conditional constraint of the form So, it makes sense to me. Even when I try to generalize it, I end up at the same thing. I can see why putting it into So, it's just a way to add a constraint without adding a dependency, and where the constraint is trivially satisfied if the constrained package is not part of the program. |
Yes, in effect it's adding an "incompatibility", because it's a statement that says package My side note was that: afaik this only happens when introducing conflicting top-level symbols in two packages.
(1) could be done in the language by encouraging If the primary motivation is conflicting top-level symbols, then maybe the root of the problem is language features that doesn't encourage forward compatibility (1). |
Fwiw I think in general semantic versioning does cover this use case, the goal is not to change how semantic versioning works. Instead what I am proposing is I think best described by @lrhn :
|
I do think that option B could be interesting as well, it would help solve some additional cases that come up. But I do worry about the UX implications for some users:
Possibly it would be enough to just log a warning to users who run a |
Option (B) definitely has UX implications. On the other hand, it would be a really cool and innovative :D It would effectively make dependency constraints dynamically tweakable after package publication. |
Ya, it would be a better alternative to retraction for many use cases I think. It would also enable some packages to avoid breaking changes, where the breakage is not actually expected to affect general users, and only a certain other tightly coupled package. You could add a new upper bound dynamically to that one tightly coupled package instead. |
I don't think we have any plans for this in the foreseeable future. Closing as won't-fix for now. Please file a new issue if this is still pressing. |
This is a proposal for a new dependency type, a "friend dependency" (not attached to the name).
These dependencies would not be real dependencies. However, if this dependency was a part of the version solve, then it would take the constraints into account.
The motivation would be issues such as dart-lang/sdk#46687. There are cases where your package may only be compatible with a certain version range of another package - but you don't actually depend on that package, and don't want to introduce that dependency just to enforce the version constraint.
In particular if you want to move something from one package to another, this can be useful and allow you to do it without any breaking changes in either package.
The text was updated successfully, but these errors were encountered: