Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

OOD using IoC containers - how to construct dependant objects?

I am trying to get better with IoC,DI and OOD for better testability and looser coupling.

So when we design classes with heavy use of IoC and DI we can endup with classes with multiple dependencies for example

class Processor
{
    private IService1 m_Service1;
    private IService2 m_Service2;
    private IService3 m_Service3;

    //approach 1 
    public Processor(IService1 service1, IService2 service2, IService3 service3)
    {
        m_Service1 = service1;
        m_Service2 = service2;
        m_Service3 = service3;
    }
    //approach 2
    public Processor(IContainer container)
    {
        m_Service1 = container.Resolve<IService1>();
        m_Service2 = container.Resolve<IService2>();
        m_Service3 = container.Resolve<IService3>();
    }

    //approach 3
    public delegate Processor Factory();

}

Im thinking what should be the usual approach here. We can leave constructor with 3 parameters, but if we are building app using autofac (for example) most likely it will rarely be used other than by resolving types from some container instance like

    Processor proc = new Processor(
 container.Resolve<IService1>(),
 container.Resolve<IService2>(),
 container.Resolve<IService3>());

so I am thinking maybe approach 2 is better, when we depend on multiple types from container. Anyway we will have to add reference to autofac somewhere, so any reasons not to do it now?

Autofac also provides delegate factory method approach

http://code.google.com/p/autofac/wiki/DelegateFactories

var processorFactory = container.Resolve<Processor.Factory>();
Processor processor = processorFactory.Invoke();

So we have also approach 3 - we will not use constructors to create our class instances, instead we will be calling resolved delegate from container and it will resolve dependencies for us.

Since im fairly new to IoC its hard to say when we should use 1,2,3. They have advantages and disadvantages.

I think generally if class has 1 dependency we can probably always use approach 1.. other than that I am really not sure what to choose and when.

UPDATE i have read about service locator anti pattern but Ive come up with 4th (or true 3rd approach)

its close to ServiceLocator except its not, we pass an object that looks like this

public class ServiceLocatorObject
{
        private IService1 m_Service1;
        private IService2 m_Service2;
        private IService3 m_Service3;
        public IService1 Service1 {get {return m_Service1;}}
        public IService2 Service2 {get {return m_Service2;}}
        public IService3 Service3 {get {return m_Service3;}}

        public ServiceLocatorObject(IService1 service1, IService2 service2, IService3 service3)
        {
            m_Service1 = service1;
            m_Service2 = service2;
            m_Service3 = service3;
        }
}

And now we create

//approach 4
public Processor(ServiceLocatorObject servicesToUse)
{
    m_Services = servicesToUse;
}

Now we have decoupled our class from service implementations and its clear what real dependencies it needs (if we assume all services availabe on passed object are required) because we aren't passing a container that can contain 100 implementations. And that object can be even reused if that 3 service combination might be required in some another class in our application. So we are using constructor DI not ServiceLocator pattern. interface is clear and not overloaded with dependencies, new class might be a good reuse candidate.

What would you say about this one?

like image 851
Valentin Kuzub Avatar asked Aug 13 '11 03:08

Valentin Kuzub


People also ask

What is dependency injection and IoC container?

Dependency Injection is the method of providing the dependencies and Inversion of Control is the end result of Dependency Injection. IoC is a design principle where the control flow of the program is inverted. Dependency Injection is one of the subtypes of the IOC principle.

How does dependency injection container work?

A DI Container is a framework to create dependencies and inject them automatically when required. It automatically creates objects based on the request and injects them when required. DI Container helps us to manage dependencies within the application in a simple and easy way.

How do IoC containers work?

IoC Container It manages object creation and it's life-time, and also injects dependencies to the class. The IoC container creates an object of the specified class and also injects all the dependency objects through a constructor, a property or a method at run time and disposes it at the appropriate time.

Which of the following can be created and configured using IoC container?

Spring IoC Container is the core of Spring Framework. It creates the objects, configures and assembles their dependencies, manages their entire life cycle.


1 Answers

The service location pattern is often considered an anti-pattern these days (using container.Resolve and injecting the container).

After MUCH struggling with this concept myself and trying to decide if I like it or hate it, I've come to the personal realization that I agree service location is an anti-pattern - because it obfuscates the interdependencies which exist and which are a core concept of OOP.

Have a read here: http://blog.ploeh.dk/2010/02/03/ServiceLocatorIsAnAntiPattern.aspx

I actually LIKE that fact that in option 1, Process CLEARLY expresses its dependency on each of the services it lists are parameters in the constructor. It makes the dependencies very obvious....and further I think it helps promote good design.

Just saying Processor takes an IContainer doesn't tell us very much...and thus you need to take a much closer look to identify interdependencies.

like image 86
Jeff Avatar answered Sep 28 '22 02:09

Jeff