When teams grow, so does the communication overhead. When a team is a dozen people, daily standups take too long. Keeping up with what a dozen other developers are up to takes a big portion of your day. At some point the large team splits, hierarchy emerges, responsibilities are divided. You don’t keep up with what every person is doing, but you may know what each team as a whole is working on.
Code has the same problems. When a dozen classes work together intimately, the dependencies get nutty. When it’s fifty? Forget about it. The same communication overhead exists for code. Risks of communication breakdowns (bugs) is very high.
Treat your code like your human workers. Break it into teams (namespaces, packages, modules) of eight classes or fewer. Classes or functions used by only one other class don’t count; it’s the interconnecting lines of communication we want to minimize. Each team has one public interface.
Each team member (class) can only have one task in progress, one responsibility. When a team is working on two projects, break it up. Add hierarchy, reduce communication channels, and hire some middle managers if you have to. They won’t be such a burden; code is not power-hungry by nature.
Communication overhead applies to code as much as to people. Organize your components and keep them isolated. You may find such treatment cruel and dehumanizing, but the code won’t mind.