views:

200

answers:

3

Hi

Im fairly new with DDD and Im trying to use IOC in order to loosen up my tightly coupled layers :)

My C# web application consists of a UI, domain and persistence layer. My persistence layer references my domain layer and contains my concrete repository implementations and nhibernate mappings. Currently my UI references my domain layer.

My question : How do I use an IOC container to inject my concrete classes, in my persistence layer, into my domain layer? Does this meen that my UI should also reference my persistence layer?

A: 

No, I wouldn't inject persistence into either model or view.

You really need a separate service tier that sits between view and the rest. The service tier knows about units of work; it orchestrates persistence and model objects to fulfill the use cases.

Model objects need not know about what layer uses them. They express the domain concepts.

duffymo
Are you saying that my 'Service tier' (as you describe it) should reference my persistence layer and domain layer?
MegaByte
Yes, that's correct. The view, which includes controllers, would use references to one or more service interfaces to fulfill the view request. The services use the persistence and model tiers. This arrangement has the added benefit of keeping your services reusable, even if you change view technologies.
duffymo
Great, this makes more sense...but where does the IOC container fit into all of this. They usually say that you setup the IOC container from your front-end, in my case the web application. Can you explain?
MegaByte
No, the front end doesn't set up the IOC container. That's a server-side function. When I write a Spring web app, there's a listener that instantiates the IOC container when the web app is loaded, reads the configuration, instantiates the components, and wires them together. I'd imagine something similar for .NET.
duffymo
A: 

You UI should NOT reference your persistence layer. Using IoC, you would inject the concerns of the lower layer up into the layer above it, in a "stack" arrangement.

So, your IoC configuration will inject the persistence implementation into your domain layer. The domain layer should have no knowledge of persistence except for the interfaces used to save and retrieve domain objects. Those interfaces are implemented by the classes /logic in your persistence layer.

Dave Swersky
So I don`t reference my persistence layer anywhere?...Do you just specify the persistence layer assembly name in the IOC container and it will automatically create the instance?
MegaByte
Yes. The purpose of IoC is to "loosely-couple" your persistence and domain tiers, so that there is no static reference between them. You don't "Add Reference" in Visual Studio. This allows you to "plug in" any of several persistence *implementations* by configuration.
Dave Swersky
ok, so I have tried this. But then the UI developer needs to resolve each service or object in the domain, using the var obj = = (FooService) kernel[typeof(FooService)]; notation...
MegaByte
This isn't The Spring Way. I don't know what IOC/DI framework you're using, but pages don't call services in Spring; controllers do.
duffymo
@MegaByte- your Views should be binding to Models/ViewModels, which expose domain objects (Entities, DTOs, whatever.) The Controllers communicate with the middle tier, where your domain objects and business logic lives. The middle tier gets injected with the persistence implementation from "below".
Dave Swersky
+2  A: 

Dave is right, the purpose of DI and IOC is to loosely couple the components of your system.

Your UI should only know about your Domain, your Domain should only know about your Persistence, and your Persistence should know nothing about anyone else.

Good .NET IoC containers are StructureMap (my preferred), Ninject and Castle Windsor.

There are multiple ways of implementing DI/IoC, the most preferred way is using interfaces.

You would have an interface for your Persistence layer:

public interface IPersistantStorage
{
    List<Foo> GetStuff();
    void AddStuff(Foo f);
}

Likewise for your Domain layer:

public interface IDomainManager
{
    List<Foo> GetStuff();
    void AddStuff(Foo f);
}

Then implement concrete classes for each.

Your chosen IoC container will then "inject" the concrete classes to the constructor.

Here's an example of how it works with StructureMap:

public class SomeClassInUILayerThanNeedsToGetSomeThing
{
     IDomainManager domain;

     public SomeClassInUILayerThanNeedsToGetSomeThing(IDomainManager realDomain)
     {
         this.domain = realDomain;
     }

     public List<Foo> GetSomethingFromSomewhere()
     {
         return domain.GetStuff();
     }
}

Then in the StructureMap bootstrapper (called usually in your application start event - Global.asax)

public static void ConfigureIoCFramework()
        {
            ObjectFactory.Initialize(x =>
            {
                   x.For<IDomainManager>().Use<DomainManager>();
                   x.For<IPersistantStorage>.Use<NHibernateStorage>();
            });
        }

All your UI knows is that its going to call some Domain class that implements some interface. All your Domain knows is that its going to call some Persistence class that imlplements some interface.

The "How" or this "What" is handled by the DI Container above.

How you setup what depends on your system. I typically have this setup:

  1. Website -> references 2 assemblies: Common (extension methods, business entities, etc), Service (like a calling point from UI - layers on caching to persistence storage, etc)
  2. Service -> references 1 assembly: Repository
  3. Repository -> references nothing.

Then i would inject a concrete implementation of a service layer into the UI, and inject a concrete implementation of the repository into the Service layer.

If you then look at your solution properties, look at the Web project, you will only see 2 depedencies. In particular, it will not depend on the persistence layer.

If you want to pass around objects, consider projecting your tables into POCO's (contained in the Common assembly).

RPM1984