When you start using dependency injection (DI), you probably come from the painful world of singletons. Singletons are a lie. When we were doing structured programming (remember? What we did before OO?), that was called “global variable” and everyone knew they were bad. But hey, OO came along and we had the same problem and to solve it … we used global variables. Only we didn’t name them that. We said “It’s a Singleton!” and everybody was happy.
Except that the mighty singleton has the same problems as the global variable – because they are the same thing.
A solution was sought and DI was invented. When people start to use DI, they are still in the “Singleton” mind because you can’t get rid of an idea that has served you (more or less) well over many years. Since a human can’t simply forget what he’s been doing for a long time (it’s traditional), singletons leaked into DI leading to odd design which felt wrong.
Software developers are paid for their brains. If something feels wrong, it usually is. Most of the early code we come up with then starting with DI violates the Law of Demeter.
A common solution to the problems with many singletons is to replace them with a single singleton (for example one which loads and offers the application context in Spring). While this is convenient, we still have a global variable left.
Another solution is to write constructors that take 27 parameters so you can pass in all the parameters. If you avoid that trap, then your class will have 27 setters. Holy Ugly, Batman.
How to solve that? Use more DI. Most of the 27 ex-singletons will be passed on to other worker classes. So instead of passing on the singletons to create the worker classes deep down in the code, create the worker classes using DI (so the DI framework can fill in all the ex-singletons they need) and then pass in the 2-3 workers.
For some code, see this article: Dependency Injection Myth: Reference Passing