upvote
Many small crates published by large, trustworthy projects are fine and preferable to one large crate that "does everything".
reply
Why?

Honest question. Commons, Guava, Spring, and more seem to take this approach successfully (as in, the drawbacks are outweighed by the benefits in convenience, quality, and security) in Java. Are benefits in binary size really worth that complexity?

And before someone says “just have a better standard library”, think about why that is considered a solution here. Languages with a large and capable standard library remain more secure than the supply-chain fiascos on NPM because they have a) very large communities reviewing and participating in changes and b) have extremely regulated and careful release processes. Those things aren’t likely to be possible in most small community libraries.

reply
> Honest question. Commons, Guava, Spring, and more seem to take this approach successfully (as in, the drawbacks are outweighed by the benefits in convenience, quality, and security) in Java.

Commons and Spring have spent significant effort to break themselves up in the past, and would probably come as aggregations of much smaller pieces if they could be started today with the benefit of hindsight.

reply
Why? It's the essence of "Simple Made Easy": you don't have other code to complect with. You have a smaller interface, focused on a singular goal. When a library has to work as a standalone project, it can't be accidentally entangled with other components of a larger project.

Smaller implementations are also easier to review against malware, because there are fewer places to hide. You don't have to guess how a component may interact with all the other parts of a large framework, because there aren't any.

There are also practical Rust-specific concerns. Fine-grained code reuse helps with compile times (a smaller component can be reused in more projects, and more crates increase build parallelism).

It makes testing easier. Rust doesn't have enough dynamic monkey-patching for mocking of objects, so testing of code buried deep in a monolith is tricky. Splitting code into small libraries surfaces interfaces that are easily testable in isolation.

It helps with semver. A semver-major upgrade of one large library that everyone uses requires everyone to upgrade the whole thing at the same time, which can stall like the Python 2-to-3 transition. Splitting a monolith into smaller components allows versioning them separately, so the stable parts stay stable, and the churning parts affect smaller subsets of users.

reply
Tangent, but thanks for adding "complect" to my vocabulary!
reply
You will have lots of dead code in your build.

That dead code might have "dead dependencies" - transitive dependencies of its own, that it pulls in even though they are not actually used in the parts of the crate you care about.

In the worst case, you can also have "undead code" - event handlers, hooks, background workers etc that the framework automatically registers and runs and that will do something at runtime, with all the credentials and data access of your application, but that have nothing to do with what you wanted to do. (Looking at you, Spring...)

All those things greatly increase the attack surface, I think even more than pulling in single-purpose library.

reply
Libraries like Guava and Commons don't have transitive dependencies - they are self contained except for other parts of the same library.
reply
The same issue occurs whether you bundle all the code together or not, it's just that if you bundle it together you don't see what's happening and you can't use only part of it easily.
reply
Yeah I’d agree that multiple crates under one project is basically the same as 1 large crate. The real problem is how many people you’re trusting and it’s all coming from the same person.
reply
Contrary to what the article here presents, Rust does not have a culture of microlibraries like NPM does. The author and their LLM are cargo-culting a criticism of Rust made by people whose only experience is with the Node ecosystem. The Rust stdlib may not be especially "wide" compared to languages like Python, but it is quite deep, with the objective of making it so that you don't feel the need to publish single-purpose libraries which only exist to fix papercuts. Dozens of new APIs get added with every Rust release, which, occurring every six weeks, amounts to hundreds per year.
reply
What are you talking about? Every Rust project I see seems to have 5 dependencies that do some simple thing that should be in the standard library, or at least in some centrally-audited monolibrary of utilities.
reply
Perhaps you're referring to things like regex and rand (each of which is itself multiple crates for the purpose of code organization), which are all first-party crates provided by the Rust organization itself, simply shipped and versioned separately from the standard library? If you trust the Rust organization enough to install and run the provided toolchain binaries on your machine, then you trust them enough to depend upon the dozens of crates that are provided under the umbrella of the Rust project.
reply
Can you name 5 as an example?
reply