Comment by awesome_dude

20 hours ago

Package management is the bane of nearly every language/technology

Nobody has "solved" it, and I don't think that there will ever be one (never say never, though, right?)

For Go we rely on developers of libraries to adhere to the semver versioning scheme accurately, and we cannot "pin" versions (a personal bugbear of mine)

There is a couple of workarounds - using SHAs not unlike the git commit hash to provide a pseudo version, and, vendoring (which is a cache of known dependencies - which brings with it cache management problems)

I had the misfortune of having to use Python with a virtual env on the weekend - it did not end well, and reminded me why I migrated away from Python.

Look at Perl (cpan) Java (maven, gradle) Ruby (gems) Go (dep, glide, vgo, modules) Rust (cargo) Node (npm, yarn, etc)

OSes too Redhat (yum, rpm, etc) Debian (apt) Ubuntu (snap - god why????)

And so on

> I had the misfortune of having to use Python with a virtual env on the weekend - it did not end well, and reminded me why I migrated away from Python.

I see this sentiment a lot, and it doesn't match my experience at all.

In my decade-old bubble of using Python professionally, I've never had an issue with virtualenvs. The few issues I might've had with dependency resolution must be so far in the past that I don't remember. But that's not strictly about virtualenvs. Likewise, pip could be clunky, but we don't have to deal with it anymore.

My niche is mostly backend. Other Python niches must be considerably worse in this regard.

Actually with Go modules you are always pinning dependencies. What’s in your go.mod is what is used. If your go.mod needs to be updated because a dependency wants to bring in a newer version of a transient dependency, the go.mod has to be modified (by the go command, not by you)

> we cannot "pin" versions

you can? that's why go.sum exists. you can also use the replace directive for more advanced scenarios.

Nix solved it. Languages could choose to adopt Nix as their packaging system.

  • It did and didn't. Nix tools for building language-specific packages almost always wrap the language build tool/package manager. This can be easy or hard, depending on how onerous the build tool is for vendoring libraries.

    What Nix and build tools need to agree on is a specification or protocol for "building a software dependency tree". Like, I should be able to say 'builder = cargo' in a Nix derivation and Cargo should be able to pick up everything it needs from the build environment. Alas, there is simply far too much tied up in nixpkg's stdenv for this to be viable, so we have magic stdenv builder behavior via hooks when a build tool is included in nativeBuildInputs.

    • I think one of the key problems too is that a system level dependency is managed by people dedicated to ensuring the chaotic nature of the package they are responsible for conforms to the way the OS they are maintaining for has proscribed.

      There's no real way to do that at a language level - we cannot have "Go has determined the package you are trying to fix has not met the versioning requirements proscribed so you cannot submit the patch to fix it"

      What language dependencies do is what OSes would think of as "unofficial versioning" that is, an OS will let you install and run an unofficial version of some lib (we've all been there, right, multiple versions of some core library because one doesn't work with whatever you are trying to install), but they will not manage it at all.