15 ms·
Ask HN: Why does every package+module system become a Rube Goldberg machine?
A programming language has a "core language" plus a package/module system.
In each successful language, the core language is neat-and-tidy,
but the package/module system is a Rube Goldberg machine.
See JavaScript/TypeScript, Python, or C/C++.
Lots of brain cycles are spent on "programming language theory".
We've roughly figured out the primitives required to express real-world computation.
In contrast, we apparently have no "package management theory".
We have not figured out the primitives required to express dependencies.
As a result, we keep building new variants and features,
until we end up with <script>, require(), import, npm, yarn, pnpm, (py)?(v|virtual|pip)?env, (ana)?conda, easy_install, eggs and wheels ...
Is it just a "law of software" that this must happen to any successful language?
Or are there examples of where this it has not happened, and what can we learn from them?
Is there a "theory of package management", or a "lambda calculus of package management" out there?
- jakewins 4y agoHave you used Go or Rust package ecosystems? My experience is that the older gen languages you mention had to invent package management, made lots of understandable mistakes and now are in a backwards compat hellscape. Rust and Go built their packaging story with the benefit of lessons learned from those other systems, and in my experience the difference is night and day.
- omgtehlion 4y agoIdk about Go, but Rust’s cargo seems nice, clean yet powerful. That was my impression some time ago. But last week I attempted to compile a couple of (not very big) tools from cargo. And it ended up downloading hundreds of dependencies and gigabytes of packages. Looks like node_modules.jpg all over again :(
- verdverm 4y ago> Idk about Go I wrote a post highlighting Go's mod system: https://verdverm.com/go-mods/ https://verdverm.com/go-mods/ imo, it is the best designed dependency system I know of. One of the nice things is that Go uses a shared module cache so there is only one copy on your computer when multiple projects use the same dependency@version
- omgtehlion 4y agoI think, this is not a problem with package manager per se. But with extremities of coding culture. On one side of the spectrum is “NIH” and reinvent everything yourself. On the other side is: let’s pull left-pad from package, because packages are good, we need MORE PACKAGES. The best solution always lies somewhere in the middle. But finding this “middle” (and adhering to this approach) is the hard part.
- marcus_holmes 4y agoI think I'm on the NIH side of things. Not because I like inventing things (well, partially), but because of the security problem [0]. I don't see it being talked about here, either. Our current system of pulling in packages made by random people on the internet is going to burn us. We assume that everyone who creates a package is an honest, reliable, developer who will not inject malicious code into their package. This assumption is similar to the assumptions we made around SMTP, HTTP, DNS, and every other internet protocol. Turns out we were wrong and surprise! you can't trust people on the internet. I'm not sure if we can solve this with package managers. But package managers are part of the culture that has created this problem, and are probably a reasonable starting point to try and address it. [0]:https://david-gilbertson.medium.com/im-harvesting-credit-card-numbers-and-passwords-from-your-site-here-s-how-9a8cb347c5b5 https://david-gilbertson.medium.com/im-harvesting-credit-car...
- Groxx 4y agoI really like a lot of the distribution- and safety-related decisions Go modules made. Domain names and the proxy+sumdb are wonderfully clear, flexible, and scalable, and I think we'll see copies of it in many future languages. The rest of the stuff around modules, like crippled constraints, zero control over contents (which they have changed!), and completely non-existent "x is available, upgrade" or release tooling: constant, unnecessary pain, and it'll be inflicting serious damage on the ecosystem for many years to come.
- verdverm 4y ago> crippled constraints Do you mean ranges on dep versions? The way it is currently, the version you set is the minimum, and the algo finds the highest minimum set across all deps and uses that. If ranges were introduced, you'd end up with an NP hard problem and need a SAT solver for your deps again > Release tooling What are you looking for here? Libraries only need to push a git tag, binaries do require a bit of work, but Goreleaser fills that pretty nicely. It would seem hard to standard where binaries would be pushed > completely non-existent "x is available, upgrade" https://go.dev/doc/modules/managing-dependencies#discovering_updates https://go.dev/doc/modules/managing-dependencies#discovering... "go list -m -u all"
- junon 4y agoAs someone who contributed somewhat extensively to the node_modules problem early on, Cargo is definitely better than the JS ecosystem in this regard. Further, another major difference is that you don't need those dependencies after you've built. You can blow them away. Doing that with node is not as straightforward, and in many cases, not possible.
- pjmlp 4y agoDoesn't look like it, see module drama in Go, while Rust is having an npm like ecosystem of tiny crates. Plus none of them handle binary library distribution as some of the packing models that came before them.
- tomcam 4y agoCan you give me a one-liner about module drama in Go?
- pjmlp 4y agoFirst they weren't supported, so the community created various ways of dealing it including a kind of Google's blessed implementation, then Google decided to create their own official way, then there was the transition time which I guess not everyone has done, having SCM urls as imports is just bad, and how GOPROXY DoS some SCM repos outside of Github.
- Nzen 4y ago[0] https://go.dev/blog/appengine-gopath https://go.dev/blog/appengine-gopath gopath / workspaces original [1] https://go.dev/blog/migrating-to-go-modules https://go.dev/blog/migrating-to-go-modules current system [2] https://news.ycombinator.com/item?id=34310674 https://news.ycombinator.com/item?id=34310674 goproxy agressively polling sourcehut It's worth recognizing that go isn't alone in dns-based namespacing : java's maven/gradle use the same strategy: https://repo1.maven.org/maven2/gov/nih/imagej/imagej/1.47/ https://repo1.maven.org/maven2/gov/nih/imagej/imagej/1.47/
- xiphias2 4y agoNpm has lots of not understandable mistakes: it should already be as good with ES6+TS as other systems. Import should just work everywhere. We should have left Commonjs a long time ago, while keeping backwards compatibility. At the same time what I see with the node+npm system is that everything is just ,,it just doesn't work by default''. Having 10 other package managers doesn't work either, they are faster, but don't solve this problem.
- eurasiantiger 4y agoJust use .mjs extension for your code, add extensions to your imports and everything does just work.
- noahtallen 4y agoExcept in typescript, where you have to import a file with the .js extension, despite the actual file being .ts: https://github.com/microsoft/TypeScript/issues/42151 https://github.com/microsoft/TypeScript/issues/42151, https://github.com/microsoft/TypeScript/issues/49083 https://github.com/microsoft/TypeScript/issues/49083, https://github.com/microsoft/TypeScript/issues/16577 https://github.com/microsoft/TypeScript/issues/16577 This one issue (IMO) is preventing parts of the ecosystem from switching to esm.
- mhio 4y agoHow does the js extension stop a project from targeting ESM?
- tsimionescu 4y agoGo package management is a mess of hacks. It doesn't even have a repository, instead relying on source control systems to do the actual work, with special hacks for each source control system to define the artifacts that can be downloaded (e.g. using Git tags with some magic format, or Perforce commit Metadata). It requires you to physically move all code to a new folder in your version control if you want to increase the major version number. It requires users of your code to update all of their import statements throughout their code whenever you move your hosting. It relies on DNS for package identity. It takes arcane magic to support multiple Go modules in the same repo. I can go on, but it's a terrible hodge-podge of systems. It works nicely for simple cases (consuming libraries off Github), but it's awful when you go into details. And it's not even used by its creators - since Google has a monorepo and they actually use their internal universal build tool to just compile everything from source.
- gwd 4y ago> It relies on DNS for package identity. The flip side of this is that it never has to worry about naming collisions or namespacing: Your public package name must be a URL you control. Additionally, there is no requirement for a centralized package facility to be run. The Golang project is currently running pkg.go.dev, but that's only been in the last few years; and if they decided to get rid of it, it wouldn't significantly impact the development environment. Finally, the current system makes "typo-squatting attacks" harder to do. Consider the popular golang package github.com/mattn/go-sqlite3. The only way to "typosquat" the package is to typosquat somewhere up the dependency tree; e.g., by creating github.com/matn/go-sqlite3 or something. You can't typosquat github.com/mattn/sqlite3, or github.com/mattn/go-sqlite, because you don't own those namespaces; whereas with non-DNS-based package systems, the package would be called `go-sqlite3`, and `sqlite3` or `go-sqlite` would be much easier to typosquat. All those things I find really valuable; and honestly it's something I wish the Rust ecosystem had picked up. > It requires users of your code to update all of their import statements throughout their code whenever you move your hosting. This is a necessary cost of the item above. It can be somewhat annoying, but I believe this can be done with a one-line change to the go.mod. I'd much rather occasionally deal with this. > It requires you to physically move all code to a new folder in your version control if you want to increase the major version number. And the benefit of this is that legacy code will continue to compile into the future. I do tend to find this annoying, but it was explicit trade-off that was decided back when they were developing their packaging system. Packaging is a hard problem, with lots of trade-offs; I think Go has done a pretty good job. One way in which Go and Rust have it easier than Python or Node is that the former only have to deal with developers; the latter have to deal with both developers and users, whose requirements are often at odds with one another.
- folex 4y agoBeing in the Rust full time for last 2 or 3 years: it is quite a pain to setup a release process for big Rust workspace. Version incrementing, packaging wasms, dancing around code generation – all doable, but not standardized. There's a release-please to automate all that, but it's not an easy task to set it up in all of your repos. Besides, if in addition to Rust projects, you have projects in other languages like JavaScript, then you have to do it twice and struggle with understanding all of the package management systems provided by all languages you have. A single swiss-army-knife package manager would be amazing.
- dboreham 4y agoGo and Rust don't have packages. They have tooling to pull library code from git and build it in-place to be linked into a local project. That's not (really) packaging.
- steveklabnik 4y agoCargo does not “pull library code from git” unless you expressly ask for it to. And given that packages have to depend on other packages, and cannot depend on a git repository, that feature is mostly useful for testing bug fixes, private repos for leaf packages, stuff like that.
- tremon 4y agoI thought Rust doesn't have binary libraries? If you declare a Rust dependency, cargo pulls its source and builds it together with your own code? I assume that's what the GP meant, anyway.
- steveklabnik 4y agoSource code is stored in an S3 bucket owned by crates.io, and not from any form of source control, including git. That the entire code of all dependencies is hosted in one place is an important differentiator of crates.io vs what Go does, which is why this is relevant in this context. Crates.io is centralized, with all of the advantages and disadvantages that that brings, and Go is decentralized, with all of the advantages and disadvantages that brings.
- SuperSandro2000 4y agoBut it is a pain for a distro to upgrade a vulnerable crate dependency
- ttyprintk 4y agoIt sounds like you’re familiar with the status quo, so let’s look at this as a matter of requirements: - Cross-platform - Wraps another packaging format - Lowest disk space - Dependency version solving - An OS can run make changes to its own low-level state using its own tools - User can configure when and what are installed Even Nix, which has its own language and isolation model, can’t meet all these.
- whateveracct 4y agoNix almost does meet those though. It's cross-platform to some degree. If Windows is a requirement for this, I see why it doesn't qualify. Nix wraps other packaging formats all the time. There's endless x2nix converters. In a way, Nix is "lowest disk space" - by nature of lazy evaluation, Nix closures are always exactly what they need. Now, they may "actually" need less and are holding onto more due to how packages are written by people. And you do need to GC. Dependency version solving can actually be punted to other tools. In Haskell, Nix uses a combination of cabal and pkg-config to handle Haskell + C deps. NixOS can swap out the kernel along with anything else with a line or two in your config.
- ChrisRackauckas 4y agoJulia and Rust seem to have package systems that are fine and manageable. I think these are really just major problems in Javascript, Python, and C/C++ (exactly the languages you mention) because the kind of widespread OSS code sharing just didn't exist to the extent it does today back when those languages were designed. People shared code through email, but didn't expect one button to pull in 200 Github repositories, and thus weren't built with the expectations required to make that be stable. Back when those languages were designed, you'd manually download the few modules you need, if you downloaded any packages at all. In C you'd normally build your own world, since it came before the www times, and C++ kind of inherited that. But languages which came out later decided that we now live in a world where most of the code that is executed is packages, most likely packages which live on Github. So Julia and Rust build this into the language. Julia in particular with the Project.toml and Manifest.jl for fully reproducing environments, its package manager simply uses git and lets you grab the full repository with `]dev packagename`, its package registry system lets you extend with private package worlds. I think the issue is that dependencies are central, so you can never remove old package systems because if that's where the old (and rarely updated) dependencies live, then you need to keep it around. But for dependencies to work well, you need all dependencies to be resolved using the same package system. So package systems don't tend to move very fast in any language, whatever you had early has too much momentum.
- Hendrikto 4y agoTying package management to GitHub seems convenient in the short term, but will be the baggage of the next generation. I cringe hard when I see projects depending on git repos, without pinning a version or commit.
- staunton 4y agoIt's not actually tied to GitHub. If GitHub died tomorrow, they would easily be able to move on and host the packages somewhere else. There's no way to do this without hosting. Also, there is a way to pin a version or commit. Julia for example always stores the exact commit information for all packages in the "Manifest" file. There are also straightforward ways to demand certain versions and package maintainers have the opportunity to specify compatibility and requirements precisely.
- gwd 4y agoYou haven't explicitly enumerated the things about those packaging systems which seem "Rube Goldberg" to you; nor have you mentioned either Golang or Rust's package management. I'm pretty happy overall with Golang's package management, and from my little exposure to Rust's package manager, it seems fairly decent as well. Do either of them strike you as "Rube Goldberg"? What aspects, and why?
- thiht 4y agoPackage management in Go is weird but it works well. You just run go mod tidy from time to time and you're good. Add a module proxy if you want to prevent issues with repositories disappearing and you're gooder.
- gwd 4y agoThere's already a module proxy (pkg.go.dev) by default in new versions of Go, for just that purpose. In fact, one could argue that the automatic proxy is "Rube-Goldberg"-like: It works great normally, but if you need, for instance, to pull from a repo you just pushed to, you have to track down the magic rune to type to get `go get -u` to pull directly from your repo, rather than using the cached copy at pkg.go.dev.
- kardianos 4y agoIn go, if you just pushed to a repo a tagged version, say "v1.4.2", then you just specify "go get -u "myrepo.com/foo@v1.4.2". Internally it will fail to fetch from the moduel proxy, but then (by default) it will then look directly for the git repo, and it will still work. But you can also use go workspaces if you are co-developing modules in different repositories.
- thiht 4y ago> There's already a module proxy (pkg.go.dev) by default in new versions of Go, for just that purpose Is it really a proxy in this sense? I was under the impression that it did not keep cached copies of the code, just some metadata, so that it didn't actually protect about someone removing their repo. Maybe I'm wrong about that though.
- conor_f 4y agoAt least in Python's case, I think people are much too hard on the packaging system. I don't think anyone has significant issues with pip itself as opposed to the runtime it exists within. Following from this, I think that most back-end applications should try solve their messy runtime environment issues with some containerization. Java/C(++) however...
- mschuster91 4y ago> I don't think anyone has significant issues with pip itself as opposed to the runtime it exists within. I'm running macOS with Macports, and oh boy. For a long time, the aws and eb CLI tools had different package requirements or whatnot, and you couldn't install both of them simultaneously for whatever reason. Some stuff installs fine with the system Python, some stuff needs Macports for a specific Python version, some stuff needs root access to install itself... anything Python is a hot mess.
- robertlagrant 4y agoWhile I'm trained to use venvs for everything, it would be nicer to have a flat global list of dependencies in every version required of every package, and specify allowed versions in each project, which will use what you have and/or download what's missing.
- nine_k 4y agoSystem Python? Root access? Oh. That's a terrible, terrible practice. First, one never touches the system Python. It's there for OS-managed stuff and to run OS components. Then, every Python-based tool should be installed in a separate, unprivileged virtualenv, with executables symlinked where you find them appropriate (usually ~/bin or /usr/local/bin). If you find yourself ever issuing a `sudo pip install`, chances are million to one that you are doing a disservice to to yourself.
- mschuster91 4y ago> First, one never touches the system Python. It's there for OS-managed stuff and to run OS components. Why would one want to not use what the system provides? Everything not provided by the OS is additional maintenance burden on myself. The 'nix world has managed just fine with OS-provided bash, perl and other runtime dependencies for decades. > Then, every Python-based tool should be installed in a separate, unprivileged virtualenv, with executables symlinked where you find them appropriate (usually ~/bin or /usr/local/bin). No one has time for all that. I'm not a Python developer - as a user I'm happy enough if it barely works. When an ecosystem requires messing around with completely separate instances of the runtime for each program, that's not a good sign for the quality of the ecosystem as a whole.
- tikkabhuna 4y ago> See JavaScript/TypeScript, Python, or C/C++. I feel like you've picked the 3 worst ecosystems as an example. Java has a wonderful ecosystem. You can use Maven/Gradle/Bazel as a dependency manager/build tool. All support the Maven repository format. Packages are published as jars and easily consumed. Of course you can still end up in dependency hell and you should take steps to mitigate those issues, but I'm quite happy with it. > As a result, we keep building new variants and features, until we end up with <script>, require(), import, npm, yarn, pnpm, (py)?(v|virtual|pip)?env, (ana)?conda, easy_install, eggs and wheels ... IMO the problem here is that there isn't a monopoly and its easy to swap in a replacement. JavaScript/Python developers are happy (or willing) to try something new, so new alternatives are created. Convincing a Java developer to try a new build system is difficult, so changes are made to existing systems rather than creating new ones. Go and Rust are two other systems that work well and are (almost?) universally adopted. They come with the language and there is little reason to look around.
- DemocracyFTW2 4y ago> JavaScript/Python developers are happy (or willing) to try something new, so new alternatives are created. FWIW as far as JavaScript on NodeJS goes, npm did set the standard quite firmly. You can also use yarn or pnpm, which promise improvements over npm while using the same package metadata (`package.json`) and produce npm-compatible structures in the same subdirectory (`node_modules`), so overall the user experience is muche like going from `sudo apt-get install` to the newer, more polished and otherwise largely equivalent `sudo apt install`.
- choeger 4y agoWe have such a theory, it's called "modules". But unfortunately, modules are even less popular than proper typesystems have been for decades. It's no coincidence that Rust (which has basically copied Haskell's type system to a large degree) and Julia (which is essentially a Lisp in disguise) have somewhat sound packaging systems. C/C++ does not even have a tidy core language, let alone proper modules (yes, yes, C++ modules might change that, but they are still a complex mix of templates and normal code).
- pastage 4y agoI do not understand what you mean by modules, and how Rust and not Java or Python is helped by this.
- simiones 4y agoModules typically refers to a unit of code that packages together several types and functions (and/or other top-level concepts in your language, e.g. macros, templates, metaclasses, namespaces, packages) with an explicitly declared public interface, while still allowing these types and functions to have additional internal APIs that are not exposed. A module has to declare what other modules it depends on explicitly. The public interface of a module has to be explicit enough that a compiler for that language only needs the public interface description of that module to compile code that depends on it. A good example of the most widely used and successful module system is C compiled libraries. The header files represent the public description of a library (or, for dynamic linking, the .so/.dll itself embeds this info as well), and a C compiler only requires these header files to be able to compile dependent code and later link the two. It is also impossible to access non-public members of the library from standard C (without resorting to direct memory access, of course). Java packages don't have these properties because of two problems: there is no way to indicate dependencies between packages, and there is no standard way to have a bundle that corresponds to a package (since different .jar files can all load classes into the same package). The Java module system was created specifically to address these problems (and is still not fully adopted throughout the ecosystem). C++ breaks C's module system because of its heavy reliance on templates, which have to be entirely declared in the public API and can't have any internal API of their own; and because the compiler needs to know the total size of a class, including the size of its private members, to compile any code which references objects of that class. For Python, I'm honestly not sure if Python packages fit this definition of a module or not.
- icelancer 4y agoI just spent a few hours in npm/node/heroku hell, so... yeah. It's awful.
- goodpoint 4y agoBecause most developers don't learn from other projects and redo the same mistakes. It's a form of not-invented-here syndrome and you can see it in all the comments defending their favorite language.. > we apparently have no "package management theory". Apparently. In reality there's been plenty of research - and for decades - that is not being used.
- austinjp 4y ago> In reality there's been plenty of research - and for decades - that is not being used. Can you link what you're referring to? Genuine request, I'm curious and keen to learn more.
- Akronymus 4y ago> Is it just a "law of software" that this must happen to any successful language? Or are there examples of where this it has not happened, and what can we learn from them? Dotnet has nuget and it is quite pleasant to use in my experience. I think the big deal is having some standardized way of managing them as a layer on top. In teh dotnet case, it is having the solution pull in the nuget packages, rather than individual files. Along with having a standardized way to index available packages from each source (In this case the nuget json)
- deleted 4y ago[deleted]
- Quequau 4y agoRube Goldberg was a prophet.
- tbarone 4y agoI'll say that on the whole it seems to be getting better with time. Most people have already mentioned Rust / Go as examples of this. I do agree it is an issue. Doing away with node_modules completely on the last rails 7 app I worked on was the most cathartic experience of my life.
- denton-scratch 4y agoIt annoys me that every gee-whizz new language needs to have it's own package-management system. There's no reason why a package-management system needs to be language-specific; dependencies are often cross-language. Hell, even some blocks of code contain more than one language. The package-management system is responsible for deploying packages. The way a package is deployed should depend on the operating environment, not on the language. These language-specific packaging arrangements typically deploy into some private part of the file-system, organized in its own idiosyncratic way. Using git as a repository is just nuts. Git is privately-owned, and stuffed with all kinds of unaudited junk. You can't audit everything you install by hand; so these systems force you to install unaudited code, or simply not install. I've been using Debian derivatives for years. I appreciate having an audited repository, and an installation system that deploys code to more-or-less predictable filesystem locations.
- pjmlp 4y agoBecause cross platform packages isn't a thing, and not everyone wants to create a package for every platform out there.
- Sebb767 4y ago> There's no reason why a package-management system needs to be language-specific; dependencies are often cross-language. Hell, even some blocks of code contain more than one language. This sounds a lot like a case of https://xkcd.com/927/ https://xkcd.com/927/ . Languages have different ways of importing and installing dependencies, trying to create a package manager over all of those is just going to end up making things even more complex, especially if you target all platforms at once. > Using git as a repository is just nuts. Git is privately-owned, and stuffed with all kinds of unaudited junk. Git is fully open source. Are you confusing Git and GitHub?
- tazjin 4y ago> Languages have different ways of importing and installing dependencies They're not actually different. They call things differently, and they have different methods of passing the required lookup paths/artifacts/sources to their compilers/interpreters/linkers, but in the end all of them are conceptually the same thing.
- emmelaich 4y ago> we apparently have no "package management theory" Honestly, I'd like to have a lowest common denominator of "just dump the contents of the tar/zip archive" here. Only check required would be to ensure you're not overwriting anything. Dependencies and PATH management etc could be done out-of-band. That way you would not have to re-download stuff at least.
- Linux-Fan 4y agoI actually wrote something of that sorts for my personal projects: https://masysma.net/11/maartifact.xhtml https://masysma.net/11/maartifact.xhtml Downloads tgz if not already downloaded, saves it to directory `../x-artifacts` and optionally extracts it.
- rpigab 4y agoI think package management is something so important you either have to get it right on the first released version of the language, or never release an official one at all. So if you look at C, there was basically no internet or even HTTP, so if they wanted to fetch + store dependencies from centralized repositories, it would have been difficult and then need to change a lot over the years. Python is the worst to me, I love the language, but I hate the tooling, managing installations, packages, modules, etc. Sometimes languages are relased with just a spec and don't want to force any choice of tool or way of doing things on you, so you just manage that yourself or create third party tools, and that's where it gets wild in every direction, but it also creates room for new ideas, innovation, which later are used in "official" modern package managers built in the language tools. And yeah, nowadays I use Rust even for scripting stuff that would be easier to do in Python, just because I don't want to create a thousandth virtualenv, find a lib that does what I want but it's for Python<3.6 ou Python2 etc., so in the end it's easier in Rust even though some new libs require nightly builds of the toolchain.
- cageface 4y agoI’ve also found it not that much harder to do scripting kinds of things in Rust vs Ruby or Python. It’s a bit of extra effort of course but having a nice self contained binary at the end is pretty handy.
- jonfw 4y agoWe've been using Go to build CLI tools rather than writing scripts for certain tasks recently, and I've found that Golang is very well suited for that. we use the urfave/cli library, which works great, and gets you a ton of things for almost free (passing and documenting flags and arguments) that you just don't get easily in bash
- junon 4y agoI was going to disagree that Python's is the worst, but then I thought about it and.. yeah, it's up there. I think there are definitely some other ecosystems with worse package management systems but they're certainly not as mainstream as Python.
- tazjin 4y ago> In contrast, we apparently have no "package management theory". We have not figured out the primitives required to express dependencies We have a good hunch. The basic theory behind Nix definitely goes in the right direction, and if we look away from all the surface-level nonsense going on in Nix, it's conceptually capable (e.g. [0]) of being a first-class language dependency manager. For this to work at scale we'd need to overcome a couple of large problems though (in ascending order of complexity): 1. A better technical implementation of the model (working on it [1]). 2. A mindset shift to make people understand that "binary distribution" is not a goal, but a side-effect of a reasonable software addressing and caching model. Without this conceptual connection, everything is 10x harder (which is why e.g. Debian packaging is completely incomprehensible - their fundamental model is wrong). 3. A mindset shift to make people understand that their pet programming language is not actually a special snowflake. No matter what the size of your compilation units is, whether you call modules "modules", "classes" or "gorboodles", whether you allow odd features like mutually-recursive dependencies and build-time arbitrary code execution etc.: Your language fits into the same model as every other language. You don't have to NIH a package manager. This last one is basically impossible at the current stage. Maybe somewhere down the line, if we manage to establish such a model successfully in a handful of languages and people see for themselves, but for now we have to just hold out. [0]: https://code.tvl.fyi/about/nix/buildGo https://code.tvl.fyi/about/nix/buildGo [1]: https://cs.tvl.fyi/depot/-/tree/tvix/ https://cs.tvl.fyi/depot/-/tree/tvix/
- folex 4y agoYes! I'm in a team that works on a pet prog lang for distributed systems, and we did some research of using an existing package managing systems. We've settled on NPM for now, but god I wish there would be a better generic package manager out there.
- mijoharas 4y agoNot a generic package manager, but it's probably worth calling out asdf as the generic version manager[0] (maybe you're already aware of it, but it's a generic replacement for nvm, rvm, virtualenv, *vm, which supports any language based on plugins.) Again, maybe you're already aware of it, but I think it's a nice example of genericising a concern common to many languages which sounds similar to what you're asking for (albeit unfortunately in a slightly different space). [0] https://github.com/asdf-vm/asdf https://github.com/asdf-vm/asdf
- pastage 4y agoWhy do we need different systems for all languages, all Linux/Windows/Mac/Android distributions. Why are no one reusing what is already there. It might seem like an easy problem to fix. Rust, Java and Go certainly has their problems too, not quite sure why people feel they are good examples. I think the world is complicated and you will in the end need to support compilations/installations on AmigaOS 2.05 on m68k running in kubernetes native.
- KptMarchewa 4y agoBecause I don't want my side project to share dependencies with system-wide python.
- neilv 4y agoThe Racket module system, designed by Matthew Flatt, is great. But to fully appreciate it, it helps to understand syntax transformation in Racket. Once the rigorous phase system forces non-kludgy static rules about when things are evaluated, your syntax transformers and the code on which they depend could cause a mess of shuffling code among multiple files to solve dependency problems... until you use submodules with the small set of visibility rules, and then suddenly your whole tricky package once again fits in a single file cleanly. I leveraged this for some of my embedded doc and test experiments, without modifying the Racket core. (I really, really like single-source-file modules that embed doc, test, and package metadata all in the same file, in logical places.)
- karel_3d 4y agoI like golang package management in practice - sure, you have the "v2" thing and "every package can bump any package if you're not careful", but it works in practice because people are careful, and the minimal version selection is always deterministic. The proxy thing and the drama with sr.ht is annoying, but maybe it was solved while I didn't look.
- drewcoo 4y agoBecause of a surplus of worn out boots, candles, chickens, bowling balls (all bygone common, everyday, understandable items), and human invention (meaning "copying" badly, wheel reinvention - seldomly punctuated with novel synthesis). Or was that open source software? Or was that any private corporate software ecosystem? If I squint the problems all start to look the same. I must need glasses, considering my squint frequency.
- Falkon1313 4y agoI don't see many complaints about Free Pascal/Delphi. You want a unit? Get it, add it, use it. No 3rd party Rube Goldberg contraption needed. No package managers or dependency resolvers, no special build tooling, no lock files. No constantly having to run updates and figure out what they broke by way of transitive dependencies. Just get what you need and use it. I haven't, however, developed enough professionally with it to know how that plays out long-term in practice. But I'd have to imagine it would compare favorably to just about everything else nowadays. The things I've been using for the last couple of decades are all pretty abysmal in comparison. I'd say they were a solution in search of a problem, but people have managed to create a problem to justify the solution, which really still isn't very good. At least, not nearly as good as the simple get, add, use pattern.
- dagw 4y agoThere are two problems that make package management hard, neither which are tackled by a "Get it, add it, use it" approach. Dealing with cross platform issues and package dependencies. If we ignore these two problems then package management is easy. We could make a 'rule' that packages cannot depend on other packages, and that packages only support the single OS/CPU combo they were originally developed for, but that will cause other problems.
- tsukikage 4y agoThey all followed the same process: Step 1: look at all the existing package+module systems, and realise they are all horrible Rube Goldberg machines, way too bloated for the simple thing you want to do Step 2: write your own package+module system! It's lean, mean and just does the simple obvious thing your simple one-man project needs. Step 3: your system hits the real world! Your system is used with projects that involve more than one person and grow organically, and that spread to more and more esoteric environments. The Rube Goldberg projects have Rube Goldberg aims and their target ecosystems have Rube Goldberg requirements while goalposts shift continuously with tight deadlines. You add features and toggles to your system to support these things. Step 4: congratulations! You are the proud inventor and owner of yet another Rube Goldberg machine. It is now time to move on to better things; the system, meanwhile, is handed over to some committee and will only grow in complexity from here. https://www.kiplingsociety.co.uk/poem/poems_palace.htm https://www.kiplingsociety.co.uk/poem/poems_palace.htm
- deleted 4y ago[deleted]
- deleted 4y ago[deleted]
- Vosporos 4y agoYou might want to check PackagingCon https://www.youtube.com/watch?v=bdX1XXpLFYY&list=PLl386dCR5QGQu7XhFaVTwEGoD7fLtnGQ7 https://www.youtube.com/watch?v=bdX1XXpLFYY&list=PLl386dCR5Q...
- badpun 4y ago> neat-and-tidy (...) C++. This is a huge oxymoron. Additionally, C++ does not even have a package manager.
- noloblo 4y agoWhat about haskell cabal and stack
- hiljusti 4y agoI appreciate Hackage and its lack of garbage, although I think the exclusivity can't scale. I also like Haskell's module system All other aspects of Haskell package management feel unfinished, like "an exercise left to the reader." The lack of polish is astounding. See also: "Why I Don't Code in Haskell Anymore" (https://www.youtube.com/watch?v=SPwnfSmyAGI https://www.youtube.com/watch?v=SPwnfSmyAGI) from TsodingDaily
- whateveracct 4y agoYou don't have to use Hackage. What part is unfinished? Just docs and the verbose CLI? It solves for versions, you can declare native dependencies in various ways, it has multiple solid integrations with Nix (which in turn automatically resolves both Haskell and native deps for you). Also that video is not a compelling source. That guy is just wrong lol. Or, rather, it's just his opinion that seems to be based on the 5-10 years ago state of Haskell. I'm an engineer (professionally - in Haskell - for years), and I don't find anything about the packaging or "engineering" painful. If we're talking engineering, the optimizing compiler + RTS are extremely impressive.
- hiljusti 4y agoWell sure, there's Stackage, and there's Nix, and there's some other options. Haskell, for my money, is similar to Node.js in that I don't have confidence I could reliably expect the state of Haskell development _today_ to resemble Haskell development 5~10 years from now. There's a cost to falling behind (who wants to work on a Haskell project using 10-year-old conventions?) and there's also a cost to keeping up. Don't get me wrong, I think it's getting better. Stack is easy enough to learn, Stackage has nice for guarantees on compatibility. Nix solves some issues for deployments, although "multiple solid integrations" is maybe a too-rosy description from my experience... but I don't think that Haskell's ecosystem is in its final form yet. Not in the way that Maven or Cargo feel like they're stupid simple and here to stay.
- DemocracyFTW2 4y agoIf I wanted to point out what the greatest mistake in the conception of the NodeJS package manager—npm—is, its 'original sin', if you will, is the conceit that SemVer ('semantic versioning', a great idea in itself) is 100% reliable and that, therefore, it would be heretic or contradictory for a single module or sub-package in a project to ever want to `require()` two distinct versions of a module, say, xyz@1.0.1 and xyz@1.2.0. This is now fixed[1] but the developers stubbornly refused to see the occasional necessity of doing just this for many years. [1](https://medium.com/weekly-webtips/how-to-install-multiple-versions-of-the-same-package-in-npm-71c29b12e253 https://medium.com/weekly-webtips/how-to-install-multiple-ve...)
- jonfw 4y agoI am starting to see some consistency these days. I mostly work in Go, so I'm not intimately familiar with the state of the art in other languages, but it looks like most ecosystems have a tool that support this flow. A declarative (go.mod) file that always installs the same dependencies every build, a tool to update that lock file (go mod tidy), and an indication in the source that indicates how the dependency is being used (import).
- gwbas1c 4y agoIn C#, I liked the pre-Nuget approach where you just made sure 3rd party dlls were in a location relative to source code control, (or in source code control if they were small.) Not really "package management," but it was straightforward and worked very well... (Until you had to juggle 32/64 bit native dlls.)
- silon42 4y agoYou can do that with nuget too.
- Dowwie 4y agoYour mistake is in the use of the word "every" when in fact you've only considered a few. Rust, for instance, uses cargo for packaging and it's probably the most intuitive part of Rust (/s).
- chubot 4y agoIt's because the software ITSELF is structured poorly, not just the package managers Big pyramids of dependencies are inherently fragile (whether dynamically or statically typed) Dependency inversion can make it so that your dependency tree is exactly 1 deep, and it's dynamically wired together in main() But most people don't write code in that style. It takes extra effort
- onion2k 4y agoScope creep.
- deleted 4y ago[deleted]
- PaulHoule 4y agoPythoners have themselves to blame. The worst thing that happened to Python was that distributions like Red Hat not only shipped Python as an rpm but shipped system scripts in Python. This made it practically impossible to upgrade the system Python without breaking scripts and is fundamentally incompatible with how Python packaging works. (You are just one 'sudo pip install' from breaking your system) Like people who are impressed with ChatGPT (wow that answer seemed so confident even if it is wrong), Pythoners systematically mistake footguns for solutions. For instance, use 'pip install --user' and now the package you've included is visible when you type 'python', 'python3', use a venv, conda, whatever. I've had people tell me that having a 'python3' is the best idea anyone's had since Solomon proposed cutting a baby in half, but if you stop and think you realize that pretty soon you have 'python3', 'python3.5' (broken), 'python3.6' (maybe broken), 'python3.7', 'python3.8', 'python3.9', ... I would say venv's really solve the problem with the exception that you can currently trash all your venv's with 'pip install --user'. The trouble is that people who are bothered by this stop using Python, the people who are still using Python are people who have difficulty perceiving the nature of the problem never mind that there is a problem. The algorithm used by pip to resolve packages is not sound. It goes off trying to install things and can only find out late in the game that it installed a package which is not compatible with another package. This can be solidly blamed on the egg package format which can only determine the dependencies of a package when it tries to install it by running a setup.py. This is nice because it can adapt to the environment dynamically (say add a timezone db on windows) but it is not like Java's maven that knows it has a consistent solution before it downloads the JARs. I'm pretty sure you could make a Python package manager that works like Maven if it only installed wheels because you can read the directory of a wheel (a ZIP file) with one or two http range requests and then read the dependency data with another http range request. Poetry doesn't quite do this. Poetry does a lot better than pip does, but whatever it does takes a really, really, really, long time. Poetry might be the best thing going but it has the fundamental flaw of trying to be a 95% or 98% solution which, to the Pythoner, sounds like a good idea. The trouble is that writing programs that are 98% is to computer science what Bigfoot is to zoology or ESP is to psychology. The gap between that and 100% is not 2% but more like 200% because figuring out exactly what is wrong with the conceptual model and working around it in a hard case is at best like pushing a bubble under a rug. Imagine how much trouble you could get into with a 98% correct sort or binary search algorithm... It's a place where professional developers just don't want to go. Java has the advantage of extreme xenophobia and bad feelings all around that mean that: (1) people don't expect to link very much C code into Java, and (2) people don't feel entitled to use the Java bundled with their Linux system and have it really work. Because of (1), Java code tends to be self-sufficient and avoids a whole sector of 'dependency hell' involving .so and .dll files. Because of (2) people feel both responsible and empowered to install a JDK that works unlike the typical who Pythoner doesn't. Don't think that docker helps in any way, what I found what that Docker accelerates the ability of Pythoner to find pythons that are broken in odd ways, configured with strange default character sets and such. Javascript has the nice feature that file A can import from package version B and file C can import from package version D so that the 'diamond dependency' problems that are so terrible in Java (Like that bug in Guava post-13 that broke HDFS) and still problematic in Python rarely produce problems. (You only have problems if an object from A migrates to C and it gets used in incompatible way, contrast that to Java where probably the classloader blows up) I was wishing over the weekend that Python had something like that because once more I have been building and packaging machine learning models for inference in Python and it would be really sweet to pack up a model that uses scikit-learn or pytorch or whatever into a Python package and then load it into a web server or a batch job. It's totally practical to do that, using joblib to unpickle a few MB of code. Once you end up needing two different versions of pytorch though, you are really screwed.
- qbasic_forever 4y agoThere is no real theory because it's a solved problem--packages and dependencies form a DAG or graph and it's just an ordering and traversal problem that's easily solved. The pain and fragmentation you're mentioning is that everyone has different opinions about how they want to configure/bundle/organize code and package metadata. That's really the only core difference between deb/rpm, npm/yarn, pip/poetry/conda/<a million other python tools>, handmade makefile/cmake/autotools/etc. People just had different ideas about how they wanted to do things at the periphery. At their core all of those tools are just simple DAG walkers. Basically, you're thinking it's a technical problem when in reality it's just a social issue. Some people prefer something one way, others prefer it the other way--there is no consensus (and likely never will be, people will always be building tools to do things their way).
- jmull 4y agoWell, not DAG, because the A is for acyclic, and dependency graphs can definitely contain cycles.
- pxc 4y agoYeah, that's a misfeature. It should definitely be a DAG. Which ecosystems 'support' that besides Node?
- lamontcg 4y agoThey really shouldn't, and some dependency systems like rubygems/bundler after the molinillo switch ban them entirely.
- tremon 4y agoIn the case of immutable builds (and hence immutable dependencies), dependency graphs cannot contain cycles. At most they can have the same package occur twice in the graph, but with different dependencies or different build options.
- jmull 4y agoYou might be referring to something specific thing I'm not familiar with... generally, an immutable build doesn't impose a structure on your dependency graph, just that it can't change (in any detail, hopefully) from build to build, without an explicit change in source.
- jcarrano 4y agoBecause anyone can write a mediocre "gets the immediate problem solved" type of package manager, while designing and implementing a programming language that someone else would want to use requires way more knowledge and skill. Eventually the shortcomings of the package manager will become more evident, but at first it will seem to work and solve some pain points programmer have. Something similar goes for build systems.
- al2o3cr 4y agoTBH I think you may just have a sampling problem - the JS and Python spaces have two of the messiest package-management ecosystems.
- namelosw 4y agoModern languages like Rust and Elixir are fine. JavaScript, C/C++, Python are very old and the package systems were pretty much bolt-on. And of course a lot of historical factors were playing a bit role. In the old days, people usually start minimal. When they get burned they also find they were locked-in - thus the bolt-ons. > we apparently have no "package management theory" People are definitely standing on top of each others' shoulders. Node.js npm actually felt like Ruby package tools but also being first-party (they also cut some corners, and made some design choices - some worked well and some didn't). i.e. Hex for Elixir feels like nothing new, but avoided most common pitfalls others have experienced. I believe most language designers nowadays can do the same, given they want to play it safe and want nothing too novel.
- deltarholamda 4y agoAvoiding past pitfalls is the best part of a new language ecosystem. I remember when Python was the new kid on the block and how joyous it was to work with in comparison to Perl. By the time Ruby came around, the same thing was being said about it, sometimes with aspersions cast at Python and how wonky it was. Maybe after a few more generational cycles we'll develop the One True Language, bug-free, intuitive tooling, and sane to use.
- derefr 4y agoWhat I really want to know, is why package development is such a Rube Goldberg machine. Not for programming-language packages, per se, but rather for OS packages of simple programming-language packages. Have you tried to package a random Python/Ruby/etc. CLI program, for Debian? Or how about for Homebrew? Each one involves a cacophony of PL scripts calling shell-scripts calling PL scripts, and internal/undocumented packager subcommands calling other internal/undocumented packager subcommands. It takes ~forever to do a checked build of a package in these systems, and 99% of it is just because of how spread out the implementation of such checks is over 100 different components implemented at different times by different people. It could all be vastly simplified by reimplementing all the checks and transforms in a single pass that gradually builds up an in-memory state, making assertions about it and transforming it as it goes, and then emitting it if everything works out. You know — like a compiler.
- megous 4y agoThat's a Debian specific quirk. There are simpler, more cohesive package management systems, like eg. pacman, where package maintainers's tools mastery is not an arcane art in itself.
- rklaehn 4y agoI find cargo (rust package manager) relatively pleasant to use. It's not perfect, but it also is not a constant source of confusion like sbt (scala package manger) was back when I did scala. In the long term, I think the whole notion of a "package" is obsolete. In unison https://www.unison-lang.org/ https://www.unison-lang.org/ , code is just a content-addressed merkle tree. So dependencies are both more precise and more fine grained than packages. E.g. if there is a new version of a library, but the part of the library that you actually use is unchanged, unison will detect this and not trigger a full rebuild. The whole notion of a package becomes less important.
- hiljusti 4y agoCargo and Leiningen are the only two build/package tools I've used that are legitimately pleasant and unobtrusive. (And Cargo is more pleasant than Leiningen but I think that's the rest of the toolchain like rustc, clippy, etc) Correlation is not causation, but some food for thought is that Rust and Clojure are also consistently the top two languages in Stack Overflow survey "most-loved languages" lists.
- michael1999 4y agoPart of it is deliberately ignoring the lessons of the past because they seem like overkill. Python has the excuse that it is old enough to predate the lessons of Java and Maven. But the node and js worlds deliberately ignored things like namespaces and mandatory version specification because they were uncool. And then they had to introduce package-lock and typo-squatting defences because the complexity of the world isn't always negotiable.
- perrygeo 4y agoI'd say we have a fairly good existing theory that explains modern package management: Conway's Law. We self-organize into communities of practice and select the package management strategy that works best. Reaching across communities to develop a grand centralized strategy that fits everyone's needs would be __possible__, but involves significant communication and coordination overhead. So instead we fracture, and the tooling ecosystem reflects ad-hoc organizational units within the community. Ecosystems like Rust cargo that have batteries included from the start have an advantage, virtually all Rust developers have a single obvious path to package management because of this emergent social organization. Ecosystems like Python's seem like the wild west, there is deep fracturing (particularly between data science and software engineering) and no consensus on the requirements or even the problems. So Python fractures further, ironically in a search for something that can eventually unify the community. And python users feel the strain of this additional overhead every day, needing to side with a team just to get work done. I'd argue both of these cases are driven by consequences easily predictable from Conway's Law.
- MuffinFlavored 4y agoIs there a name for a phenomena/theory that states "the more people you add to a problem while asking them to solve it in an opinionated way, the more likely you are to get conflict/fragmentation/less people agreeing overall as consensus gets diluted and number of possibilities/opinions increases?"
- sixstringtheory 4y agoMaybe it should be called Lydgate’s Law: “You can please some of the people all of the time, you can please all of the people some of the time, but you can’t please all of the people all of the time.”
- thenerdhead 4y agoHave you read https://medium.com/@sdboyer/so-you-want-to-write-a-package-manager-4ae9c17d9527 https://medium.com/@sdboyer/so-you-want-to-write-a-package-m... ? The author does a great job pointing out the problems, theory, and ecosystem change that makes it a Rube Goldberg machine. By definition, a package manager is always "incomplete" because it cannot catch all the security vulnerabilities, binary compatibility, or knowing the dependencies ahead of time nor their interactions together. Thus it can be unsuccessful at managing dependencies - its primary job. Source: Also work on a notable package manager.
- jerf 4y agoA solution can not be simpler than the problem. The problem is a classic "looks simple until you really examine it".
- TillE 4y agoThis is the answer. If you really want to learn about the issue, try designing a package manager in detail, and be sure to handle the thousands of edge cases which arise in real world usage.
- intrasight 4y agoI'd think that with all the CS PhDs, there'd be some academic work in this area. I haven't gone looking. My experience as a .Net developer has not been that it's a Rube Goldberg machine. I isolate all my projects and minimize 3rd party dependencies.
- warrenm 4y agoIt's far simpler than you think It all boils down to NIHS - "not invented here syndrome" Between developers being suspicious of anyone else's work, and their innate love to build things they'll use (your wheel is cool, I guess...but MY wheel does THIS!) ...you get a gajillion libraries that overlaps 95% of the time (but never on the 5% you "care" about) Eons ago David Pogue wrote in his review of Word (98, I think) for the Mac, "MacWrite fit on one floppy disk and had 95% of all the features I've ever needed in a word processor. Word take a CD, and has 96% of all the features I've ever needed in a word processor." Why is Word so big? Is it because a 'word processor' needs to be that big? Why are there so many libraries with incredibly weird interdependencies (version 1.9.2a of this lib needs 2.1.x2 of that one, not 2.1.x3 or 2.1.g7; but if you have version 1.9.3 of this lib, you can use 2.1.x2 up through 2.1.x9 ot he other one)? Same thing - somebody somewhere sometime somewhy decided to use that library in their own stuff, and is now forever and always bound to it (...until they refactor or rewrite a perfectly good tool that was in Scala into Haskell)
- Pet_Ant 4y agoI think the issue is how hard it is to test with a range of package versions. Maven initially supported package ranges, but that got dropped in favour of repeatable builds.
- jrockway 4y agoYou mention Python and Node, which are programming language that unusually require end users to have the text of your program and all its dependencies on their own machine, and the languages store some parts of your program in /usr/lib and other parts of your program in your source directory. (npm does a little better here and at least puts the dependencies in your project directory.) Those constraints make development and packaging hard no matter what. Python and Node both need a way to compile the code down to a single statically-linked binary like more modern languages (Go, Rust), solving the distribution problem once and for all. There are module systems that aren't insane, like Go's module system. It uses semantic versioning to mediate version conflicts. Programs can import multiple major versions of the same module. The module requirements files ensure that every checkout of the code gets the exact same bytes of the code's dependencies. The compiler is aware of modules and can fetch them, so on a fresh workstation, "go test ./..." or "go install ./cmd/cool-thing" in a module-aware project works without running any other command first. It is actually so pleasant to use that I always think twice "do I want to deal with modules" before using a language like Javascript or Python, and usually decide "no". npm and pip are the DARK AGES. That's why you're struggling. The community has been unable to fix these fundamental flaws for decades, despite trying in 100 incompatible ways. I personally have given up on the languages as a result. The standard library is never enough. You HAVE to solve the module problem on day 1.
- briffle 4y agoif npm and pip are DARK AGES what does that mean perl's CPAN is?
- jrockway 4y agoI haven't used Perl for 15 years, but it was pretty miserable back then. Obviously I had my workflow and didn't run into too many problems, but I was certainly nervous about how I could share my work with other people. (Putting it into prod wasn't that bad. I don't know why, but it always went OK. CPANPLUS helped at the time.) I used to teach Perl trainings as a side job, and people would literally be in tears over @INC. It was bad. I don't use Python much these days, but it's not as bad as Perl 15 years ago. I see blog posts like "how to set up the perfect Python dev environment with Docker" and it makes me very sad, but at least teams are getting their work done. The edge cases of Python packaging, though, are really really bad. For example, the C compiler that Python was compiled with (and C library; musl vs. glibc) affects installability of modules through pip. This really forces your Linux distribution to be the arbiter of what modules you can use, which is always too out of date for development. Also, the exact requirements (what are the sha256s and URLs of the code files that this code depends on) depends on architecture, compiler, etc. As far as I can tell, you have to run code to find the whole dependency tree. That is the fatal flaw I see with Python's packaging system. I spent a lot of time trying to use Bazel to unify all the work my company does across languages. Python was the killer here. We do depend on a lot of C extensions, and I have a C toolchain built with Bazel (so that arm64 mac users can cross-compile to produce Linux releases; maybe a dumb requirement, but it would be too unpopular to discriminate against certain developer devices), but getting Python built with that toolchain, and using that Python to evaluate requirements.txt didn't work. (There are bugs open; they all end with "Python has to fix this".) As a result, you don't get compatible versions of, say, numpy with this setup. Dealbreaker. Partially Bazel's fault, partially Pyton's fault. (It pained me to use Bazel for Go, but it did all work. While the workflow wasn't as nice as what Go has built in, easy things were hard and hard things were possible. I had working binaries within a few hours, buildable on any supported workstation type, with object and test caching in the cloud.)
- Someone 4y agoIf you let everyone and their dog create and maintain packages and package dependencies and leave it to them to declare forward/backward compatibility between versions of packages, and your package manager ends up being popular, I think it’s unavoidable that you end up with a mess. Foo may not be updated for Bar 2.0, while the Baz you use states it needs it, Bar 3.0 may incorrectly declare to be a 100% stand-in for anything between Bar 1.5 and Bar 3.0, Baz and Qux may contain similar functions that would better be part of their shared dependency Quux, etc. Tooling can make navigating that mess more or less difficult, but the mess still is there.
- lloydatkinson 4y agoHave you used nuget for .NET? I have to say I've never once run into any of the problems I encounter sometimes weekly with NPM for Node.
- hardware2win 4y agoIndeed, people act as if package managers were some Turing award level problem because they havent tried ecosystems that at least try to provide good ux like rust or .net
- lloydatkinson 4y agoIt's actually a nice change when I'm working on a .NET project knowing that some random dependency or NPM type problem is literally never going to be a problem with nuget.
- samsquire 4y agoI think the problem is the answer to this question: What is harder regarding computation - arranging for a computation or doing the computation? What I mean is that the computation of an addition or subtraction is easy but the arranging of instructions of code into an algorithm is hard. Everything has to be in the right place for the algorithm to work right. This is why packaging is so difficult. Each algorithm and code expects things to be in a certain place. ABIS and packaging for them is tedious.
- maximumcomfy 4y agoA few reasons: 1) Every developer no matter how new wants to contribute something. 2) There is no centralized authority in most languages/package system to stop them doing so 3) Imagine all the bad code you write in the first 2 years but now you can't delete it because 100 other developers rely on it and 100 other developers rely on them The rube goldberg machine exists because of the matryoshka dolls that is the dependency tree. Sometimes rewriting things is actually easier than trying to untangle the wire of dependencies.
- tstrimple 4y agoAlmost any trivial application can be trivially implemented using these build systems. People encounter their own “unique” edge cases and build their own “unique” solutions to them. Over time, all these edge cases result in a proliferation of bubble gum, duct tape and baling wire that you’ve described.
- digitalpacman 4y agoHave you experienced nuget? Seems pretty solved and solid and unchanged since... forever now.
- sinenomine 4y ago"The entropy-pool, a reservoir of dumped complexity"