>it's an architectural approach used primarily for managing separation of concerns and modularisation
That always feels like a post hoc justification to me. If you demand 100% test coverage on a Java/C# project then you will almost certainly end up with some kind of dependency injection at the end. Whether that is useful or not is often debatable.
Dependency injection where the injected dependencies are interfaces - particularly, interfaces designed to provide the minimal external requirements of the module - has a broad architectural impact on the design and implementation of a system than just enabling unit testing. It enables isolation, decoupling and modularisation and clarifies the system interactions.
> It enables isolation, decoupling and modularisation and clarifies the system interactions.
That’s what Spring claims but the truth is that using interfaces enables those things. Dependency injection might encourage the use of interfaces, but it also inserts an abstraction between tests and the things you want to test.
In my experience dependency injection frequently obfuscates system interactions and invalidates any assurances you might get from good unit tests.
Dependency injection is just a tool. It can be useful but is often misused and doesn’t perform magic.
You can do dependency injection without a DI framework/container, just declare the required dependencies for a class as required parameters in the constructor and build your own dependency tree manually when constructing the objects in `main()`-equivalent.
Using a DI container is not required to implement the DI pattern, it's just a tool that facilitates some more complex DI.
I tend to prefer to keep my projects simple enough that manual DI is quite appropriate and readable.
As the other commenter points out, I believe you are conflating DI implementations with Dependency Injection as a methodology. But I suppose I am too, because really I'm talking about using dependency injection to achieve Dependency Inversion - the D of the SOLID design principles.
There are good and bad implementations of dependency injection (or, perhaps, appropriate and inappropriate depending on requirements), but the principle of dependency inversion applies at an architectural level, before specifics of implementation and things like unit testing come into play
That always feels like a post hoc justification to me. If you demand 100% test coverage on a Java/C# project then you will almost certainly end up with some kind of dependency injection at the end. Whether that is useful or not is often debatable.