5 ms·
That example code looks like the worst of all worlds. First off you aren't using interfaces, which makes it unclear how you're writing test versions of your cl
by Someone1234 5y ago
That example code looks like the worst of all worlds.
First off you aren't using interfaces, which makes it unclear how you're writing test versions of your classes, but also you're setting up a massive foot gun by having a dependancy-injector with completely uncoupled consumers later in that same class. For example if I have multiple setService (e.g. serviceA, serviceB, and serviceC) and I want to call .afterPropertiesSet(), how do I know which it depends on externally? Do I have to go inspect afterPropertiesSet()'s code? Or just wait for an exception to be thrown in a Run<->Throw<->Fix endless cycle? Eww.
There's a very, very, good reason why all DI frameworks have you use interfaces and the class's constructor to inject. Because if injection happens during class construction, every call after can make the assumption those things exist. By decoupling that assumption from those calls, you've created a development hell (i.e. this is an unmaintainable mess).
There're two good ways to do DI:
- During class construction. They then always exist in the class's scope.
- Every method call individually takes in all explicit dependencies (e.g. GetMagic(iDatabase database, iDateTime dateTime, ...)).
Your example is neither of those.
- vbezhenar 5y ago> First off you aren't using interfaces, which makes it unclear how you're writing test versions of your classes Use interfaces if you want, there are different approaches to testing. Some classes are fine to inject as they are. Some classes are fine to mock with libraries like Mockito. And sometimes interfaces makes sense. > For example if I have multiple setService (e.g. serviceA, serviceB, and serviceC) and I want to call .afterPropertiesSet(), how do I know which it depends on externally? I'm not sure I follow you. You just wrote that class, surely you know what dependencies you need. > There's a very, very, good reason why all DI frameworks have you use interfaces and the class's constructor to inject. You're wrong here. I don't know a single DI framework that forces you to use interfaces and constructors. Setter injection or field injection is supported everywhere, at least in Java world. > By decoupling that assumption from those calls, you've created a development hell (i.e. this is an unmaintainable mess). I used that approach. It works good and it scales without issues with quite complex dependency chains. One issue is a little bit of mundane work, but it's not a lot and simplicity worth it. > There're two good ways to do DI: > - During class construction. They then always exist in the class's scope. Constructor injection is terrible approach to use without DI framework. You'll need to move your initialization code around almost every time your dependencies change. You inevitably will invent yet another DI framework, buggy and incomplete and at this point you lost. Also it does not allow for circular dependencies, which sometimes are necessary. Another point is that Java does not have named parameters and long constructor calls are hard to read (recent Idea improves that a little bit with inlay hints, though). > - Every method call individually takes in all explicit dependencies (e.g. GetMagic(iDatabase database, iDateTime dateTime, ...)). That's not a dependency injection, as it requires to pass dependencies through every call chain. If you suddenly need some service deep inside your chain call, you have to change all functions which lead to that call. It might be a suitable approach for some 1000-LoC one-file program, but it does not scale.