5

I am reading currently "Dependency Injection in .NET" by Mark Seemann. And I am wondering what would be the best way to compose a DDD ASP.NET MVC application.

In simplified scenario, the general rule of thumb, would be to have Domain Model which would be core of the application, and would not have any dependencies on Data Layer or Presentation. It would expose certain interfaces which Presentation would use (hence dependency) and Data Layer would implement (hence dependency). So it is all nice and clear.

Dependencies in DDD app

However, now, when we compose the application. Which in case of ASP.NET MVC app we would do in global.asax (http://blog.ploeh.dk/2011/07/28/CompositionRoot). Our composition root will require dependency on all layers, because it needs to register all applicable types.

Composition Root in DDD app

This makes all dependencies looks messy, now Presentation layer has a project reference to Data Access layer (in VS terms). It is easy for a developer to make a mistake and use types form Data Access layer directly, which would effectively couple those layers.

Is there a clean way to solve this conundrum? It almost would be nice to have the Composition Root outside of the presentation layer, but in MVC that would not be possible.

UPDATE

After asking this question I found a related one: DAL -> BLL <- GUI + composition root. How to setup DI-bindings? and it had some interesing solutions. The accepted solution is almost perfect, however I would like the composition root to be outside of presentation layer, and reference presentation layer rather than the other way.

One reason for that is that it is to me more conceptually clear - composition should be on the very top. The other reason is that in my case presentation layer has many DI objects in it already (mostly domain object to view model mappers) and I would like to have them composed in one spot as well.

This thread gave me some ideas though, I think what I am trying to do may be possible.

Community
  • 1
  • 1
Sebastian K
  • 6,235
  • 1
  • 43
  • 67
  • I am using DDD in ASP.net MVC almost exactly like what you want to achieve. I inject all the implementations using Ninject directly from the UI project (inside `Global.asax`). All other classes receive as parameters the interfaces they require to work with (so they are not responsible for creating the objects). The project is pretty big, but this approach worked very nice. If i want to change from Web to Desktop, for example, i just have to re-initialize the interfaces (probably using Ninject again), and nothing else has to change – Catalin Mar 12 '13 at 09:55
  • 3
    `It is easy for a developer to make a mistake and use types form Data Access layer directly, which would effectively couple those layers`. It's easy to a lot of stupid things no matter how you try to prevent it. Don't model your application after what the user may not do. Model it so it's easy to do things correctly. – jgauffin Mar 12 '13 at 11:37
  • I agree with @jgauffin. You should always do code reviews. Even if you do trust the other developers in doing things the right way. And if you don't trust hem, you should probably do even more code reviews. – Steven Mar 12 '13 at 12:42
  • Again, not an answer to your question, but what looks nice and clean design in a graphic can mask hidden complexities - specifically unnecessary abstraction. You could pollute your domain classes with presentation code. See Ayende's post: http://ayende.com/blog/4784/architecting-in-the-pit-of-doom-the-evils-of-the-repository-abstraction-layer – Raul Nohea Goodness Mar 12 '13 at 15:25

4 Answers4

3

It is easy for a developer to make a mistake and use types form Data Access layer directly, which would effectively couple those layers.

It's easy to do a lot of stupid things no matter how you try to prevent it. Don't model your application after what the developer may not do. Model it so it's easy to do things correctly.

he accepted solution is almost perfect, however I would like the composition root to be outside of presentation layer, and reference presentation layer rather than the other way.

My container has support for what you ask. In each project create a single module which registers everything else:

public class CompositionRoot : IContainerModule
{
    public void Register(IContainerRegistrar registrar)
    {
        registrar.RegisterType<ISomeType, SomeType>();
    }
}

In your UI project you simply load all dlls:

registrar.RegisterModules(Lifetime.Scoped, 
                          Environment.CurrentDirectory, 
                          "myproject.*.dll");

That's it (you can also replace most manual RegisterType etc with a single line if you tag your implementations with the [Component] attribute).

https://github.com/jgauffin/griffin.container

Steven
  • 166,672
  • 24
  • 332
  • 435
jgauffin
  • 99,844
  • 45
  • 235
  • 372
  • Your answer does not actually address the question. *"It is easy for a developer to make a mistake and use types form Data Access layer directly, which would effectively couple those layers. Is there a clean way to solve this conundrum?"* – MattDavey Mar 12 '13 at 13:26
  • The question in the update is `The accepted solution is almost perfect, however I would like the composition root to be outside of presentation layer, and reference presentation layer rather than the other way. ` which I do answer. I answered the text you gave in a comment (but I also copied it to the answer now). – jgauffin Mar 12 '13 at 13:31
  • ok great, I removed the downvote. But I still disagree with your answer :P – MattDavey Mar 12 '13 at 13:34
  • OK, I see, so in your case, you remove direct dependency, by registering modules dynamically, run-time. Interesting, I need to look into that. – Sebastian K Mar 12 '13 at 14:25
2

Most IoC containers expose the concept of logically grouping together bindings into a module.

The effect is that only the assembly containing the module needs to know about the concrete implementations, and the composition root only needs to access the modules.

Example (pseudo):

// In data access assembly
namespace MyProject.DataAccessLayer
{
    internal class MyRepository : IMyRepository
    {
        // ...
    }

    public class DataAccessModule : IModule
    {
        void Configure(container)
        {
            container.ForInterface<IMyRepository>()
                     .UseType<MyReposutiry>()
                     .Singleton();
        }
    }
}

// In presentation layer assembly
namespace MyWebApp
{
    void Booptstrap()
    {
        var iocContainer = /* ... */

        iocContainer.AddModule(new RepositoryModule());
    }
}

Notice that the concrete implementation class of MyRepository is internal. Only the module needs to see it.

The natural extension to this pattern is that each assembly exposes only an IoC module publically, all the other concrete classes are an internal implementation detail.

MattDavey
  • 8,897
  • 3
  • 31
  • 54
  • Ok, so in your case you would still have project reference between Presentation and DataLayer, however you will not be able to misuse DataLayer class since those will be internal. Interesting. The only drawback I can see here is that your component interface is directly tied to IoC container. That is if you wrote module registration in autofac you cannot use it with app written in Ninject, or with Poor Man DI. – Sebastian K Mar 12 '13 at 14:29
  • @SebastianK yes that's right, one IoC container would not be able to load a module written for another IoC container. You would have the same problem with jgauffins proposed solution too. If it's important to have an abstraction layer over multiple containers you might like to look into [CommonServiceLocator](http://commonservicelocator.codeplex.com/) - although this does not abstract container configuration. – MattDavey Mar 12 '13 at 17:01
1

One way to attain a greater degree of encapsulation is to expose the domain as an HTTP service, with say ASP.NET WebAPI. The ASP.NET MVC solution would then reference this API. There would be no data access dependencies, only a reference to the service. For simplicity, the published language of the API can be extracted into an assembly that could be referenced by the MVC presentation solution. The trade-off of this approach is added moving parts and the steps involved in creating and managing a service.

Additionally, having the configuration you describe is perfectly acceptable. The encapsulation attained by extracting a service might not be worth the price. Developers should have the discipline to prevent leaks of the sort you describe.

eulerfx
  • 36,769
  • 7
  • 61
  • 83
0

I am working on a solution architected in the way the eulerfx describes above (it was a system requirement rather than my own design choice). It will solve your problem, though you may want to consider separating your domain model classes from your domain. In addition you will need another composition root for the web api services, and as he notes, a further layer of mapping from the webcontroller viewmodels (which will have to be shared between the service and the website) to the domain models.

Ive created a few solutions now using the methods described in the Dependency Injection in .NET book and I can say that using the methods described within it has certainly meant better quality, loosely coupled code.

Good luck!

KerSplosh
  • 466
  • 8
  • 26