Jeremy D. Miller -- The Shade Tree Developer

Sponsors

The Lounge

Wicked Cool Jobs

Syndication

News

Advertisement

Images in this post missing? We recently lost them in a site migration. We're working to restore these as you read this. Should you need an image in an emergency, please contact us at imagehelp@codebetter.com
Before you use an IoC tool, some concepts to know first
 
JEREMY’s NOTE:  I’m trying to rewrite the StructureMap documentation today, and I’m going to blog most of it out here as I finish it until Brendan tells me to stop polluting the main feed.  This article is intended to be an introduction to the concepts behind an IoC tool for folks with little or no previous exposure.  Feedback will be very much appreciated.
 
 
From my original release back in June 2004:  StructureMap is a Inversion of Control (IoC) slash Dependency Injection framework that can be used to improve the architectural qualities of an object oriented system by reducing the mechanical costs of good design techniques.  Using StructureMap does not in any way improve your architecture per se, it simply strives to make the mechanics of a good Object Oriented Design cheaper to implement.  Additionally, StructureMap allows you to efficiently exploit a well designed Object Oriented architecture to provide extensibility mechanisms, flexible deployment options, and self validating configuration and deployment.

Over the years a series of concepts and principles have been discovered and developed to describe well-structured Object Oriented systems.  To most effectively use StructureMap, or any other IoC tool for that matter, your system needs to be designed with these principles first:

To sum it all up, well designed Object Oriented systems are composed of many objects that work with each other to accomplish to goals of the system.  We want our systems to be decomposed into cohesive classes that perform a well defined responsibility within the system, rather than monolithic “God” classes that do too much.  A cohesive class will have to be dependent upon other classes to perform services outside of its own tightly defined responsibility.  In IoC speak, we call the collaborating objects dependencies

 

Dependencies

For example, in my current system we have a class called AddressEditController that governs the creation and editing of Address entities in our web based UI.  The AddressEditController needs to validate user input and persist or load data.  Those are two distinct responsibilities, so AddressEditController has dependencies on other objects for these services. 

    public class AddressEditController : Controller

    {

        // AddressEditController uses IValidator to validate user input

        // and IRepository to load and save Address information

        private readonly IValidator _validator;

        private IRepository _repository;

 

    }

So here’s some facts about AddressEditController:

  • AddressEditController depends on IValidator and IRepository 
  • AddressEditController cannot function unless it has both an IValidator and an IRepository
  • From the concepts section above, for best results, the AddressEditController should be loosely coupled to its dependencies by knowing as little about the inner workings of the real IValidator and IRepository
  • The real IRepository is a Gateway into NHibernate. The concrete Repository class cannot be used without its own dependency trail of external configuration, a Singleton to keep track of an expensive resource, and some NHibernate bootstrapping code. 

Just calling a new() constructor on its dependencies isn’t the best design for our AddressEditController.  Creating a concrete Validator class is very possible, but what if we want to selectively replace the implementation of IValidator later?  That’s only somewhat likely, but the dependency on Repository is a much larger concern.  I might have semantic decoupling between AddressEditController and Repository, but if AddressEditController calls new Repository() itself, AddressEditController will not be able to function without all that NHibernate bootstrapping.  I do not want a piece of my user interface to be tightly coupled to the existence of the persistence layer. 

In other scenarios, creating the dependencies may involve more than just calling new() on the dependencies (don’t believe me?  Go try to create an HttpContext object).

AddressEditController is responsible for the workflow around editing Address entities in the UI.  It shouldn’t be concerned with NHibernate configuration and whatnot.  One way to solve this problem is to move the responsibility for building its dependencies to somewhere external to AddressEditController

 

Inversion of Control and Dependency Injection

In many cases, I don’t want my classes to have to be aware of how their dependencies are created or located.  I don’t want controller classes to even care that they’re using an object that is created via Microsoft’s Provider infrastructure, or a Singleton, or needs configuration data.  My class should only know the public interfaces of its dependencies.  I can make that true by applying “Inversion of Control.”  Instead of doing:

        public AddressEditController()

        {

            _validator = new Validator();

            _repository = new Repository();

        }

where AddressEditController calls linearly through to the constructors on Validator and Repository, we can invert the control to make the creator of AddressEditController responsible for building the dependencies and “pushing” them into AddressEditController

    public class AddressEditController : Controller

    {

         private readonly IValidator _validator;

        private IRepository _repository;

 

        public AddressEditController(IValidator validator, IRepository repository)

        {

            _validator = validator;

            _repository = repository;

        }

    }

The code sample above uses a form of Inversion of Control called Dependency Injection to push in the dependencies via a constructor function.  Of course, at some point, something needs to know how to create the entire chain of dependencies and do all of that Dependency Injection.  StructureMap supports a pattern known as Service Locator:

            // Creates an AddressEditController with all of its dependencies

            AddressEditController controller = ObjectFactory.GetInstance<AddressEditController>();

ObjectFactory is a StructureMap class that serves as a well known place to go and find any service that you need.  When the AddressEditController is created and returned by ObjectFactory, it should be completely ready to go.  There’s another important concept to understand before you use StructureMap. 

 

Auto Wiring

Every "real" IoC container supports the concept of "Auto Wiring."  Auto Wiring simply means that StructureMap can figure out dependency chains for you without a lot of explicit configuration.  When you ask for AddressEditController, there is more going on than just AddressEditController and its two dependencies.  The Repository class itself has its own dependencies.

        [DefaultConstructor]

        public Repository(ISessionSource source) : this(source.CreateSession())

        {

 

        }

In turn, the concrete version of ISessionSource above has its own dependencies:

        public SessionSource(IDictionary<string, string> properties, PersistenceModel model)

        {

            _configuration = new Configuration();

            _configuration.AddProperties(properties);

 

            model.Configure(_configuration);

 

            _sessionFactory = _configuration.BuildSessionFactory();

        }

which starts to get interesting because SessionSource needs some information like connection strings that have to come in from Xml configuration: 

<StructureMap MementoStyle="Attribute">

  <DefaultInstance

    PluginType="ShadeTree.DomainModel.ISessionSource,ShadeTree.DomainModel"

    PluggedType="ShadeTree.DomainModel.SessionSource,ShadeTree.DomainModel">

    <properties>

      <Pair Key="connection.provider" Value="NHibernate.Connection.DriverConnectionProvider" />

      <Pair Key="connection.driver_class" Value="NHibernate.Driver.SqlClientDriver" />

      <Pair Key="dialect" Value="NHibernate.Dialect.MsSql2000Dialect" />

      <Pair Key="hibernate.dialect" Value="NHibernate.Dialect.MsSql2000Dialect" />

      <Pair Key="use_outer_join" Value="true" />

      <Pair Key="connection.connection_string" Value="a connection string that I’m certainly not giving out to you!" />

      <Pair Key="show_sql" Value="true" />

    </properties>

  </DefaultInstance>

</StructureMap>

Here’s some of the configuration for the other services that the entire EditAddressController needs:

            ForRequestedType<IValidator>().TheDefaultIsConcreteType<Validator>();

            ForRequestedType<IRepository>().TheDefaultIsConcreteType<Repository>().CacheBy(InstanceScope.Hybrid);

            ForRequestedType<PersistenceModel>().TheDefaultIsConcreteType<DovetailPersistenceModel>();

At no point did I specify that EditAddressController needs an IRepository that needs an ISessionSource that needs 2-3 other things, but yet when I call:

            // Creates an AddressEditController with all of its dependencies

            AddressEditController controller = ObjectFactory.GetInstance<AddressEditController>();

StructureMap will construct EditAddressController that had a new instance of Repository that had a new instance of SessionSource that had an IDictionary<string, string> object and a new instance of DovetailPersistenceModel.  I don’t have to explicitly tell StructureMap to do that for me because it uses its “Auto Wiring” feature to examine the dependencies of each concrete class and act accordingly.  StructureMap does need to know what to do with each type of object it encounters.  When it tries to build the Repository class StructureMap sees the constructor argument for ISessionSource on Repository, and knows to build and inject a new SessionSource object (and so on as deep as you need to go).


Posted Sun, Jun 29 2008 4:40 PM by Jeremy D. Miller
Filed under:

[Advertisement]

Comments

Jeremy D. Miller wrote re: Some Concepts to Know First
on Sun, Jun 29 2008 4:42 PM

Another note, It'll be published in a wider format, so the code getting cut off won't be quite the same issue

jdn wrote re: Before you use an IoC tool, some concepts to know first
on Sun, Jun 29 2008 8:35 PM

This is good stuff, very helpful, especially for people like me who are using StructureMap 'in anger' for the first time.

Thanks.

Jeremy D. Miller wrote re: Before you use an IoC tool, some concepts to know first
on Sun, Jun 29 2008 8:37 PM

@John,

Please feel free to drop me a line if anything is confusing or unclear about the API or in the docs.

jdn wrote re: Before you use an IoC tool, some concepts to know first
on Sun, Jun 29 2008 9:50 PM

@jdm

Yep.  I'm obviously not starting with the most complicated uses of SM, so I expect the API to lead the way, but will send anything if it isn't obvious.

Afif wrote re: Before you use an IoC tool, some concepts to know first
on Sun, Jun 29 2008 9:55 PM

Jeremy,

I would be very interested in knowing what are your views on Ninject(another IOC container)? Have you had a chance to look at in any detail? I am fairly across the reasons for using IOC and the benefits it brings, but am yet to dive into a tool, simply because I haven't had a chance to use it at work, and also a bit reluctant before starting to choose one that has the smallest learning curve and complexity from a user's perspective. Going by the tutorials ninject seems pretty decent(read: easy to learn), specially with no 'xml' configuration files.

While I imagine your views will be baised with you authoring StructureMap albeit they will still be very helpful.

- Cheers

Jeremy D. Miller wrote re: Before you use an IoC tool, some concepts to know first
on Sun, Jun 29 2008 10:35 PM

@Afif,

I purposely avoid looking too deeply at the other IoC tools, so I'm not really the right source.  You can use both Windsor and StructureMap w/o any Xml, so that isn't really unique.  I've put a bit of effort to make StructureMap more accessible for newcomers, but the biggest part of that effort is probably in the form of (unwritten) documentation.

Honestly, they're not that different for the simple things.  Just don't repeat that I said that, okay?

Reflective Perspective - Chris Alcock » The Morning Brew #125 wrote Reflective Perspective - Chris Alcock &raquo; The Morning Brew #125
on Mon, Jun 30 2008 3:30 AM

Pingback from  Reflective Perspective - Chris Alcock  &raquo; The Morning Brew #125

tomdekoning wrote re: Before you use an IoC tool, some concepts to know first
on Mon, Jun 30 2008 5:01 AM

Hi Jeremy,

I will be starting today with StructureMap as well. Will let you know if anything is unclear..

KR,

Tom

Asa wrote re: Before you use an IoC tool, some concepts to know first
on Mon, Jun 30 2008 7:03 AM

Hi Jeremy,

Forgive my dumb question, but does using an IOC tool mean giving up the New Keyword to initialize objects?

DotNetKicks.com wrote Some concepts to know before you use an IoC tool
on Mon, Jun 30 2008 7:03 AM

You've been kicked (a good thing) - Trackback from DotNetKicks.com

Dew Drop - June 30, 2008 | Alvin Ashcraft's Morning Dew wrote Dew Drop - June 30, 2008 | Alvin Ashcraft's Morning Dew
on Mon, Jun 30 2008 8:01 AM

Pingback from  Dew Drop - June 30, 2008 | Alvin Ashcraft's Morning Dew

tomdekoning wrote re: Before you use an IoC tool, some concepts to know first
on Mon, Jun 30 2008 9:05 AM

Hi Jeremy,

Where can I find the documentation on structuremap? When I look at sourceforge.net/docman there is no documentation available, or am I missing something?

KR,

Tom

Jeremy D. Miller wrote re: Before you use an IoC tool, some concepts to know first
on Mon, Jun 30 2008 9:12 AM

Tom,

I'm writing it as fast as I can.  There is existing documentation for StructureMap 2.0 at structuremap.sourceforge.net

tomdekoning wrote re: Before you use an IoC tool, some concepts to know first
on Mon, Jun 30 2008 9:21 AM

Sorry, I don't know how I could have overlooked that one. Thanks!

Kerry wrote re: Before you use an IoC tool, some concepts to know first
on Mon, Jun 30 2008 9:40 AM

We're still behind the curve a bit on IoC, so I hope a few rather basic questions are tolerable.  I'm not sure if we'll get to use Structure Map per se, but these may help with our general architecture.

The first thing that comes to mind is how does ObjectFactory know when to use an object that has had state modifications as opposed to a new one?  One example I have is a specification we use that compares a base object's (a "Firm.Type") property to that of an object of a different type ("Employee.FirmType").

When a Firm is edited, we need to modify each one of it's employees to make sure the types match.  However, when an employee is modified, we need to make sure of the same thing (because an employee can be removed from the firm by setting Firm.Type to none).

So passing in a stateful firm to the Specification is critical when the specification is originated from a firm modification, but we need a new firm from the database when the employee is modified.

How does IoC handle this?

Chad Myers wrote re: Before you use an IoC tool, some concepts to know first
on Mon, Jun 30 2008 11:33 AM

@Kerry:  I'm not sure what you're trying to accomplish here. Why should Employee care what exact type of Firm it has? Doesn't that violate the Liskov Substitution Principle?  Employee should have a Firm. It can be any type of class as long as it derives from Firm.  

I don't think this problem has anything to do with IoC, so this may not be the best place to ask this kind of question.

What are you trying to do with the Employee/Firm stuff and how are you using IoC in your project? Maybe that'll help us understand what you're up to.

Nate Kohari wrote re: Before you use an IoC tool, some concepts to know first
on Mon, Jun 30 2008 11:44 AM

@Afif

Ninject is my framework, so naturally I would suggest you check it out. ;)

However, StructureMap is great, as are other frameworks like Castle Windsor and Autofac, and Jeremy is right in that they are very similar for the simpler cases. However, each has nuances -- for example, Ninject provides context during activation, so the activation process is more programmatic and less of a "map lookup". This lets you do some interesting things depending on state when your instances are being resolved and activated.

I also haven't dug too deeply into StructureMap's internals, so I can't conclusively say either framework is "better". I think it comes down to a matter of taste, and you should try each of the different tools and decide which of them feels right to you.

RobinClowers wrote re: Before you use an IoC tool, some concepts to know first
on Mon, Jun 30 2008 1:17 PM

Hi Jeremy, thanks for this post, it helped me understand exactly what auto wiring is and how it relates to the service locator pattern.  Another thing I would like to see is some info on the different config options, especially the fluent API.

Arjan`s World » LINKBLOG for June 30, 2008 wrote Arjan`s World &raquo; LINKBLOG for June 30, 2008
on Mon, Jun 30 2008 2:30 PM

Pingback from  Arjan`s World    &raquo; LINKBLOG for June 30, 2008

Andrei Butnaru's blog wrote Programming links 06.30.2008
on Mon, Jun 30 2008 2:38 PM

Programming links 06.30.2008

Guy Ellis wrote re: Before you use an IoC tool, some concepts to know first
on Mon, Jun 30 2008 3:26 PM

I haven't used StructureMap (yet) but that was an excellent explanation of IoC and DI - thanks!

Frank Smith wrote re: Before you use an IoC tool, some concepts to know first
on Tue, Jul 1 2008 7:44 AM

Overall, this is a good article. Just one point... I don't think you are using the word "cohesive" in the correct way. The concept of cohesion at the class level isn't related to whether the class depends on other classes or not.

See also:

javaboutique.internet.com/.../coupcoh

www.developer.com/.../3327121

"A cohesive object is one that cannot easily be broken up into multiple objects. It is an object that has one clear purpose and one clear entity that it represents."

Jeremy D. Miller wrote re: Before you use an IoC tool, some concepts to know first
on Tue, Jul 1 2008 8:10 AM

@Frank,

I didn't mean to imply that "cohesive" automatically means that a class depends on other classes.  What I meant was that a class that is cohesive will *have to depend on other classes for services outside the scope of its own cohesive responsibilities*

The point I was going for is that classes are not monolithic and interact with each other.

Kerry wrote re: Before you use an IoC tool, some concepts to know first
on Tue, Jul 1 2008 9:37 AM

@Chad,

Thanks.  It's not the type of firm, it's which firm.  In the one case, the firm has been edited (but not yet persisted) and we're trying to make sure all of its clients are updated with the edited properties (may be a smell there, but that's a requirement at this point).

In the other case, we want to be sure that the client has the same settings as an already persisted firm.

If that's not clear enough, I'll be more than happy to take it offline - I don't want to clutter up these comments with it.

Chad Myers wrote re: Before you use an IoC tool, some concepts to know first
on Tue, Jul 1 2008 10:27 AM

@Kerry:

Yeah I'd be interested to hear what's going on there. You can email me firstname.lastname@gmail.com (chad.myers...)

Frank wrote re: Before you use an IoC tool, some concepts to know first
on Tue, Jul 1 2008 7:36 PM

@Jeremy:

I was just attempting to make the point that cohesion and interclass dependency are orthogonal concepts. A cohesive class may or may not have dependencies on other classes. The same is true for a noncohesive class.

Cheers,

Frank

on Sat, Jul 5 2008 11:33 AM

Its about time to clear out the backlog. CLR/.NET/Visual Studio/TDD/ALT.NET Jeremy has a nice piece here

Jonty wrote re: Before you use an IoC tool, some concepts to know first
on Thu, Jul 10 2008 1:58 PM

How do you deal with the fact that certain assemblies do not have references to other assemblies?

I am calling registries in each assembly like below:

StructureMapConfiguration.AddRegistry(new BusinessLogicLayer.DependencyInjectionRegistry());

Then in my BusinessLogicLayer I have:

protected override void configure() {

ForRequestedType<IBusinessLogicStuff>().TheDefaultIsConcreteType<BusinessLogicStuff>();

StructureMapConfiguration.AddRegistry(new DataAccessLayer.DependencyInjectionRegistry());

       }

Is this the correct approach?

Brian Johnston wrote re: Before you use an IoC tool, some concepts to know first
on Thu, Jul 24 2008 9:32 PM

@JEREMY’s NOTE:  I’m trying to rewrite the StructureMap documentation today, and I’m going to blog most of it out here as I finish it until Brendan tells me to stop polluting the main feed.  This article is intended to be an introduction to the concepts behind an IoC tool for folks with little or no previous exposure.  *Feedback will be very much appreciated.*

Two things have always been top-most in my mind:

1) A hello-world walk-through - and I mean 'hello-world' - as dumbed down as it can get with every step there (assume your reader/watcher is complete moron with no ability to figure anything out on there own).

The reason being is people like myself, this is what make or breaks our interest.  Naturally I'll have some interest because I've read your stuff for a while, know your a smart guy, and conceptually understand what your doing with the framework and how it can build a better product, but that alone won't sell me.  When I get on the site and start looking at the API docs, I can only read those long pieces of documentation and all the 'getting into the weeds' code when I have a genuine interest in the technology.  A hello world can actually do that for me.  

Taking your examples above...you lost me pretty quickly - first you hit me with a bunch of design principals, some okay for the context, some a little to technical for newbies (# Open Closed Principle, the Single Responsibility Principle, and the Liskov Substitution Principle and # Dependency Inversion Principle) - pretend your talking to management, keep the summary (and don't be afraid to expand upon it!) and just add those links for 'further reading'.  Next you got straight into real world code.  I don't work where you work - so instead of focusing on how the framework can help me I'm sitting here wondering why you have a separate controller for just handling address because we use a controller that covers the entire customer (including addresses)...see what I'm saying? I'm getting lost in the weeds rather than focusing on the benefits of the framework.  I want the real world code, but later, after I got the framework down.

From a hello world I can generally determine (a) is it the right fit for me on the current project or possibly an upcoming one?  (b) is it going to be hard to get other developers to use (c) is it creating more problems than its solving for my current project (d) am I'm going to spend 80% of my time implementing 20% of the project in order to use this framework (e) (if applicable) can I write tests for code that use this?

2)Know your audience - this kills me, I mean it gives me GREAT pains with Rhino Mocks and why my use of it is minimal - never assume your audience has worked with a similar framework or really 'gets' what the framework is doing conceptually and that all you need is API documentation and a sprinkle of examples with a 2 sentance explanation of what's going on.  

Rhino Mocks for example: conceptually I know what mocks are for, the benefits, etc., I've read every piece of documentation on that website, but can I apply that knowledge using RM?  Only after much grief and then my use of it is minimal because it just doesn't 'mesh'.  I don't know how else to describe it...it's cumbersome, kludgey, reminiscent of RPG with that chaining crap, etc...

Now don't get me wrong, I *know* in reality it's very powerful and it's a matter of experience and someday it will flow like water out of my fingertips (as is this framework) - but it's turning that learning curve from a mountain with a 900ft cliff face to a bump in the ground that you could barely roll a ball down; that's the challenge.

That's my two cents...since you asked.

Angel "Java" Lopez wrote Noticias y enlaces II
on Thu, Sep 18 2008 8:27 AM

Hoy viene una lista de enlaces, sobre tecnologías, sitios, noticias, de varios temas (siguiendo con el

Jeremy D. Miller -- The Shade Tree Developer wrote A Gentle Quickstart for StructureMap 2.5
on Sun, Nov 30 2008 10:56 PM

The most general question I get with StructureMap is “how do I get started?” Personally, I’d recommend

Community Blogs wrote A Gentle Quickstart for StructureMap 2.5
on Sun, Nov 30 2008 11:48 PM

The most general question I get with StructureMap is “how do I get started?” Personally, I’d recommend

A Gentle Quickstart for StructureMap 2.5 - taccato! trend tracker, cool hunting, new business ideas wrote A Gentle Quickstart for StructureMap 2.5 - taccato! trend tracker, cool hunting, new business ideas
on Tue, Dec 2 2008 10:15 AM

Pingback from  A Gentle Quickstart for StructureMap 2.5 - taccato! trend tracker, cool hunting, new business ideas

A Gentle Quickstart for StructureMap 2.5 - taccato! trend tracker, cool hunting, new business ideas wrote A Gentle Quickstart for StructureMap 2.5 - taccato! trend tracker, cool hunting, new business ideas
on Wed, Dec 3 2008 11:04 AM

Pingback from  A Gentle Quickstart for StructureMap 2.5 - taccato! trend tracker, cool hunting, new business ideas

A Gentle Quickstart for StructureMap 2.5 - taccato! trend tracker, cool hunting, new business ideas wrote A Gentle Quickstart for StructureMap 2.5 - taccato! trend tracker, cool hunting, new business ideas
on Thu, Dec 4 2008 11:08 AM

Pingback from  A Gentle Quickstart for StructureMap 2.5 - taccato! trend tracker, cool hunting, new business ideas

Rainer Schuster wrote Der moderne "Programmierer"
on Fri, Dec 5 2008 7:23 AM

Einführung Der Aritkel von Norbert Eder hat mich zum Nachdenken angeregt. Zum Nachdenken über meine aktuelle

on Tue, Feb 3 2009 4:29 PM

Its about time to clear out the backlog. CLR/.NET/Visual Studio/TDD/ALT.NET Jeremy has a nice piece here, Before you use an IoC tool, some concepts to know first Favorite Visual Studio 2008 Keyboard Shortcuts (Corey Schuman) [via Alvin ] MbUnit in Visual

Developer wrote re: Before you use an IoC tool, some concepts to know first
on Mon, Aug 31 2009 11:29 AM

Very good article, very useful.

Add a Comment

(required)  
(optional)
(required)  
Remember Me?
Devlicio.us