cheerfulstoic

cheerfulstoic

Conflicting dependencies and use of the ~> operator

I feel like Elixir is getting big enough and old enough that I’m starting to experience problems with conflicting dependencies. An example from an application that I’m currently working with:

I went to try out the merquery library. This application uses version 1.0.2 of the jq library (the latest version, but from over five years ago) which in turn specifies poison ~> 4.0. The merquery library that I was adding specifies flint ~> 0.6 and flint 0.6.0, in turn, specifies poison ~> 6.0

This was actually just the beginning of the headaches and I had to chase down a few situations, making a couple of forks in the process to versions which didn’t conflict.

For a while I’ve been thinking that it’s wise practice to follow a general rule:

  • When specifying dependencies for an application, prefer the ~> operator (either x.y or x.y.z generally)
  • When specifying dependencies for a library, prefer the >= operator

I think pretty much everybody will agree with the first point. My thought on the second being: new versions of your dependencies will come along and, if there are bugs, you can fix your library (or if something is too difficult or you don’t have time you can add a ~> or <= constraint). But you shouldn’t stand in the way of applications wanting to use your library with newer versions of shared dependencies because probably most of the time they will work

Absolutely I think that you should consider your libraries use of each dependency. If you’re including jason and all you do is very simple usage of Jason.encode and Jason.decode, then the likelyhood that a major version will break things is low and you should probably use >=. If you’re using a library in a complex and intricate way, then you should consider if you should limit the versions you allow.

But I think that most people writing a library are used to using the ~> operator from building applications.

So my suggestions (given that this is the ideas/suggestions/proposals area of the forum):

  • have some advice in the documentation
  • if people are mostly in agreement, build a bot which goes to Elixir dependencies (especially more popular ones) and automatically suggests changes, along with a detailed explanation of the whys involved and things that the maintainer should consider on if they should or should not accept the change.

I’m happy to work on these things (and others) because I think it will be more and more of a big deal to help make Elixir development smoother in the long run (I’ve used npm enough to see how bad things can get :sweat_smile: )

Also, this post from the Ruby world has some good discussion on the topic as well.

Most Liked

zachdaniel

zachdaniel

Creator of Ash

You can override dependencies if necessary, but I think there is something major missing from overriding dependencies, specifically I think you ought to be able to say why you are overriding a dependency, and then mix can tell you when you don’t need to anymore.

For example:

{:jq, "~> x.x", override: [:merquery]}

says “I know that merquery wants a different version, but I’m overriding it”. Then if later you update merquery, and no longer need the override, mix will instruct you to remove it. Additionally, if you add some new dependency that wants an older version of jq, you have to acknowledge that you are also overriding that dependency.

This makes it a bit safer to use override as a consumer of libraries, which I think helps alleviate this issue a bit as well.

zachdaniel

zachdaniel

Creator of Ash
ericmj

ericmj

Elixir Core Team

There is more to it than just changing the library name. There are lots of global names that would have to be modified to ensure uniqueness, application names, module names, process names, ets table names etc.

zachdaniel

zachdaniel

Creator of Ash

I’m suggesting that this is built into the mix dependency resolver. Right now the following happens all the time:

  • I want to add foo to my app. I already have bar and baz.
  • foo depends on a newer version of bar.
  • I can’t update bar because baz depends on it.
  • I check how they baz and foo use bar, and confirm that its fine to just override.
  • So I add {:bar, "~> ...", override: true}
  • Someone else adds buzz to the app, which also depends on an old version of bar.
  • Problem 1: We never find out that we just overrode bar for the sake of buzz as well.
  • Next, foo releases an update that depends on more stuff from the old version of bar.
  • Problem 2: mix tells us we can update foo, so we update it and have bugs.

If instead of override: true, I could say:

{:bar, "~> x.x", override: [foo: "x.x.x"]}

which would say “this override only overrides the dependency that foo at exactly version x.x.x has on bar”, then we are protected from any of those accidental changes.

Adding buzz would produce an appropriate dependency conflict warning, solving Problem 1. We can then go look at the code/docs and decide if we want to override the bar dependency for that version of buzz as well.

foo won’t appear to be automatically upgradeable, solving Problem 2.

al2o3cr

al2o3cr

FWIW, >= in libraries can cause its own headaches, especially if the package being referenced doesn’t follow semver.

For instance, here’s a pair of issues from standardrb that were ultimately driven by interactions between >= and already-locked versions:

Where Next?

Popular in Proposals: Ideas Top

MeerKatDev
many times we do stuff like (e.g. test setups, json views in phoenix) aaa = ... bbb = ... ccc = ... %{aaa: aaa, bbb: bbb, ccc: ccc} and...
New
rhcarvalho
Hi all, I would like to gather some feedback before a more intentional proposal to add a new :depth option when specifying a Git depende...
New
rekkice
I’m building an editor integration to evaluate Elixir code in an IEx session. While Code.eval_string/3 allows tracking variable bindings,...
New
kip
Sumary of proposal DateTime.from_iso8601/3 adjusted to: set all numeric fields to the values as parsed (not shifted to UTC), preservi...
New
pdgonzalez872
Hi! There has been some discussion about hiring/jobs on here and I thought about running this by everyone. I wanted to try to help recr...
New
dli
Ecto currently supports some data-modifying WITH statements / CTEs for Postgres: Options: […] :operation - one of :all , :update_all ,...
New
winsalva
Hello all. First of all i’m running this using termux on an android phone. Running mix assets.setup shows this message 06:54:08.450 [de...
New
bartblast
This could resolve to {[a: 1, b: 2]}. Was it ever considered to allow such syntax? Notice this: {:abc, a: 1, b: 2} and this: my_fun(:abc,...
New
sezaru
When writing my code, I always find __MODULE__ very useful to use as alias of that module “inner dependencies”, ex: alias __MODULE__.{Im...
New
dkuku
This is a proposal to make the map key mismatch errors a bit better: Every time I have a typo It’s very challenging for me even when I u...
New

Other popular topics Top

SoCreat
i’m a new one to elixir which editor can i use vs code? or atom? Thanks! :smiley:
New
sergio
In Ruby, I can go: User.find_by(email: "foobar@email.com").update(email: "hello@email.com") How can I do something similar in Elixir? ...
New
yawaramin
In the Dialyzer docs ( http://erlang.org/doc/man/dialyzer.html#requesting-or-suppressing-warnings-in-source-files ), there is a way to tu...
New
albydarned
Hello all! I am typing this post from my new MacBook Pro with the M1 chip. I’m loving it so far, and will probably use it as my daily dr...
New
jerry
Good day to you all. I have been struggling to get a query involving like and ilike to work. Can anyone assist me on this, please? pro...
New
_russellb
I want to try my hand at web scraping. What tools/libraries do I need to use. I’m hoping to turn this into something professional so don’...
New
malloryerik
Hi, this is for people who, like me, have had some friction using .html.heex templates in VSCode. The solution seems to be, in a hyphena...
New
KronicDeth
Elixir plugin for JetBrain’s IntelliJ Platform (including Rubymine) This is a plugin that adds support for Elixir to JetBrains IntelliJ...
289 35421 110
New
jay1
Why is it that the mnesia database isn’t the most preferred database for use in Elixir/Phoenix?
New
magnetic
Hey :wave:t3: Elixir community, I’ve been learning Elixir, and working on some side projects. My editor of choice is VSCode, and althoug...
New

We're in Beta

About us Mission Statement