Most of my production code has fixed types of dependencies, illustrated below: the House
for example, at run time, always depends on the same Kitchen
.
Therefore, I am wondering what I gain by having the House
force whoever constructs it to inject its dependencies as opposed to provide the option to inject the dependencies, i.e. provide both a default constructor and a DI-constructor?
What you lose by not allowing default construction is easily seen if you compare mainDI
and mainDefault
.
Even if each class has only has two dependencies, if the dependency hierarchy depth is 3, as for example in the House -> Bedroom -> Bed
path, you have to instantiate 2^3 objects in your top level class which seems unfeasible for large projects with a dependency hierarchy depth of 10 or more.
Having the DI constructor, I am still able to unit test a class.
So for all the DI experts out there, what is the downside of this approach?
struct House {
House(Bedroom ib, Kitchen ik) : b(ib), k(ik) {}
House() : b(Bedroom()), k(Kitchen()) {}
private:
Bedroom b;
Kitchen k;
}
struct Bedroom {
Bedroom(Bed ib, Lamp il) : b(ib), l(il) {}
Bedroom() : b(Bed()), l(Lamp()) {}
private:
Bed b;
Lamp l;
}
struct Bed {
Bed(Frame if, Mattress im) : f(if), m(im) {}
Bed() : f(Frame()), m(Mattress()) {}
private:
Frame f;
Mattress m;
}
mainDefault() {
House h()
}
mainDI() {
Frame f;
Mattress m;
Bed b;
Lamp l;
Kitchen k;
Bed b(f, m);
Bedroom br(b, l);
House h(br, k);
}