Clean Code Talks - Dependency Injection

by Miško Hevery

Google Tech Talks
November 6, 2008

ABSTRACT

Clean Code Talk Series
Topic: Don't Look For Things!

Speaker: Miško Hevery

Video



Slides

Permalink | Links to this post |
The comments you read here belong only to the person who posted them. We do, however, reserve the right to remove off-topic comments.

2 comments:

Yorgos Pagles said...

This is an extremely helpful talk. But I wonder how can the factory / builder step of wiring the dependencies together can work in C++.
I.e. we have a class A that depends on B. The builder will allocate B in the heap, pass a pointer to B in A's constructor while also allocating in the heap and return a pointer to A.
Who cleans up afterwards? Is it good to let the builder clean up after it's done? It seems to be the correct method since in the talk it says that the builder should setup objects that are expected to have the same lifetime or at least the dependencies have longer lifetime (I also have a question on that). What I mean in code:

class builder {
public:
builder():m_ClassA(NULL),m_ClassB(NULL) {}
~builder() {
if (m_ClassB) {
delete m_ClassB;
}
if (m_ClassA) {
delete m_ClassA;
}
}
ClassA *build() {
m_ClassB = new class B;
m_ClassA = new class A(m_ClassB);
return m_ClassA;
}
};

Now if there is a dependency that is expected to last longer than the lifetime of the object we are injecting it into (say ClassC is that dependency) I understand that we should change the build method to something like:

ClassA *builder::build(ClassC *classC) {
m_ClassB = new class B;
m_ClassA = new class A(m_ClassB,classC);
return m_ClassA;
}

Doesn't this bloat the interface of the builder? Is there another way?

Scott Vachalek said...

Hi Yorgos,

If I am understanding your question correctly, and correctly mimicking your C++ syntax, your build method should look more like this:

ClassA *builder::build() {
m_ClassB = new class B;
m_ClassC = new class C;
m_ClassA = new class A(m_ClassB,m_classC);
return m_ClassA;
}

In other words, you want to concentrate all of the "wiring" information in one place if possible.

In practice, in a large system, this makes for a very bloated builder. The way Guice handles this is that the associations between interfaces and implementations are broken into modules, which are passed to the injector which then uses the accumulated mappings to construct and assemble the necessary objects.

I haven't done C++ in many years so I don't know if there's a C++ equivalent of Guice or Spring but it is worth searching for -- no doubt the authors have thought about the issues of memory lifecycle management that we can ignore in the Java world.