Dependency Injection is over Hyped

Dependency Injection is over Hyped

Dependency Injection frameworks have been over-hyped for too long. In most of the cases in which I have seen it touted as a perfect fit, it hasn’t really been necassary; And in some cases it made those applications harder to maintain than an alternative ‘Service Locator’ would have been. However, You can find some developers speaking as if you should avoid Service Location.

Update: I removed a quote from Nathan Evans, since he felt is was taken out of context. He says that he does not object to Service Location as a whole, and I will have to take him at his word on that. He does show some usage of Service Locator in his blog entry in the references below. I had thought he meant it was always bad, and not just when used within an IoC framework. There are plenty of other authors in the last 6 months that have clearly been against Service Locator. See the references below.

And on this blog and elsewhere you have developers such as me accepting provider model, a service locator, as a viable pattern; and accepting that dependency injection is also viable. Elsewhere you have dependency injection evangelists bashing provider model and any form of Service Locator. In the middle you have Martin Fowler.

Martin Fowler “The choice between Service Locator and Dependency Injection is less important than the principle of separating service configuration from the use of services within an application.”

‘Dependency Injection’ is only one form of the D in the SOLID design principles, ie. Dependency Inversion. I do highly recommend Dependency Inversion in any application that has a need to interact with dynamic data, or that has any level of business logic. Both Service Locator and Dependency Injection can be an anti-pattern or a viable pattern depending on the scenario.

MVC Controllers

Microsoft MVC does support Dependency Injection frameworks by having a dependency resolver to create any MVC controller factories, model binders, view engines and more. On the other hand it does this using IDependencyResolver which follows the Service Locator pattern.

A controller is an application specific implementation of page flow logic. If you need to change that logic you then should just do so in your application and redeploy. There shouldn’t be a need to have a Dependency Injection framework inject your controller instance for you. Just let the MVC framework handle instantiation normally. The reason most developers inject their controllers is so that the dependencies they need can be injected into them. This seems like a lazy excuse by a Dependency Injection framework. Maybe a better implementation strategy would be post compilation manipulation by a Dependency Injection ‘Tool’, similar in some ways to PostSharp. (I am not part of or affiliated in any way with PostSharp. My only connection is as a customer.)

Here is a typical example of a controller that I have seen in applications using Dependency Injection. This would look the same for any dynamic proxy based Dependency Injection framework. The Dependency Injection framework specific pieces are in application configuration and in bootstrapping code which sets the IDependencyResolver to be used.

Is there any value in the Controller being injected in this scenario? Is this controller logic going to swapped out with another controller derived from SomethingController? The answer is, very unlikely. The business rules are in the injected providers, and not in the controller. All the controller does is define the actions available, the parameters to those actions, and then pass off all the real work to the providers. Those providers are what you may want to swap out with another implementation someday. So why not just stick to Service Locator in the controller?

With service locator you don’t need to configure your MVC application to use a dependency resolver, as you would need to do with any of the dependency injection frameworks. Which is less code? More importantly, which is easier to debug an issue during dependency resolution?

Also note, that with Service Locator the controller doesn’t need to inject every provider type that every downstream class needs to use. It only needs to worry about the provider type(s) it uses directly. The example above is the ‘SomethingFormatter’, which is not directly used by the controller.

Both of these examples could be refactored to move the check of the current user down into the business layer of ‘SomethingProvider’, and therefore the implementation(s) of the provider. That would leave the action method as 3 statements: a business layer call, view model instantiation, and passing the view model into the view. Ideally, that is all any GET action method would consist of (as seen within the controller code).

Dependency Injection uses Service Locator

Under the covers when objects are instantiated they are created by a Service Locator. Here is some code using Spring Dependency Injection to get a reference to transaction support classes. This is not the recommended way to get Spring transaction support, but it is documented as a way in case you need more flexibility than the recommended code. My point here is to show that dynamic proxy based Dependency Injection frameworks also use Service Locator as an implementation detail, even if you don’t normally see it.

Minimal Provider Service Locator – the static ‘Manager’

Provider model traditionally has a counter part static class to resolve the provider implementation collection, and an ‘active’ main provider. It is responsible for loading the possible providers from configuration and making those provider types available for instantiation. The pattern typically dictates that there is a static member on this static class for every member of the provider type, which delegates the call to the active provider instance. This is not a real requirement of the pattern.

You can minimize this static class to have 2 simple properties which delegate the real work to a shared library class. The following example leverages the Candor.Configuration.Provider.ProviderCollection in the Candor.Core NuGet package (source on Github).

In this example the ContactRequestManager is your Service Locator. For each type of provider you would have a separate static Service Locator class.

Provider Model DependencyResolver

You can take the example in the previous section a step further by reducing down to a single service locator for all your provider types. Even simpler you can just put this class into a shared library. I have made it available in the Candor.Common 0.7.0+ NuGet package (namespace Candor.Configuration.Provider).

I have only just started using this implementation of a Service Locator, so it may not have all the kinks worked out yet. Let me know if you have any constructive feedback.

Configuration

Configuring The provider resolver is easy with either code configuration or xml configuration. To see traditional provider model xml and code configuration, see my older article Provider Model Enhanced in the references below.

Code Configuration

This code configuration would go somewhere in your application startup. In an MVC application create a separate file to hold the code configuration and then call it from your Global.asax.cs. Or do as shown here and use Web Activator, available via NuGet and Codeplex.

If you need to use different providers in various configurations then you can either use conditional compilation for the blocks that need to vary, or you could read a ‘CurrentEnvironment’ AppSetting and use that value to configure which providers to use or the parameters to be passed into them. However, most variations would be in the database connections, cache server names, and the like. Most of those settings will still be controlled and transformed by configuration transforms.

Xml Configuration

Here is the equivalent configuration if you are using the ProviderResolver. This would go in your web.config or your app.config as appropriate. It is similar to the configuration you would have for classic provider model when the providers are loaded by a Manager class. The only difference in the classic provider model case is the name of the ‘UserProvider’ node would be ‘UserManager’, and the ‘SomethingProvider’ node would be ‘SomethingManager’.

This is much more verbose than the code configuration. The other disadvantage of xml configuration is the lack of compile time checking for type names. However, It is easy to transform different providers in configuration transforms. And less commonly, you can change configuration at any time after deployment. I have used xml configuration more in the past, but I plan on using code configuration more often in the future.

Update 4/11/2013, 9:30pm CST: I had to update the article to use xml syntax coloring, because the csharp syntax coloring stripped out all of my generics. If you know how to post C# code using generics on wordpress properly, please let me know.

About the Author

Co-Founder and CTO of Watchdog Creative, business development, technology vision, and more since 2013, Developer, and Mentor since 1999.
See the about page for more details.

2 Comments

By Frisian

Looking at your article from a Java point-of-view, I miss the distinction between dependency injection as such and dependency injection frameworks.
Using dependency injection allows to configure objects per instance. Using a service locator on the other hand configures objects per class unless the service locator to be used is configurable itself (maybe by dependency injection?).
The difference is most obvious with unit testing. With DI you mock the dependency and inject it into the object to be tested. With a service locator, you have to mock the dependency and the service locator to test an object.
That said, in any non-trivial application there will be the need to configure objects of the same class in a different way and be it only for unit testing. The problem is, that you usually cannot foresee which object it will be, so – to be forearmed – you use dependency injection all the time.
Using the usual trifecta of DI (constructor, setter, abstract getter) doesn’t tie your code to any DI framework. If nothing else works, you can do the plumbing yourself in the application code.
Using annotations like @AutoWired on the other hand tie you to a DI framework. What’s worse, you have nothing gained in comparison to a service locator, because now it is just as difficult to configure instances of the same class in a different way within the same context.
Besides, a web controller is not the best example for DI. It’s interface is tied to the web framework in use, because a controller is where the rubber meets the road. It being used with a different configuration is highly unlikely. Business or data access layer objects have application-specific interfaces and are much more likely to be used in different configurations.
For example, some databases signal constraint violations right after the fact, whilst others only signal them after a commit. So, in order to deal with the subsequently thrown exceptions, you have to proxy either the data access object or the business object depending on the database in use.
Lastely, even if DI is only the “D” in “SOLID”, it helps also with the “I”, because DI promotes the use of interfaces by making it easier to change the implementation.