(Update: James updated his blog entry with a list of resources to good D/I articles [here and here] which discuss much better the topics below.)
James Shore has a new post about Dependency Injection, which he calls a “25-dollar term for a 5-cent concept.”
While his examples were indeed examples of D/I, he seems to miss a critical one, the ability to use Spring and Spring.NET to inject dependencies at runtime using configuration files. He has a code snippet that looks like:
public class ExampleTest {
TestDoStuff() {
MockDatabase mockDatabase = new MockDatabase();
// MockDatabase is a subclass of DatabaseThingie, so we can
// "inject" it here:
Example example = new Example(mockDatabase);
example.DoStuff();
mockDatabase.AssertGetDataWasCalled();
}
}
public class Example {
private DatabaseThingie myDatabase = new DatabaseThingie();
public Example(DatabaseThingie useThisDatabaseInstead) {
myDatabase = useThisDatabaseInstead;
}
public void DoStuff() {
...
myDatabase.GetData();
...
}
}
While it is true that the above is a form of dependency injection, so is the following:
The above is a sample configuration file from a good article on Spring.NET in MSDN Magazine.
So, D/I isn’t just about passing in a dependency via a constructor at compile time. It’s about decoupling your code using interfaces so that you can inject completely different implementations at run-time using configuration.
Of course, Spring.NET is much more than that. You can initialize object graphs, set properties in objects, and initialize singletons, all from a config script.
Oddly enough, the one use James hits on – testing – is the one that I don’t use frameworks like Spring.NET for, and one where his interpretation of being able to pass mocks in from the tests is very valid. But to say that D/I is a 5-cent concept because you can pass in a dependency via a constructor at compile time is similar to saying Rails is only a rapid environment because it is dynamically typed. While both statements are technically correct, they miss a vital concept – configuration based injections with D/I, and metacoding with Rails.