upvote
> 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