Fragmentation
theprogrammersparadox.blogspot.com
theprogrammersparadox.blogspot.com
This is such a good line. Most dependencies I see in enterprise software fail miserably at this and that's why they think they need a monorepo.
I've found that people with substantial open source experience are often much better at figuring out what the 'natural' lines are because they tend to see the modules and libraries which they produce as final products. Their libraries are designed to be highly composable and cater to a broad range of use cases and systems.
The key is writing components that are generic and broadly compatible. You want to avoid putting business logic into your dependencies. Try to keep all the business logic at the highest level possible in your code.
It's very simple if you think about it; just imagine that you're a new developer on a large project, what would you want the code to look like? Most likely, you want to be able to understand what the system is doing by reading as few files as possible and you want the system's features to map to these top-level files in an obvious way.
Because when you're debugging a feature, the first thing you need to do is figure out where in the code that feature is implemented. If you can't come up with a simple answer to this, then your system is probably poorly implemented.
At the same time, too much fragmentation will lead you to, indeed, have so many callbacks and other "controller" classes that you'll need a non-trivial amount refactoring anything you need to add a new feature, because the previously chosen lines of delimitation don't correspond to what the new feature needs.
P.S. in any case, a robust interface specification is a prerequisite to good engineering.
Brian Will has a very good video explaining this (timestamp is where he talks about encapsulation).