Ah, I see — I misinterpreted your previous response. Somehow, I interpreted it as a suggestion to *only* inject the top-level classes, and pass the rest of the arguments in constructors. That isn’t what you suggested.
But my general point about constructor injection is that it can result in clients having to know more the internal workings of dependencies than I personally would prefer. If you ever have a use case where you need to instantiate an object directly instead of obtaining it from a registry, you now have to know about that object’s dependencies.
Consider the example of our classes A, B, and C where A needs to instantiate B. The constructor injection form of this might look something like this, in pseudocode:
public class A {
public void doSomething() {
C c = Registry.getC();
B b = new B(c);
b.doThing();
}
}public class B {
private final C mC; public B(C c) {
mC = c;
}
}
The field injection form of this would look something like this:
public class A {
public void doSomething() {
B b = new B();
b.doThing();
}
}public class B {
@Inject C mC;
public B() {
Registry.inject(this);
}
}
Imagine we refactor B to now depend on C and D. In constructor injection world, you’d need the following:
public class A {
public void doSomething() {
C c = Registry.getC();
D d = Registry.getD();
B b = new B(c, d);
b.doThing();
}
}public class B {
private final C mC;
private final D mD; public B(C c, D d) {
mC = c;
mD = d;
}
}
And you can see where this starts to get slightly nastier than the field injection version, where only the implementation of B needs to change.
Of course, in a world where all instantiations are only performed by your Registry class, this doesn’t matter much. The A class would never need to instantiate a B object directly — instead, it would just call Registry.getB(), so only the implementation of Registry needs to change. But from what I’ve found in my apps, attempting to force everything to be instantiated only via the Registry becomes tricky.
I agree with your initial point — if you’re limiting where you use field injection, you probably don’t need a library like Marinator. As long as the only places you use field injection are in your top-level Android framework classes, you may be fine just reaching into the Application directly. It’s just that I have found field injection to be more helpful in certain cases.
So I think this is a case where we may just have to agree to disagree about the relative pros and cons of constructor vs field injection. But thank you for a thought provoking and interesting discussion!