I was speaking with Phil Haack this week at MIX 09 and we were discussing his choice to drop Dependency Injection from his talk on ASP.NET MVC Ninjas on Fire Black Belt Tips. Which, by the way, was an awesome talk that you should go check out if you weren’t able to be there. The reason that Phil chose to remove the Dependency Injection piece of his talk was simply because whenever you show off dependency injection in a very simple scenario it always seems to devolve into a “why would I want to do it that way?” sort of discussion. Phil suggested that some thought needed to be put into a scenario complex enough to show the benefits of Dependency Injection, yet simple enough to still get across to an audience. (I’m going to be using Ninject 2 in this post, which is currently in beta. Go check it out, and be sure to thank Nate for writing it.)
The Problem
The problem is that the majority of the benefits of dependency injection only become apparent when you start dealing with scale. The entire concept of "Inversion of Control" (which is the underlying principle on which Dependency Injection operates) lends itself to larger and more complex applications. "Inversion of Control" is all about externalizing the flow of the application. In its Dependency Injection incarnation, instead of instantiating classes which will then in turn do work to go out and find their dependencies, we are asking the container to construct a class for us, while at the same time finding and resolving all dependencies and passing those to the class. We don’t have to think about how this object is constructed, the Dependency Injection container "wires it up" for us. Because of this, it really only lends itself to larger applications because externalizing the flow of an application causes overhead. It is no longer possible by looking at the source of the classes to tell what dependencies will be used at runtime. In a large system this is much less of a concern, because we are now moving massive amounts of repetitive configuration out of classes and into more centralized locations where they can be changed more easily. If you want to read more about Inversion of Control, you should go over to Martin Fowler’s Bliki.
To enforce the idea that Dependency Injection is too complicated for simple setups, let’s create a very simple scenario using a service class and a repository that many of us are probably look at fairly regularly. First we will have a repository:
public class UserRepository: IUserRepository { public IEnumerable<User> GetUsers() { return new List<User>(); } }
And an interface for that repository:
public interface IUserRepository { IEnumerable<User> GetUsers(); }
And then we have a service class takes the repository as a constructor:
public class LoginService { private readonly IUserRepository userRepository; public LoginService(IUserRepository userRepository) { this.userRepository = userRepository; } public void LoginUser(string username, string password) { //some crap that uses repository to get user and check password } }
Then I declare an interface for this:
public interface ILoginService { void LoginUser(string username, string password); }
Then we config the dependency injection:
public class DefaultModule: Module { public override void Load() { Bind<ILoginService>().To<LoginService>(); Bind<IUserRepository>().To<UserRepository>(); } }
Then I request my LoginService:
var service = kernel.Get<ILoginService>();
And then I pat myself on the back for doing such an awesome job of showing everyone how sweet dependency injection is, while simultaneously mocking everyone who just “doesn’t get it”. It is pretty awesome, right?
Only the above looks good to masochists only. If you even have the slightest of pragmatic blood in you, the above looks like ridiculous overkill. And for an application that simple, it is extreme overkill.
The Realization
In fact, using “poor man’s Dependency Injection” we could just have easily done it like this:
public class UserRepository { public IEnumerable<User> GetUsers() { return new List<User>(); } }
And the service like this:
public class LoginService { private readonly UserRepository userRepository; private LoginService(UserRepository userRepository) { this.userRepository = userRepository; } public static LoginService Create() { return new LoginService(new UserRepository()); } public static LoginService Create(UserRepository repository) { return new LoginService(repository); } public void LoginUser(string username, string password) { //some crap that uses repository to get user and check password } }
And been done with it. I even created factory methods on the service to show that we can still have the abstraction away from the constructors. So I could get my LoginService like this:
var service = LoginService.Create();
And what do we lose here? Well, I got rid of the interfaces, but we could have kept those. So we didn’t really loose anything in the abstraction front. We also didn’t lose anything in the flexibility front, because I abstracted away the constructor using a factory method, so if we need to change how they are instantiated, we still have that option. And we also didn’t lose anything in the clarity front, in fact, I think we gained big here. It is much easier to tell how the application is going to behave.
At this point you may be thinking that I am an opponent of dependency injection, but the reality is that you couldn’t be more wrong. I am a huge proponent of it, and I tend to use it even on fairly simple projects. But from what we have seen above, it may be hard for someone to wrap their head around exactly what benefit DI is going to give them.
Benefits, We Are Going To Get There
So, let me say one thing before we really start to find a way to show off Dependency Injection. In order to ever appreciate DI you really have to subscribe to the single responsibility principle (often referred to as SRP). If you don’t see the benefit of each class being responsible for one thing, and you are a fan of 5000 line classes, then I’m not sure that I am going to be able to help you. You really have to love composition of classes, but you may be someone who simply doesn’t mind constructing dependencies inside of the enclosing classes or simply uses the service locator pattern to pull in dependencies.
When I started thinking about this problem, I thought “great”, I’m going to have to come up with some stupidly complicated example that really will end up doing more harm than good. But the more I thought about the problem, the more I realized that classes pulling in their own dependencies doesn’t get complicated very quickly, but when classes don’t contain enough context to configure themselves, then config can start to get ugly pretty quick.
So let’s get back to our earlier example of the UserService and UserRepository class. If you are familiar with the Repository pattern then you are probably familiar with the idea that its main purpose is to abstract an underlying persistence store so that everything looks like an in-memory list. This extremely simple abstraction works amazingly well, even if enterprise situations where we have multiple back-end stores. So let’s go ahead and pretend that I work in Acme Insurance and I have two different web services that I am going to be hitting against in order to pull my user data. We will use a standard IUserWebService contract for these web services. We are going to need to get those two dependencies into our UserRepository so that we can use them as stores for user data. These guys will look like variations on this:
public interface IUserWebService { IEnumerable<User> GetUsers(); }
And then in a real application, we would have the automatically generated WCF proxy classes for these, but in this case we are just going to create a few dummy stub classes. Okay, so we have these new services, and they are going to have to get into the repository, but we are still doing good with “poor man’s” Dependency Injection. All we need to do now is to just instantiate these services inside of the repository like this:
public UserRepository() { userWebServices = new IUserWebService[2]; userWebServices[0] = new UserWebServiceFacade(); userWebServices[1] = new UserWebServiceFacade(); }
Easy enough. We can also expose a constructor that will allow us to pass these are parameters too for testing:
public UserRepository(params IUserWebServiceFacade[] userWebServices) { this.userWebServices = userWebServices; }
The only problem is that now how are we going to tell the two services in the constructor up above their config information? You see what I am talking about? These two lines:
userWebServices[0] = new UserWebServiceFacade(); userWebServices[1] = new UserWebServiceFacade();
You see we haven’t really gotten all that complicated, but already we have hit a point where we have dependencies that don’t contain enough information to configure themselves. So what do we do? Well, we could do this:
public UserRepository() { userWebServices = new IUserWebServiceFacade[2]; userWebServices[0] = new UserWebServiceFacade("http://www.test.com"); userWebServices[1] = new UserWebServiceFacade("http://www.test2.com"); }
But we don’t really want to hard code the configuration for these straight into the repository, so we can do this instead:
public UserRepository() { userWebServices = new IUserWebServiceFacade[2]; userWebServices[0] = new UserWebServiceFacade(ConfigurationManager.AppSettings["service1"]); userWebServices[1] = new UserWebServiceFacade(ConfigurationManager.AppSettings["service2"]); }
But now we have code which directly accesses configuration and then passes it to a child class. Okay, so you don’t really care about that…but what happens now when we need to do some decryption on data coming back from these services? So we throw an IDecryptor into the mix (surely you don’t think that the repository should be decrypting data, do you?):
public interface IDecryptor { string Decrypt(string encryptedString); }
Hmmm. The issue becomes now that both of these need a different key, you don’t expect disparate business locations to use the same encryption key do you? So if we need to get keys and more config, then now the repository constructor will start looking like this:
public UserRepository() { userWebServices = new IUserWebServiceFacade[2]; IDecryptor decryptor1 = new Decryptor(ConfigurationManager.AppSettings["key1"]); IDecryptor decryptor2 = new Decryptor(ConfigurationManager.AppSettings["key2"]); userWebServices[0] = new UserWebServiceFacade(ConfigurationManager.AppSettings["service1"], decryptor1); userWebServices[1] = new UserWebServiceFacade(ConfigurationManager.AppSettings["service2"], decryptor2); }
Wow. This is starting to get a bit ridiculous. Next thing you know they are going to use different encryption schemes, ports, etc… Once you start thinking about other config settings, we either have to start reading them in from config right in the constructor, or pass them in.
If we were to use DI then we would have this config (in the latest Ninject 2 branch):
Bind<ILoginService>().To<LoginService>(); Bind<IUserRepository>().To<UserRepository>(); Bind<IUserWebServiceFacade>().To<UserWebServiceFacade>() .Named("Service1") .WithConstructorArgument("url", ConfigurationManager.AppSettings["service1"]); Bind<IUserWebServiceFacade>().To<UserWebServiceFacade>() .Named("Service2") .WithConstructorArgument("url", ConfigurationManager.AppSettings["service2"]); Bind<IDecryptor>().To<Decryptor>() .WhenParentNamed("Service1") .WithConstructorArgument("key", ConfigurationManager.AppSettings["key1"]); Bind<IDecryptor>().To<Decryptor>() .WhenParentNamed("Service2") .WithConstructorArgument("key", ConfigurationManager.AppSettings["key2"]);
As you can see the ILoginService is tied to LoginService, IUserRepository is tied to UserRepository, and then we bind IUserWebServiceFacade to UserWebServiceFacade twice with two different service addresses. Then we use these named bindings to bind the two classes used to decrypt the data.
So we end up with a bunch of classes with simple constructors, only referenced interfaces, which can be built and configured in virtually any way by the Dependency Injection container. The configuration may look complicated, but when you consider that for most interfaces you will have only a single implementation, the configuration stays much more simple than you would imagine.
The Repository:
public class UserRepository: IUserRepository { private readonly IUserWebServiceFacade[] userWebServices; public UserRepository(params IUserWebServiceFacade[] userWebServices) { this.userWebServices = userWebServices; } public IEnumerable<User> GetUsers() { var result = new List<User>(); foreach (IUserWebServiceFacade service in userWebServices) { result.AddRange(service.GetUsers()); } return result; } }
The Web Service:
public class UserWebServiceFacade: IUserWebServiceFacade { private readonly string url; private readonly IDecryptor decryptor; public UserWebServiceFacade(string url, IDecryptor decryptor) { this.url = url; this.decryptor = decryptor; } public IEnumerable<User> GetUsers() { // implementation return new List<User>(); } }
And the decryptor:
public class Decryptor: IDecryptor { private readonly string key; public Decryptor(string key) { this.key = key; } public string Decrypt(string encryptedString) { // implementation return string.Empty; } }
Reflecting On What We Have Accomplished
We don’t have any knowledge of how these dependencies are constructed anywhere except for the config in our DI container. We can change them from transient to per request to singleton with a simple change. We can replace our web service implementation without digging into the source. What if this web service had many methods which were being used by a multitude of different classes? How many constructors would we wade through in order to update the references to this class in order to change the way it is being built?
These are the kinds of questions that you need to be asking yourself as you look at these examples because even though I think that this example shows off Dependency Injection pretty well, it is still fairly canned. It is hard to truly grasp the full benefits until you have a class which is used across fifty other classes that you suddenly need to modify the constructor on. Now sure you can get the same effect from factory methods, but again the benefits come in scale. If we use service locator, then we need to have that service locator everywhere in order to request our dependencies. Nothing is more satisfying with DI than when you need to add a dependency to your constructor that has already been wired up, then all you have to do is request the type and the rest is just handled for you.
Another advantage of the DI framework is that most of them are setup with lifetime management. This allows you to change a class from per-request to transient to singleton by simply changing a setting. Most DI frameworks will also allow you to create your own reusable custom lifetimes.
Try It For Yourself
As much as I can try to convince you that Dependency Injection is the best thing since sliced bread, you really have to try it our for yourself. After you use it for a bit, you’ll start to realize how natural it is to just throw dependencies into your constructor so that you can keep small classes, but still have them all wired up quite easily. You’ll soon start to realize that it is changing the way you write your code.
Then again, you may try out Dependency Injection and find that you hate it. I urge you to press forward with it, at least for a bit, but if you really find that you hate it then I’d love to hear why. I’d also love to hear from people who love dependency injection, but think that I gave a horrible example.
Summary
In this post we looked at a common problem in many business apps and how we would solve the problem with and without dependency injection. Dependency Injection allows us to wire up our applications in a central place all while using less code. It helps keep our classes loosely coupled and testable, while providing a high level of extensibility. I hope you have found this post useful!
Loved the article? Hated it? Didn’t even read it?
We’d love to hear from you.
Some things to keep in mind with constructor DI :
values that can change in time!
I had some problems with these, and did not really found a good solution, only a hack.
add a property so set the correct new value, before calling the method.
Example : class A has a constructor of Interface b, implemented in Class B.
but the value of some properties in Class B are changed in another part of the Code. So when you call a method on Class A, it has the old values of B, not the new ones.
Probably I made a mistake in my program, but I only inherited it, and did not write it from the start.
WPF -> WCF I think 😉
Btw, I don’t see Inversion of Control mentioned anywhere. Isn’t it so that Inversion of Control is the concept and dependency injection is the mechanism to make it possible? So depedency injection isn’t a concept, it’s a mechanism to make ANOTHER concept possible and THAT concept, Inversion of Control, is what this is all about and what’s important, not DI. Doing DI without understanding IoC is stupid, the reason to do DI should be: IoC, and thus explaining the necessity of DI is easy: explain the necessity of IoC and describe DI as a mechanism to accomplish IoC in your application. You did a good job describing the necessity of IoC however IMHO failed to name it once, which is a bit of a shame, considering the fact that IoC is what’s important here and you can accomplish IoC in more than one way, as long as you make IoC possible in your software.
@ruben I’m not quite sure I understand what you mean. Is your DI container something like Spring.net where everything defaults to singleton?
@Frans Yes, I meant WCF, that is what I get for going to Microsoft MIX. They inject WPF into your brain.
And I do completely agree with you. While I think that DI is still a concept, it is not the underlying principal, but a means to an end. I was writing this in the mode of trying to sell dependency injection rather than explain the underlying concepts, but it is a bit of an oversight for me to not bring up IoC.
One point to make though, if someone learns the mechanics of DI and then by doing so sees the value in it, then I think that they have then indirectly grasped the notion of IoC without realizing it.
I’ll look over the post a bit because I think there are a few places where I used the term "Dependency Injection" when I should have used IoC.
[quote]One point to make though, if someone learns the mechanics of DI and then by doing so sees the value in it, then I think that they have then indirectly grasped the notion of IoC without realizing it.[/quote]
Agreed.
I think it’s that exact point which causes the confusion between DI and IoC, even on wikipedia 😉
Great example! I think you really well illustrated how a complex dependency chain is a real pain that is solved elegantly by a DI container.
Good point about SRP. When an object has a dependency and uses "Poor Man’s DI" to create that dependency in a constructor overload, you might say it is technically violating SRP because perhaps it should not have the responsibility of creating that dependency. But that doesn’t seem so egregious in the simple case.
But when it must create not only its own dependencies, but the dependencies of the dependencies, then that becomes pretty egregious. I think I’ll use that point to illustrate the benefits of DI next time. 🙂
Excellent post. 100% agreed.
One of the major benefits I like about IoC containers is when they support automatic mapping. I.e. you don’t need to explicitly tell the container to map LoginService to ILoginService. When the app starts up, you tell the container to map classes to the first interface it implements, unless otherwise specified. In this way, I don’t even need to remember to wire things up in the container. Just create the interfaces and classes and start using them.
I’m with Kyle on this one. If you use auto-wireup, then IMO, DI makes sense on all applications… even the small scale ones.
Many times I’ve had applications start small and grow over time and once it gets to that point, there are growing pains in refactoring the app to use DI.
I’ve gotten in the habit of starting all services and apps with the interfaces and worrying about the implementation later.
@Brian That is an excellent point, but auto-wireup is hard to explain until someone understands the manual wiring. 🙂
And yes, like I said in my post I use DI on virtually all applications, because the ones that we never expect to become production applications are always the ones that do exactly that.
And starting with interfaces and doing some contract-first development is often an excellent approach.
Much like your point to Frans, I think sometimes jumping in head first (as a side-project) is the best way to learn.
I started with auto-wireup and through that made sense of it all as I began to understand what was happening behind the scenes.
Different kind of learning though, I guess not everyone does it that way.
Great post. I’m going to use this as a reference when someone asks for a concrete example of DI. I have a tendency to assume too much is understood when I attempt to break it down for someone.
Justin,
Sorry, I disagree that this is a good example, though I appreciate the effort to spread knowledge.
You took unrealistically crappy code and turned it into beautiful Cinderella by injecting DI into it.
For instance, I do services all day long and I have yet to see anyone place them into an array.
I think the challenge is to take well factored non-DI code and make it better by using DI.
@Robert Ha, thanks for the critique. Your concern is about placing them in an array? I could have just as easily passed them in as separate parameters. Would that have been a better example?
I think the idea here is to take code that has external dependencies and then introduce complexity due to the ways in which the dependencies need to be configured. I believe the example does a fairly good job conveying they, even if it might not represent something that you personally would do in your own code. Thanks!
Great stuff Justin.
I also liked your definition of the Repository Pattern for developers who are not acquainted with it:
[quote]"If you are familiar with the Repository pattern then you are probably familiar with the idea that its main purpose is to abstract an underlying persistence store so that everything looks like an in-memory list."[/quote]
Concise and understandable right away. Just like Frans B.’s explanation of DI from one of his forum posts:
[quote]"Dependency injection is very simple: inject an instance of a class X into an instance of a class Y because Y depends on X at runtime, and you don’t want to set the instance of X INSIDE the instance of Y. That’s it."[/quote]
After getting the (very) simplified gist of a pattern or principle it’s much more pleasant to delve deeper into the concept and the theories behind it.
Thanks.
I love the benefits of DI (I’ve been using Windsor), but I wonder if anyone has done any work where the dependencies vary per method called.
If my composite service layer uses multiple repositories, it seems like I shouldn’t need to create them all when the method I’m calling only needs 1 of them.
@Jim That is definitely a problem, especially if you have very heavy services. I have seen it solved before by using fine grained services or even individual "event" objects (not .net events) that represent actions within a system. Then you have much more control over what is going to be injected.
I agree that if you have a service with 8 dependencies and you are only using one of them, then you are wasting a lot of cycles.
@Jim I just had another thought as well, since you mentioned multiple repositories, you should consider injecting factories instead of the precise instance. You loose some of the benefits of ID, but it still may be flexible enough for you. The factories can in turn request the proper instances you are looking for.
@Justin That’s a good idea, I’ll look into that. I don’t like having a service layer class for every repository (which I have one per table), so I like to group them under a service with all the logically related repositories.
i.e.
UserService
– UserRepositoru
– UserDetailsRepository
– UserProfileRepository
thanks
Jim,
I had a similar problem as you, except I flipped what you did and made one repository that accesses all tables. In having that, I can make one service per table to store all the business logic and then reuse the same repository for each service, regardless of which tables I need to access.
It cuts down on the code and allows good separation of the business logic.
@Jim When I see the situation that you described it is an indication that the service might need to be redesigned because it is violating SRP.
http://hackingon.net/post/Excommunicating-Your-God-Classes.aspx
Nice work and an excellent read. Thanks.
Nice article. Since few months, I want to remove the static methods of my repository because with that, I’m not able to add easily unit tests and worst, I’m not able to control which connection that each method will use.
I have built windows applications for years and the problem of use a single connection is not a big deal compare to web application. But after the applications is growing, Patterns was hard to implement with static methods and the coupling make adding new features a nightmare.
With Dependency Injection, I can replace all my static methods without work weeks because the connection put in each of my repositories will be injected automatically and optionally if I want can be controlled if I want to create transactions, unit of work shared with multiples methods call. NInject is the best in my view to do that.
I’m always impressed when guy create a nice article that take so much time to write that I can’t give bad comment. I just can say: "Very Good work!" 🙂
You use Ninject’s `Named` and `WhenParentNamed` methods but you don’t show how that maps to the different array values. It makes the example somewhat lopsided. To be honest, I’ve very rarely needed to do something like that; it might be making the example too complicated. Great post though!
Yeah, I agree. The problem is that DI is usually valuable in cases of large or deeply nested dependencies, but those are (by definition) impossible to show in a simple example. This was my somewhat contrived attempt to show some value in a relatively simple scenario. Thanks for the feedback!