That's not an answer when the entire ecosystem is built around the idea of adding lots of dependencies to do stuff. I don't need no dependencies, I'd like to live in a world where I can add two or three. But if the culture is so far gone that those two or three transitively import 20 each, I don't have that as an option—it's all or nothing.
> That's not an answer when the entire ecosystem is built around the idea of adding lots of dependencies to do stuff.
Again. Don't add dependencies. Just don't. Vendor it yourself. Or write it yourself. Absolutely nothing is forcing you to use the dependencies except your own desire to save time.
Cargo is giving you the option to A) save your own time B) minimize dependencies. You choose A) and blame Cargo.
I don't think it's entirely fair. You're telling me "don't use any dependency at all". Vendoring is not a solution, because it does not remove the transitive dependencies. So I have to essentially rewrite it myself.
I find many libraries in C++ that don't pull 20 dependencies. It's common for me to have a C++ project that has ~6-8 dependencies. In Rust I have never seen that. Either I have no dependency at all, or I have 100+.
I actually had this toy project that I wrote both in C++ and in Rust, for the learning experience. Both did exactly the same thing, with a very similar design. In C++ I had 8 dependencies. In Rust, 186. The thing is, 186 is enough for me to not even read all their names in the lock file. As soon as 25 dependencies magically appear in my lock file, I stop caring and start YOLOing it.
> Vendoring is not a solution, because it does not remove the transitive dependencies. So I have to essentially rewrite it myself.
Vendoring means, you fork it, make any modification you want, such as reducing the number of dependencies, but keeping it up to date with upstream is on you.
Rewriting it for yourself is what happens in C++. C++ didn't get flatter by waving a magic wand, it just moved the slider. It's just that code reuse is hard, so you rewrite things that would be a shared dependency in Rust into a header file and call it a day.
> I find many libraries in C++ that don't pull 20 dependencies.
I can find many libraries in Rust that don't pull 20 dependencies (mostly by searching crates written by people like the_mitsuhiko). Some people care, but they are a minority. If you truly care about this, like the_mitsuhiko does, write it with no dependencies.
I, personally, try to minimize my dependencies, but there is a reason why most people don't care - it has little to no impact on them and saving time by NIH is better than not learning from history and reinventing wheel only square.
---
Problem is: There are infinitely many of properties to improve (number of dependencies, byte size, compile time, run time, alignment, crates not made by X, time to market, reproducibility, compliance with law XYZKM, safety etc.) and not enough time or possibility space to do them all.
> you fork it, make any modification you want, such as reducing the number of dependencies, but keeping it up to date with upstream is on you.
Say a pretty complex library has 30 dependencies. I fork it, I remove the dependencies, and now it doesn't build anymore. What do I do?
I feel like you're saying "You should not write the small feature you need yourself. Instead, you should heavily modify a big dependency that contains the feature you need, because that's certainly easier and better".
If the library did not rely on those 30 dependencies, it would not depend on them, would it?
> If you truly care about this, like the_mitsuhiko does, write it with no dependencies.
So you start by telling me that I should just remove the dependencies from my dependencies, and then you tell me that you don't do that and instead choose dependencies that don't have many dependencies themselves? It feels like we agree...
> not learning from history and reinventing wheel only square
This is the thing: "I learned from history so I don't reinvent the wheel" should not be treated like a religious belief. It's probably not a good idea to write your own kernel. But I often spend a day or two implementing a feature that I would have gotten from a dependency in 2h. And it's almost always worth it! And sometimes I depend on libraries (e.g. I usually don't rewrite an HTTP library).
> So you start by telling me that I should just remove the dependencies from my dependencies, and then you tell me that you don't do that and instead choose dependencies that don't have many dependencies themselves? It feels like we agree...
There are two cases:
1. You have 100 dependencies.
2. You just started writing your code.
If you are doing 1) then you have to vendor/fork till it's acceptable.
If you are starting from 2) just don't add them.
> This is the thing: "I learned from history so I don't reinvent the wheel" should not be treated like a religious belief.
Nothing in programming should be treated as religious belief. But duplicating code can be just as deadly as dependencies glut, taken to it's logical extreme.
A golden middle approach is best, sadly no one can agree on it.
> A golden middle approach is best, sadly no one can agree on it.
That's what I was saying: I think that we agree there. My initial point was that I don't think that the package management culture in Rust is a middle approach: it feels like most crates don't care about how many random dependencies they pull.
> My initial point was that I don't think that the package management culture in Rust is a middle approach
And I don't care about "cultures". They come and go, and change with time. What I care about are unchanging things - the programs.
Sane package managers allow you to make your code however you want to. OSS allows you to tweak the code in whatever way you need, arguing for CMake over npm is frankly baffling.
I was really talking about culture, which is important to me. The fact that many devs assume that everybody using Linux is on Ubuntu is culture, right? In Rust, it is often assumed that Rust was installed with rustup. It's nice to say "you are not forced to use rustup", but if it doesn't work when you don't, then you are kind of forced :-).
> Say a pretty complex library has 30 dependencies. I fork it, I remove the dependencies, and now it doesn't build anymore. What do I do?
If you don't know what to do in this situation it means you don't know how your dependency works, which means you've abdicated responsibility for your own code's runtime behavior. Please don't take this as accusatory, I do this almost every single day at work because it's unavoidable--I'd be fired if I didn't. But it makes me feel dirty.
The alternative is just as grim. I heard[1] that Excel went with the slogan "kill your dependencies" at least during Joel Spolsky's time. This ended with Excel team building and shipping their own C compiler.
Imagine NIH so hard, you start rewriting the compiler.
> Vendoring means, you fork it, make any modification you want, such as reducing the number of dependencies, but keeping it up to date with upstream is on you.
This is not what vendoring means, this is called forking. Vendoring is just the copy+commit phase, not the modification part.
Dunno. That's what one project I worked on called it. Forking code on GH, pulling as submodules and maintaining it (most repos were unmaintained for years).
Just don't add dependencies, it's that simple. If you have enough time to control C++ dependencies, you can control them in Rust as well.