Thursday, October 08, 2009 -
I’d like to preface this treatise with an appeal to those of lesser intellect – please close your browser now. The concepts you read below are quite high-minded and we have a secret handshake you don’t know. We are “The IoC Community” and we rock the concepts yo.
For those who haven’t read the 200 page manual on IoC – well here ya go. If your little brain can’t handle the complexities of this post might I suggest turning on Howard Stern and Spolsky at the same time, full volume, and holding your breath until you see patterns in the air. This usually helps when wondering WTF Joel is talking about.
Let’s take a walk on the Cool Kid side of the street and see what Inversion of Control is all about…
So I’m building my blog (more on that later) and it makes for a really good demo since most people understand blogs. So I’ll use it for this discussion. Let’s pretend I have a PostController (using MVC) and this thing shows Posts.
I have a single action called “Index” that grabs data from my database and sends it down to my view (let’s pretend I’m using Linq to SQL):
public ActionResult Index(){ var db=new Model.DataContext(); var posts=db.Posts.Where(x=>x.IsPublished); return View(posts); }
Groovy. Now let’s get on with this…
What I’ve done here is pretty typical, and what you would see in any demo given at a Microsoft conference. The person writing this code can easily invoke the “This is a demo/small app so shutup” rule when the Cool Kids cry foul – and that would hold most likely as it would be either Hanselman or Scott Gu giving the demo and those guys have swagger like that.
There’s no need for complexity at this point – which is true, however it should be noted that we’ve incurred what’s known as “Technical Debt” – which is akin to repairing a go-kart with duct tape. Like debt, you could live with it, but more than likely it will cause you problems as you build out your app.
Typically what you might do, as a developer, is to hit F5 (Debug/Run) to see if data appears on your page. It’s still magic to me after all these years to see data from my DB hit the screen – I dig that rush and for a moment my little itch is scratched and I feel good about myself. I see data there – so it works.
But then I begin to think – do I really want to hit F5 every time I want to make sure this page runs right? I’ll appease the Cool Kids and add a test:
[Test] public void Post_Should_Show_Posts(){ var controller=new PostController(); var view=controller.Index() as ViewResult(); var posts=view.ViewData.Model as IEnumerable<Post>; Assert.IsGreaterThan(0,posts); }
What’s this test telling you if you put your programmer’s hat on? The title is a bit misleading as we don’t know what the view will actually “Show” – moreover we’re just testing that we have posts.
This test will fail – immediately – and it will keep failing no matter how much code we write. Why? Because I have no data in my database and this test will fail until I add some. Being the impatient type I add a record to my DB and my test passes.
If your geek senses are tingling – that’s a good thing! This test is pointless to say the least – what “unit of functionality” is it testing? None. And if you look at this a bit longer you’ll start to realize that I’m not chanting or smoking a secret mix of techno-herb and sassy weed – I’m just using common sense and basic coding principles. What happens if I remove all records again? The test fails. Does that mean my Controller won’t show posts? Not at all – and this is one main reason the People Who Like Testing (Cool Kids) advocate against hitting the database.
Well what’s the point of testing Controllers then if it’s this hard!
It’s not hard – it simply requires you to look a bit further and use some tricks – that’s all.
Interfaces are scary to many developers at first – they seem rather pointless until you actually use them. In this sense they work perfectly since I don’t want to talk to my database at all – what I really want in my Controller is the ability to get data from *somewhere* (not necessarily a SQL Database). That’s the important part – and yes it’s an abstraction – but that’s one step towards the idea of “Loose Coupling”.
When I wrote my initial Controller Action above (Index), I planted data access code right in it from Linq to Sql. In doing that I also made a decision that was explicit: whenever I use this controller, I also need to make sure I have my Linq to Sql classes set up and pointed to my Post database. This is called “coupling” and you can think of Linq To Sql and your PostController on a date, having babies if that helps.
Let’s pretend I made an interface (IPostRepository) with a single method called “GetPosts()” which returns an IEnumerable<Post>. Now I can use it instead of Linq:
IPostRepository repo; public ActionResult Index(){ var posts=repo.GetPosts(); return View(posts); }
This is a good first step – but how does it help me? I can’t instantiate an interface can I? So how the heck to I make this work?
Put in plain English: our PostController has a dependency on data from the IPostRepository – it needs it to function (which is a dependency sort of like your college roommate needed to wake-n-bake in order to get moving).
We could just implement our interface in a concrete class (let’s call it SQLPostRepository since we’re using SQL Server) somewhere and instantiate that:
IPostRepository repo; public ActionResult Index(){ repo=new SQLPostRepository(); var posts=repo.GetPosts(); return View(posts); }
Now the code works, but we’ve traded one dependency for another (on SQLPostRepository) – what did we gain here? Well nothing actually – and the Cool Kids are getting pissed.
What we should do is to allow the calling code to specify this dependency when creating the class, defaulting to the SQLPostRepository if nothing was set:
IPostRepository repo; //injectable constructor public PostController(IPostRepository postRepository){ repo=postRepository; } //default public PostController(){ repo=new SQLPostRepository(); } public ActionResult Index(){ var posts=repo.GetPosts(); return View(posts); }
This works, and now we can test this by sending in a fake repository (made up of in-memory lists) or we can use mocking, which basically “lies” about stuff. I’m going to sidestep the testing aspect here (easily will derail the post) as I want to stay on Dependency Injection and Inversion of Control.
On the face of it we’ve “loosened things up” which is always good as now we can plug in SubSonic instead of Linq to Sql if we wanted to, or next year we can use the [Groovy New ORM] that’s all the rage.
There is a problem, however, with “Naked Dependency Injection”, and that problem is that Controllers typically have more than one dependency. There might be logging involved, email, a comment repository, user repository, etc and you’d have to inject each of these (and update all the calling code when you change stuff).
It’s pretty easy to end up with “Constructors Gone Wild” by following this pattern, and on occasion you can end up with recursive construction – which is really ugly and a maintenance nightmare.
It’s a strange name – Inversion of Control – it sounds like you’re turning your app inside out. Here’s what it means:
Normally, when your class needs to use another class to do something it will instantiate an instance of that class, use it, and then discard it at some point. In this case our PostController class is controlling the instance of the IPostRepository – determining when it gets created and how. All these decisions being made for our IPostRepository – isn’t that just a bit presumptuous!
Inversion of Control does the exact opposite. You have a thing called a “Container” that instantiates the classes and controls their lifetime (according to some rules you set) and it hands them out when asked for. In our blog app the control is removed entirely from the PostController and is “inverted” – handed completely to the container which tells your PostController “this is the object you’re going to get and you’re going to like it”.
The IoC container is essentially a big playground of objects just waiting to be used and reused. As you can imagine, there’s a lot of freedom when your objects are cut free like this – you can setup all kinds of rules for them and even control their lifetime. Want to make one a singleton (yuck)? You can do this easily with a half-line of code. Want to set an object’s lifetime to that of the request? Same thing.
I’ve used StructureMap a lot as it’s what I know – but Ninject or any other framework is pretty easy to pick up, no Big Brain required – so that’s what I’ll show you below.
The first thing you do is to tell StructureMap what type of class you want when a given interface is used in a constructor. You do this in a thing called a “Registry”:
public class BlogRegistry : Registry { protected override void configure() { ForRequestedType<IPostRepository>() .TheDefaultIsConcreteType<SQLPostRepository>(); } }
Then, in your Application_Start you call it:
protected void Application_Start() { StructureMapConfiguration.AddRegistry(new BlogRegistry()); }
Now when you want to use it, you ask StructureMap for an instance of the object:
var repo=ObjectFactory.GetInstance<IPostRepository>();
On the face of it this might seem like a lot of code for nothing – and it’s a bit true. IoC is an investment in your application – not a direct deposit. What you gain is the ability to “unhinge” your classes from one another, reusing them in other applications as needed.
Most importantly, as you’ll see below, I’ve lost all of my “technical debt” and not many things are more fun than being debt-free.
In the case of my blog application, I can override my ControllerFactory and ask StructureMap to build my Controllers for me – this reduces my examples above to this:
IPostRepository repo; public PostController(IPostRepository postRepository){ repo=postRepository; } public ActionResult Index(){ var posts=repo.GetPosts(); return View(posts); }
Now the Controller knows nothing of any implementation – which is awesome.
If you’d like to know more about DI/IoC (and some details on how to hook it up to an MVC App), I did a full hour’s video cast with Jeremy Miller (creator of Structure Map) and you can watch it here: http://www.asp.net/learn/mvc-videos/video-366.aspx. It’s about an hour long and I think the best of the entire MVC Storefront series.
It took me just over an hour to write this post – how long did it take you to read it? Does IoC make more sense to you? Regardless if you think it’s worth it (you might think it’s crap) – is it too high-minded? Too complex?
IoC containers take a simple, elegant, and useful concept, and make it something you have to study for two days with a 200-page manual. I personally am perplexed at how the IoC community took a beautiful, elegant article by Martin Fowler and turned it into a bunch of complex frameworks typically with 200-300 page manuals.
Am I a whole lot smarter than you?
I think that people who use IoC containers are (A) very smart and (B) lacking in empathy for people who aren't as smart as they are. Everything makes perfect sense to them, so they have trouble understanding that many ordinary programmers will find the concepts confusing. It's the curse of knowledge. The people who understand IoC containers have trouble believing that there are people who don't understand it.
Is it harder to read my final PostController versus my “Naked DI” Controller above?
I believe that if you use IoC containers, your code becomes, frankly, a lot harder to read. The number of places you have to look at to figure out what the code is trying to do goes up by at least one. And somewhere in heaven an angel cries out.
I mentioned in my last post, in the comments, that I’m no stranger to disagreeing with Joel. It crosses the line, however, when he advocates idiocy – the notion that *you* are too dumb to figure this stuff out.
Are you?
It took me 7 minutes to read it and understand it. I was following these patterns except the IoC container part. I was, as you was saying, going nuts with controllers. Now I can simplify my MVC apps.
Thank you!
I do agree with one of Joel's points that you quoted - that the people who use IoC containers are lacking in empathy for people who aren't as smart as they are. I suspect that they think of it as not wanting to sacrifice quality design to appease the set of developers who aren't interested in learning.
It is straightforward and ease people of the burden of reading a 200 pages manual :ppp
Actually, watching your video is the next way to turn. It is downloading by the way lol
But is it me or you jumped ovre the step that shows how to actually implement it? :
"I can override my ControllerFactory and ask StructureMap to build my Controllers for me".
That seems pretty straight forward for any developer already using IoC, but as the post is meant to be a manual, I expeceted to see that here too.
Hate those wobbly go-karts man. All seems good then the wheels fall of at top speed in the middle of the race.
I agree with you on technical debt and DI vs Naked DI, and it really is an investment. But will that investment ever pay off if you don't change your database?
Just a minor detail: in a sample you named your constructors PostRepository instead of PostController.
...just kidding!
But the investment is minimal. You start writing some new functionality, so you start with a test. The test needs to access the repository so you test using the repository interface (and a fake/mock).
You feel the speed because you're testing logic, without any concerns about data access etc. You can quickly change the tests, and the logic and check if it still works.
Actually the "investment" is probably a lot less time consuming than having your data access code embedded in the controller somewhere, because with that scenario you will a)spend ages trying to write tests around it and hitting brick walls or b) spend ages firing up the browser and clicking to test that things act as they should.
On the point of change, I am in the middle of changing an app from Subsonic to NHibernate (sorry Rob, nothing personal just keen to try all the options) and know that as long as the implied contract (as defined by the interface) is maintained, everything will continue to work (and my tests will help to verify that).
This is a wonderful article on Dependency Injection. I have been using Spring.NET for injecting dependencies in my projects. I was thinking of writing a small post myself on dependency injection, which I might still do. But your's is quite an elaborate article on this topic. Thans for such wonderful writeup.
Avesome post, I'll be using this for training the developers in our company on IoC. You made me laugh several times, and you explain it plain and simple. DI and IoC is not for the cool kids only, it's actually the most important principle/pattern you can learn as programmer. And it's NOT rocket science - a fact you demonstrated here perfectly.
Thanks.
These will no doubt all be resolved by Joel one day, probably when he issues a Uwe Boll style combat invitation, asking everybody who uses techniques he regards as complicated to come down personally to his white padded "boxing ring".
Until this year, though, IoC might have been regarded as slightly mysterious by people, including myself, because of the absence of introductory articles such as this.
But recently exponents such as Scott Guthrie, Castle, and yourself have helped a lot by realising that very basic introductions are needed for the duct tape masses.
"Joel Joel Joel you float,
ideas of idiocy,
Along comes our RobCon,
who makes it clear to me!"
Cheers,
Dan
Is it possible to use a technique similar to your StructureMapControllerFactory for webforms?
Rich
Rob says:
“I’ve used StructureMap a lot as it’s what I know – but Ninject or any other framework is pretty easy to pick up, no Big Brain required”
You imply that all IoC containers are created equally .. is that true? Is it really only about familiarity?
I've personally always preferred service locator because it involves so much less magic.
I totally get it when it comes to things like "injecting" a repository into a controller. But then I see examples going haywire, with people giving examples of INotificationSender or IEmailTemplateProvider or IPizzaOven. It just so happens that an object in my domain model might want to send a notification, send an e-mail, or bake a pizza in response to an event. How does that object get a reference to the object that it needs?
Do I have an insane constructor party, where the IoC container lives at the "top" of the application and any dependencies are passed from object to object like a hot potato (aka "new SillyController(ISallyRepository repo, INotficationSender notifier, IEmailTemplateProvider emailer)")? What if the objects at the top of the application don't even "need to know" that my domain object has this dependency?
Do I wrap my IoC container in a static class and reference it anywhere I please? Isn't this pretty much just a service locator then? Why wouldn't I just use that pattern since I could at least see it in a debugger?
Do I move the notificaton-sending, e-mail-sending, pizza-baking functionality to the "top" of the application near where the IoC container lives (that is, say, in the controller)? That seems to degenerate into the Transaction Script pattern with an anemic domain model.
THAT is the part of IoC that seems to require the 200-page manual, and I will admit that I just don't get it. Help!
Actually, its not so much that I don't buy into IoC, but I don't buy into any kind of mentality that suggests there is only one way to do something (which is the prevalent attitude I sense from the IoC crowd).
In this simplified example above you switched from 3 lines of easily understandable code to something that requires code in the global.asax, another couple classes, and an interface. The end result contains an extra line or two of code, but now the whole thing is "reusable" and can be unit tested. I happen to agree with Joel's quote which you openly mocked... it *is* more convoluted. It *is* harder to read and grok. And this was an overly simple example... I'm sure it gets more convoluted with large projects.
That said, and I know it won't be popular in this crowd, lets change subjects a tad. Joel Spolsky says some dumb things every so often. We all know it. But you really need to stop harping about it. I can disagree with people about technical matters and still respect them, but when they attack other people's opinions...well, thats another thing entirely.
So "Inversion of Control" is basically a Factory pattern fully implemented? As in "this is how it always should have been"...
I like this post and I'm sold on the benefits but was hoping you were going to illustrate how the ControllerFactory is implemented and uses Inversion of Control to provide an example :( Will have to try watch video later (easier to read in the office).
Overall - nicely written
Good job on writing an introduction to IoC/DI. I got a good laugh at your reposes to Joel's comments.
I find it ironic that Joel thinks that people who use IoC lack empathy towards the common user. He has repeatedly demonstrated this same lack of empathy, when he talks about writing his own custom compiler as if it were a hello-world application.
Adam
public PostRepository(IPostRepository postRepository){
should be
public PostController(IPostRepository postRepository){
on a more serious note, nice post, thanks!
Second, is it just me or is there a higher incidence of references to illegal substances in your writing since your departure from Microsoft?
I am trying to convince myself that you spend weeks or even months working on one article and that after 1,000 revisions you finally come up with what you write on your blogs. I am doing this because if you are able to explain topics, such as this IoC article, in the clear and humorous ways that you do without the agony that I envision then I have some self esteem issues to address. As someone who has tried countless times to explain & debate concepts such as IoC and TDD to programming squares I appreciate what you are able to pull off in your articles.
Keep up the good work!
as this is my first post ever (here, but we changed messages on StackOverflow) I must say that I do love your blog and I wish I'll became a great developer like yourself ... and for that I would suggest something ...
I like tutorials, I love posts and I tend to do all as I can, but sometimes I'm stuck in really easy stuff cause I loose myself on all the letters... I am a great fan of screen casts, and for this I would suggest that u could post a poll just to see how many of us loved to have a less than 5 minutes (maybe using JING) area in this blog ... not for all stuff, but I do thing it's much easier to record something and doing it live than copy/paste images and create a how-to tutorial like you present us several times ....
what do u think? and ... what do you readers like me think?
keep your fingers tickling on that keyboard ;)
I thought could Rob actually be saying these things? Anyway, about the only thing I sort of concur with Spolsky is that
some of the IOC providers make it seem complicated. When I first looked at StructureMap I didn't really know what an IOC was
and I had a heck of a time finding any "getting started" documentation. About a year later I looked again and found 3 or 4
different ways of doing the configuration and none of it worked for me. Then I tried Unity and had it working in a few
minutes. So no it isn't rocket science but sometimes not well explained. At least you've filled that gap now.
Also, here's the Fowler article. When in doubt, it's almost always a good idea to see what Martin says. http://martinfowler.com/articles/injection.html
I find that hilarious and true! No matter how many times you hit F5, its is amazing to see DB data on the screen!!!
public PostRepository(){
}
public ActionResult Index(){
var repo=ObjectFactory.GetInstance();
var posts=repo.GetPosts();
return View(posts);
}
Don't you think it's good to have someone on the other side of the fence who's very intelligent and often makes interesting observations? Obviously (to me, you and most at least) in this case he was wrong. But in may other instances it's not so clear. And for that reason he is still very well worth paying attention to :).
In many IoC, you can setup the mappings in XML. How does this help you ask? Well, what if you have several servers (dev, staging, prod), you simply swap out your config file and go on your merry little way.
Too bad it took 5 months to condense that 200 page manual and respond to Joel's post from May 16th ;)
I agree and disagree with you on this topic.
This is the newbie's guide that I could have used a year ago. As an adult student programmer who's been coding for about two years now, I was first truly introduced to IoC and DI from your storefront video with Jeremy Miller. It looked really cool and useful, but it was somewhat complicated to figure it out at the time because finding relevant and up-to-date Asp.net MVC and StructureMap information wasn't as straight forward as it is now. I did blunder around for a bit and get it figured out and integrated into my asp.net mvc app, but there was a cost of learning that I had to pay. With that cost paid, I can leverage my knowledge to apply to any of the handful of IoC containers that are available, but the initial cost cannot be ignored. As you start getting into some of the more complicated use-cases for your IoC container of choice, then you are paying the cost of learning again. However, you typically won't need the complicated usages to get started, so that learning cost can be delayed until it's necessary to pay it. Spolsky alluded to the learning cost as the curse of knowledge article link. The Cool Kids have paid this cost, and cannot empathize with people who haven't yet paid this cost. This lack of empathy caused the massive backlash and internet drama that led us here.
Spolsky makes valid points and never says that IoC is bad, and he answers the question that is asked: "What do I gain using someone else's IoC framework compared to the manual DI that I'm currently using? Is it worthwhile to train my possibly resistant coworkers to use the framework?" Instead of paying attention to that, you focus on the fact that Joel references this hypothetical 200 page manual.
I ran across this post on devlicious regarding the Spolsky kerfuffle: http://devlicio.us/blogs/vinull/archive/2009/10/08/critical-thinking-and-dissent-is-a-requirement.aspx . Spolsky bashing has become an unwritten tenet of the alt.net (AKA the Cool Kids) dogma, and I find it quite distasteful. I find the Cool Kids to be a valuable font of information as I also find Joel Spolsky to be a valuable font of information. It's my duty to myself to sort the relevant and useful information from the less useful information. It's a more important duty to myself not to waste energy focusing on the irrelevant information. This guide is the result of you focusing on a leaf instead of the forest, but it is still very valuable if you take out any reference to Spolsky and simply treat it as the newb's easy start guide to using an IoC framework.
Waiting for the part 2: "Di/IoC Frameworks, Or, are you a poor man?" :D
It's unintentionally hilarious that you paired Spolsky's "200 page" quote with your usage of StructureMap. The training guide (not including the "Quick Start" or "Glossary") is 80 pages and the API clocks in at around 215 pages. Go to http://structuremap.sourceforge.net and see for yourself.
That said, I do like IoC. I just think the community has a tendency of turning things into an overwrought mess.
Loved how you lined up the benefits of IOC/DI in a readable compact way.
I'm gonna use some of it when I'll be explaining these concepts next week to a dev team. :)
Although I agree with all the great points about IOC/DI and I know it's addictive to use (The code is so much cleaner, and all dependencies are explicitly documented through the code, I've seen a lot of developers struggle with the added abstraction. So like everything in live, we should find a middle ground (I am not sure if you say it like that in english, though).
using (IDataAccess dal = new SqlDataAccess(Configuration.ConnectionString) )
{
...//Do data access stuff
}//at this point dal.Dispose() is called immediatly closing connection to Database
Make sure the DI container calls dispose on IDataAccess or Close the connection manually after your done by calling dal.Close() to close the connection immediatly if there is a lot more stuff to do in the web request before it complets. The DI will call Dispose only when the request ends. Assuming you configure the DI container for per web request thread lifetime management.
I find that handling the lifetime management issues seem to be the area that adds a little bit of complexity to DI frameworks
Lastly, StructureMap has a VERY un-IoC feature which you promote it in your 1-page article. Namely ObjectFactory has a static accessor for components. IoC is supposed to eliminate such ideas not encourage them.
- Paul Hammant
( one of the reviewers for Fowler's article, and co-author of the first Constructor Injector DI container - PicoContainer )
I am following your blog for some time and this is a first time that I strongly disagree with you. Yes you are smart and cool, but from bussines perspective you are insane programmer who needs someone to manage him.
So you needed to remove dependancy form DB, you create you interface to introduce low coupling. Now you need your controller to use another repository and usually only in one test class because it is Unit Test. So I use setup method that in one line code with reflection sets a Stub repository class to conroller. You introduce bunch of new concepts and external libraries.
As I see it your approach is more cool and geek in me is crying out to use it, but my is way simpler. You have avoided technical debt only if you ignore increased complexity.
Another thing, yes IoC is super cooland currently heap, but may I remind you that we are professionals, not kids.
//Daniel