As you can see, either of these approaches is really just variations on a theme. The idea is that Foo, until runtime, does not know what kind of Bar it is using. This provides two major benefits, one, as you can see above, it eases testing. We can create test versions of objects, called “Mock Objects” to pass into the class we want to test. These mock objects are simplified versions of objects that the tester controls very closely, making it easier to test Foo in isolation. Additionally, with our mock objects being an example of this, this approach also allows infinitely configurable objects. This greatly increases reusablility of anything we build, and instead of going the old way of creating yet another object per configurable item, we instead just create the basic underlying class generically and plug in it’s dependencies when we need one.

For instance, if we needed a single threaded Foo and a multithreaded Foo, pure object inheritance and old style object oriented design might tell us to have both types of Foo inherit from some interface, and we differ their threading behavior based on the two implementations. But now what if we have another variation in Foo’s, maybe we have one that is designed to deal with a certain protocol – say, deal with information coming in from the web, while another Foo is designed to deal with information coming in from a local database. Now, really, we have to build 4 foos, a single threaded internet one, a single threaded database one, a multithreaded internet one, and a multithreaded database one. Vary security policies, memory management issues, and other things, and you can see how object hierarchies can explode with what might be called “cross-cutting concerns.”

Using dependency injection solves this, by creating only one Foo object and allowing the caller to vary the threading policy or data sink independently, as needed. This is also called the “Bridge Pattern”, among other things. If you belong to the camp that claims patterns are simply proof of missing language features, then the Bridge Pattern might be seen as an object-oriented ‘solution’ to the problems solved by what’s called Aspect Oriented Programming, however, we’re not going to get into that right now.

There are some minor downsides to this approach, as it incurs a runtime penalty as all these polymorphic objects are created, and the caller must also know a little more about the object its creating – breaking encapsulation, to a degree. Additionally, more overhead is required as a bunch of boilerplate factory objects need to be created.

For C++, you can use the exact same solution – pass in factory objects to another object’s constructor and then use the factory to configure the constructed object at runtime. The same upsides and downsides exist. However, luckily, with the use of templates, there is a better way. The “factory” pattern used in dependency injection, if again, you belong to the camp that believes patterns are proof of missing language features, could be seen as an object-oriented solution to treating classes and types as first class objects. That is, to say, in some languages, you cannot directly pass Types around by themselves, as arguments. In languages that you can, such as via C++’s templates, the factory pattern disappears.

How does this affect dependency injection? Well, since dependency injection, and the bridge pattern, make very heavy use of the factory pattern, it simplifies these two approaches a great deal. And while pure aspect-oriented programming is still beyond C++’s reach, clever use of templates brings you very close. I guess you could say that using templates to solve the bridge pattern is providing a generic solution to an aspect problem, rather than an object solution to an aspect problem.

To do “generic dependency injection”(GDI), which I’ll differentiate from “object dependency injection”(ODI) from here on out, in C++, you still go through the same mental processes in ODI to find the classes that you think may vary, or in the case of testing, you want to isolate your object from to test for.

class Foo {

public:

Foo() { bar = new Bar() }

private:

Bar * bar;

};

In the above, like our Java example, this class is still the Bar class. We don’t want the Bar class to be coupled with our Foo class, which it currently is, but we don’t want the overhead of building all those object factories either. And before anyone complains – yes, I know I left out the freeing of bar in the destructor, and moreover, it would have probably been easier just to make bar a value instead of a pointer, or used boost::shared_ptr. We’ll be leaving out those details for simplicity.

Once we’ve recognized that Bar and Foo are coupled, we’ll pull out the Bar type into a template, rather than having Foo know about it.

template<typename BarType>

class Foo {

public:

Foo() { bar = new BarType() }

private:

BarType * bar;

}

Voila, now in our release code, we simply create Foo like this:

Foo<Bar> …

and in our test code, we create Foo like this:

Foo<TestBar> …

Our Foo object is completely decoupled from the type of Bar it’s using, at compile-time. This increases runtime efficiency but maintains strict typechecking. If you’re a fan of “Modern C++ Design”, you’ll see that we’re co-opting “Policy based design” for testing purposes. Policy Based design is the proper name for using templating to solve the bridge pattern in general, of which GDI for testing is a specific application.

I’ll be talking more about this subject in the future, some of its drawbacks and some potential solutions. Namely, what happens now for the object that needs to create a Foo? Does it now need to know which Bar it wants Foo to use? It used to simply be able to create a Foo(), now it has to fulfill a template argument. Luckily, with some template tricks, we can use functional techniques to make this not the case. I’d also like to discuss the strengths GDI has over ODI, namely, that it’s use of types falls far closer to “Duck Typing” found in languages like Python, but unlike Python, we still keep strict typechecking. Finally, I’d also like to talk about some specific C++ strengths that good templating and use of RAII have in the relm of unit testing.

Share this!

Like this:

Related

Good post.
Dependency injection in C++ is more troublesome that one might expect. The problem I see is how to make sure that ‘Bar’ is deleted when ‘Foo’ is deleted (using the names from you examples).

Simply doing “delete foo;” in the destructor of ‘Foo’ is not an ideal solution since it forces ‘Bar’ to be allocated on the heap (automatic stack de-/allocation is suddenly impossible).

The solution using templates you suggest nice and pretty straight-forward. There is one minor problem with it, though: the constructor of the ‘Bar’-stub must hace the same signature as the constructor of ‘Bar’.

I have put some thinking into this problem but never found a really good solution not involving smart-pointers or similar. This post is a year old; have you found any other solution?

If I understand what you’re saying, you’d like to put Bar on the stack, but then Bar would have to have the same construction signature of whatever Foo is expecting.

I believe this sort of thing _may_ be enforced via the upcoming concept checks. One may have a ‘Bar’ concept that requires a Bar to have a certain constructor signature, and then make sure Foo only takes something that fulfills that Bar concept. It’s similar to the enforcement Java interfaces or C++ abstract base classes get you, but you can apply it to a template parameter.

I have made a modern DI library for C++. No code generators, no intrusive code (you don’t have to inherit from any special class), exception safety, no memory leaks (even in case of exceptions!) and no compilation (header only library).

I put to good use few smart pointers (unique_ptr and shared_ptr) and planned a new smart pointer that will allows to reduce number of allocations increasing overall performance. Objects are build recursively (circular dependency is correctly detected). If you use C++11 I think Infector++ is one of most complete solutions, it’s design was somewhat inspired by a C# library and is very easy to use, yet very effective