Question

I have been reading up on Dependency Injection frameworks. I really fell in love with the idea of separating the concerns and letting the objects do their core work - which is undoubtedly an excellent and long-standing design principle!

However the more I read on DI frameworks, the more I get worried: 1) In the way they "automagically" resolve dependencies 2) About the extreme complexities being introduced in the configuration files

On just the point #2, I have seen my customers spend millions of dollars to train the people on products of which the significant part was how "not" to touch config files. The administrators are now dreading these config files.

Nevertheless, I see another pattern called Service Locators where I could nicely assemble all the "global" services that I want at the start of my application (may be an application host or app context or whatever). Make this service locator globally available and voila!

However I see that there will be less flexibility when using the Service Locator approach when I need more than one type of "global" service based on some criterion (known to whom?)!

So, here I am more confused than before on which direction to take. Though I like the design principle very much, the complexity in the existing frameworks are throwing me off!

Are my concerns genuine? Anybody else feel the same? If so, is there any good alternative for such massively overwhelming "frameworks"?

Was it helpful?

Solution

As Nate mentioned, the "magic" is optional; you can configure everything by hand if you want.

I'd avoid the configuration files initially (or forever!) and configure the container in code. That tends to be much easier to read and maintain. Much of the time you don't need on-the-fly changes to configuration. Customers can't touch the configuration files because they don't exist.

Service locators have downsides; for one, they tend to couple your classes to the locator class/framework. A good DI framework will let you use Plain Old Objects; you may only have a single class in your project that actually uses the DI/IoC framework.

StructureMap and Unity are both pretty simple; give them a try. Start small.

Here's a really simple example with Unity (including inline configuration):

using Microsoft.Practices.Unity;

static void Main()
{
    using (IUnityContainer container = new UnityContainer())
    {
        container.RegisterType<IRobot, MrRoboto>();

        Console.WriteLine("Asking Unity container to give us a Model...");

        Model model = container.Resolve<Model>();
        model.MoveRobot();
    }
}

// class Model

public Model(IRobot robot)
{
    // Unity will hand the constructor an instance of MrRoboto!
}

OTHER TIPS

I personally quite enjoy using Autofac. The container configuration is done through code, at the same time eliminating verbose XML and enabling refactoring support.

One of the best features, though, is modules. They are units of container configuration, allowing you to manage the complexity of the many different components which comprise your application.

I am currently working on a very large project, and the experience is roughly the same as when it was small, meaning this approach scales very well.

A main tenet of DI-enabled classes is that they do not reference infrastructure code. This is the antithesis of the Service Locator pattern. The main downfall of Service Locator is that, in addition to adding complexity to classes which reference the container, there is no ability to change which version of a dependency is resolved.

With "pure" classes that don't reference a container, the resolved version of any given dependency is external to the class being injected.

If you're really thinking about going the Dependency Injection route, I highly recommend giving Martin Fowler's excellent dependency injection article a quick read:

http://martinfowler.com/articles/injection.html

I'm working on a Java project right now with lots of configuration files. We opted up-front for a Singleton pattern to represent our configuration (somewhat analagous to a global solution). Here's the things that drive me insane and make me wish we had a Dependency Injection pattern instead:

  1. Unit testing with globalized patterns sucks. Dependency Injection patterns lend themselves readily to easier unit testing and especially mock object testing. In the singleton-type case, you now have all these unit tests that still need a global state available in order to run. With dependency injection, you can make test-specific mock configuration objects that you pass into your tests. I can't overstate how much easier this makes unit testing. Another excellent paper entitled "Endo-Testing: Unit Testing with Mock Objects": http://connextra.com/aboutUs/mockobjects.pdf

  2. Using a globalized sort of approach works better in smaller systems, but as your numbers of threads grows, they all begin to compete for the configuration resources. You can run into synchronization issues and your configuration accesses can even start to become a bottleneck. This hasn't been a huge problem for us yet, but it's beginning to annoy us all.

  3. Once you go a little ways down a non-dependency injection route, there's no real going back. Going from dependency injection to some sort of globalized pattern is annoying, but doable on a sort of step-by-step basis. Trying to go from a globalized pattern back to dependency injection is a nightmare. I keep wanting to do it on our project and I just can't. It would take an entire development cycle.

Anyway, hope the article and the experience help you make a decision. I'm a long ways down the path you're thinking about heading down and I kinda wish we would've taken the dependency injection route instead :-D

Neither of these are "required" for DI - they are options supplied by some DI frameworks. Personally, I dislike the "automagic" injection too - I can see it working for really small projects, but causing problems on larger projects. For point #2 - I'm not sure I get the point - I've mostly used Spring. Spring provides both XML and Java configuration options. It provides nested configurations. If there's a part of the configuration that you don't want anyone to change and there's a part that you do - separate them into separate configuration files - or make the "changeable" one XML and the other Java. Spring also supports using values from property files which is all that I'd expect administrators to change - administrators aren't programmers - they shouldn't be "re-wiring" your app - just providing appropriate options.

Depending on the language you use there are some DI frameworks that aren't as scary, though you will have some config files, but they shouldn't be scary, but useful.

For example, I have one config file for development, one for testing and one for production.

So, depending on the one I use, the database connections can be changed, and I can swap out the database layer for tests, and use mock tests.

The sysadmins should control the production config files, as the developers shouldn't push anything to production, ideally.

Spring has a nice setup for DI, though it isn't lightweight.

I have found that the Unity Framework isn't trivial to learn, but once you are using it it is pretty easy to add new classes for injection.

So, anything new may be scary, initially, but as you get comfortable with the concept you can see advantages, such as I explained about the three config files.

My situation may be different than yours in that we already have a system designed for very flexible configuration so adding dependency injection to that configuration was almost trivial, but it seems to me that using the service locator pattern will not save you much configuration as you must still specify how to locate the services. Being able to flexibly inject mock objects for testing is an almost invaluable benefit to using dependency injection, so I would say that configuration overhead may just be a cost of doing business you need to accept to gain the benefits.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top