Dependency injection is dynamic scoping in disguise
I agree that dependency injection and dynamic scoping are similar and I think they are both anti-patterns.It doesn't make sense to stub out dependencies in unit tests (unless you absolutely have to). Stubbing out dependencies is like stubbing out native functions, operators or loops. They are called dependencies for a good reason; because your class depends on them and assumes that they work. Trying to make dependencies substitutable is overengineering and leads to poor design and gives you more work when implementing unit tests.Dependency injection is particularly bad because it makes it difficult to find the path to the dependency's source code (which is critical for debugging). Hiding the source path of a dependency is a terrible anti-pattern. When it comes to programming, there are few things more horrible than not being able to determine where some buggy piece of logic is located. I cannot imagine any use case where that would be a fair tradeoff.Any kind of injection of dependencies should be done via an explicit method/constructor parameter. Sometimes it means that the dependency instance has to traverse a few classes in the hierarchy, but that's way better because at least you can unambiguously track where the dependency came from. Also, if the dependency has to traverse A LOT of classes, then you know there is probably something wrong with your architecture (e.g. a dependency imported too high in the hierarchy and used in a deeply nested class can indicate poor separation of concerns and leaky abstraction between components).