I'm going to be using C# for this article, but the principle is what is important. Focus on the principle behind the code. :)
Imagine you get an email one morning, Valve Software wants you to prototype their next MUD game. It's going to be a dungeon crawler RPG where you will have warriors, weapons, spells, the works.
"Ok, you think to yourself. I can do this! :)"
"Great! First I need you to create our Warrior class and give him a sword just to start out."
So, you create a Warrior class:
Then you create the Sword class:
Finally, this is how you would use it:
And as expected, it works. "Send my check in the mail", you think. But hold on! Valve calls you the following morning and tells you that the producer wants another weapon for the warrior. They want to give the warrior an axe.
"No problem, Mr. Business Man Guy - I'll get right on that.", you say.
Let's create another class for the Axe then:
How can we tell our Warrior to use this...hm. Let's try this:
But wait - how do we know what weapon the warrior is supposed to use? :(
What about this, we can use a boolean attribute and use that to decide whether we use the sword or the axe.
So far so good, you can practically smell the check in the mail. You commit the code to your repository and you get an email 20 minutes later from the Bossman.
"Are you sure you thought this through? What are you going to do when we decide the warrior will have another weapon and another and another?"
When you coded as we just did above, you acquire a lot of technical debt. Stuff you're going to be held accountable for in the future and you will have to face it.
Let's use Dependency Injection to improve this code and make sure Valve pays us.
First, lets create an interface called IWeapon. This will have a single method, Hit.
Now let's modify our Sword and Axe class:
Great, our two weapons are implementing the IWeapon interface.
Lets modify the Warrior class to take advantage of this chage:
Notice how cleaner the code is and how easily we can inject the dependency. Here's how we would use this:
Since we are using interfaces instead of concrete objects, we no longer need specific object types in our class. In the constructor of the Warrior class, we can inject whatever concrete implementation we need.
"Sergio, what in the hell does all this mean? I'm still waiting for the punchline."
The benefit of Dependency Injection being able to expand an existing system without the need for modification on our part. Since we use interfaces, implementation details are not necessary so long as they follow the interfaces contract.
In the next article, I'll look into Ninject and how to use this to automatically inject dependencies without the need to wire things up manually.
Imagine you get an email one morning, Valve Software wants you to prototype their next MUD game. It's going to be a dungeon crawler RPG where you will have warriors, weapons, spells, the works.
"Ok, you think to yourself. I can do this! :)"
"Great! First I need you to create our Warrior class and give him a sword just to start out."
So, you create a Warrior class:
public class Warrior
{
Sword sword;
public Warrior()
{
sword = new Sword();
}
public void Attack(string target)
{
sword.Hit(target);
}
}
Then you create the Sword class:
public class Sword
{
public void Hit(string target)
{
Console.WriteLine("You slice {0} in half!", target);
}
}
Finally, this is how you would use it:
static void Main(string[] args)
{
Warrior gustaf = new Warrior();
gustaf.Attack("Orc");
Console.Read();
}
And as expected, it works. "Send my check in the mail", you think. But hold on! Valve calls you the following morning and tells you that the producer wants another weapon for the warrior. They want to give the warrior an axe.
"No problem, Mr. Business Man Guy - I'll get right on that.", you say.
Let's create another class for the Axe then:
public class Axe
{
public void Hit(string target)
{
Console.WriteLine("You smash the puny {0} with your mighty axe!", target);
}
}
How can we tell our Warrior to use this...hm. Let's try this:
public class Warrior
{
Sword sword;
Axe axe;
public Warrior()
{
sword = new Sword();
axe = new Axe();
}
public void Attack(string target)
{
sword.Hit(target);
}
}
But wait - how do we know what weapon the warrior is supposed to use? :(
What about this, we can use a boolean attribute and use that to decide whether we use the sword or the axe.
public class Warrior
{
Sword sword;
Axe axe;
private bool _useSword;
public Warrior(bool useSword)
{
sword = new Sword();
axe = new Axe();
_useSword = useSword;
}
public void Attack(string target)
{
if (_useSword)
sword.Hit(target);
else
axe.Hit(target);
}
}
So far so good, you can practically smell the check in the mail. You commit the code to your repository and you get an email 20 minutes later from the Bossman.
"Are you sure you thought this through? What are you going to do when we decide the warrior will have another weapon and another and another?"
When you coded as we just did above, you acquire a lot of technical debt. Stuff you're going to be held accountable for in the future and you will have to face it.
Let's use Dependency Injection to improve this code and make sure Valve pays us.
First, lets create an interface called IWeapon. This will have a single method, Hit.
public interface IWeapon
{
void Hit(string target);
}
Now let's modify our Sword and Axe class:
public class Sword : IWeapon
{
public void Hit(string target)
{
Console.WriteLine("You slice {0} in half!", target);
}
}
public class Axe : IWeapon
{
public void Hit(string target)
{
Console.WriteLine("You smash the puny {0} with your mighty axe!", target);
}
}
Great, our two weapons are implementing the IWeapon interface.
Lets modify the Warrior class to take advantage of this chage:
public class Warrior
{
private IWeapon _weapon;
public Warrior(IWeapon weapon)
{
_weapon = weapon;
}
public void Attack(string target)
{
_weapon.Hit(target);
}
}
Notice how cleaner the code is and how easily we can inject the dependency. Here's how we would use this:
static void Main(string[] args)
{
Warrior gustaf = new Warrior(new Axe());
gustaf.Attack("Orc");
Console.Read();
}
Since we are using interfaces instead of concrete objects, we no longer need specific object types in our class. In the constructor of the Warrior class, we can inject whatever concrete implementation we need.
"Sergio, what in the hell does all this mean? I'm still waiting for the punchline."
The benefit of Dependency Injection being able to expand an existing system without the need for modification on our part. Since we use interfaces, implementation details are not necessary so long as they follow the interfaces contract.
In the next article, I'll look into Ninject and how to use this to automatically inject dependencies without the need to wire things up manually.
13 Comments On This Entry
Page 1 of 1
xheartonfire43x
07 March 2011 - 12:08 PM
Really nice example of dependency injection. I have heard the phrase many times before, but never really understood it at all.
diego_pmc
07 March 2011 - 12:57 PM
Are you sure this is DI? I was under the impression DI meant asking directly for the objects you need (as opposed to asking for a factory and building the objects yourself), which reduces decoupling between the class and the factory, which means you can create the needed components as you see fit. Did I misunderstand DI?
Dormilich
07 March 2011 - 04:06 PM
a good example of "code against an Interface, not an Implementation"
BobRodes
07 March 2011 - 06:01 PM
Excellent example, Sergio, very concise and to the point. I've never been able, however, to understand what the difference between dependency injection and polymorphism is. Some people say that this is a "more flexible" version of polymorphism or whatever, but yours is exactly analogous to the example of polymorphism (I actually have a T. Rex and a flea that both move and bite) that I used when I was teaching this stuff about 10 years ago. Seemed to me at the time that Fowler was just finding new words for old ideas when he started talking about dependency injection back in 2004.
Can you shed some light on this? Perhaps there are some examples of polymorphism that don't conform to the dependency injection pattern?
Can you shed some light on this? Perhaps there are some examples of polymorphism that don't conform to the dependency injection pattern?
BobRodes
07 March 2011 - 06:13 PM
Great example, Sergio. Very concise and to the point.
However, I've never been able to see why Fowler wasn't just using new words for old ideas when he started talking about this back in 04 or so. I've used an example in my OOAD classes that seems analogous to yours (I use an iAnimal and a TRex and a Flea, with a Move and a Bite).
However, as I write this, I get to thinking. My class example doesn't have an association with it as yours does. Your polymorphed weapon has a warrior with it, and maybe it's the fact of the association that makes it a dependency injection. For example, if you had a Toon class with an Attack method, implemented by your warrior and, say, a mage, both of whom attacked quite differently, that might be an example of polymorphism but not of dependency injection?
However, I've never been able to see why Fowler wasn't just using new words for old ideas when he started talking about this back in 04 or so. I've used an example in my OOAD classes that seems analogous to yours (I use an iAnimal and a TRex and a Flea, with a Move and a Bite).
However, as I write this, I get to thinking. My class example doesn't have an association with it as yours does. Your polymorphed weapon has a warrior with it, and maybe it's the fact of the association that makes it a dependency injection. For example, if you had a Toon class with an Attack method, implemented by your warrior and, say, a mage, both of whom attacked quite differently, that might be an example of polymorphism but not of dependency injection?
dorknexus
08 March 2011 - 10:26 AM
A large portion of dependency injection is in the "program to an interface" part. That is indeed just polymorphism. However, you can program to an interface and still have a class go and fetch its dependencies from a factory or something like that. Dependency injection is specifically program to generic interfaces and providing dependencies to a class rather than having the class go and fetch its dependencies manually. DI is also generally aided by some sort of automated framework.
BobRodes
08 March 2011 - 05:41 PM
Ok, I think I understand what you're saying, Dark, but can you explain what it is in Sergio's example that makes that dependency injection and not just polymorphism? That would help me a lot.
raziel_
10 March 2011 - 09:47 AM
i always think that DI is injecting DLL in some program by replacing one that he use.
Dormilich
11 March 2011 - 05:06 AM
not sure where I picked that link up, though it’s worth a read: Inversion of Control & Dependency Injection
Page 1 of 1
Trackbacks for this entry [ Trackback URL ]
1 user(s) viewing
1 Guests
0 member(s)
0 anonymous member(s)
0 member(s)
0 anonymous member(s)
About Me

Bienvenidos! I'm a USA ex-pat living in Bolivia for the past 10 years. Web development is my forte with a heavy lean for usability and optimization. I'm fluent in both English and Spanish. I guest write for the popular Python website Python Central. Visit my website.
My Blog Links
Recent Entries
-
-
-
-
How to create a signature form for iPad and mobile devices using HTML5 and Canvas.
on Nov 27 2012 08:15 AM
-
Recent Comments
-
laytonsdad
on Apr 30 2013 11:30 AM
Dream.In.Code Badge Generator! Share your flair on your site or blog.
-
-
Jstall
on Nov 04 2012 09:18 AM
The Pragmatic Bookshelf mega blowout sale - 40% off select Ruby on Rails books.
-
-
tylrwb
on Jun 26 2012 07:34 PM
C# and MVC3 - Uploading and parsing an Excel document is easier than it seems.
Categories
|
|



13 Comments








|