I have a Presenter which has multiple dependencies that are provided by the ApplicationComponent
. Now the general pattern I've used is to use an @Inject
constructor for the presenter.
But I have a case where the presenter has around 6 dependencies. Is constructor injection still the best practice in this case? I find the constructor to become very unwieldily in such a situation. Is there another way that I'm missing?
As in the comment by EpicPandaForce having a lot of dependencies in a Presenter may be a sign that the presenter does too much. Indeed, in MVP it is easy for the Presenter to degenerate into a "god object". Still, it seems that a multi-parameter constructor is preferable to mutable classes with getters and setters or to property injection which, as in the comment, hides the number of dependencies.
If you cannot refactor your presenter e.g., by finding a higher-level abstraction for it to depend on, the types of issues that arise from constructors with a large number of parameters are addressed in Chapter 2 of Effective Java by Joshua Bloch.
One option is to convert the constructor to a builder (Effective Java Item 2). So instead of:
public Foo(Bar bar, Baz baz, Zap zap) {
this.bar = bar;
this.baz = baz;
this.zap = zap;
}
You have:
public class FooBuilder {
private Bar bar;
private Baz baz;
private Zap zap;
public FooBuilder setBar(Bar bar) {
this.bar = bar;
return this;
}
public FooBuilder setBaz(Baz baz) {
this.baz = baz;
return this;
}
public FooBuilder setZap(Zap zap) {
this.zap = zap;
return this;
}
public Foo createFoo() {
return new Foo(bar, baz, zap);
}
}
This is just the auto-generated Builder you get from using Android Studio's Refactor/Replace constructor with builder
function.
Alternative, you can extract a parameter object however you would arguably be violating the Law of Demeter in doing so:
class FooParams {
final Bar bar;
final Baz baz;
final Zap zap;
FooParams(Bar bar, Baz baz, Zap zap) {
this.bar = bar;
//etc
}
}
public Foo(FooParams fooParams) {
this.fooParams = fooParams;
fooParams.baz.doBazThings(); //etc
}