Project references in DDD

Designing a large application with Domain Driven Design (DDD) can give headaches when the number of projects in a solution grow. The more domain projects and accompanying services/repository-projects we have, the greater the chance that we (accidentally) reference a service-project from a domain project making that domain project dependent on the underlying database or ORM. That’s because the serviceprojects use factories and repositories which are relying upon the datatier.

These are things we don’t want in domain driven design so we need to keep an eye on the references in our solutions.

A few rules of thumb

  • Domain projects should not depend on the database (or ORM) but only contain business logic
  • Service projects connect the domain projects with the database (via ORM) or external services by referencing and controlling the domain objects. This means the concrete service classes and repositories are contained within the service projects.
  • Domain classes might need to call repositories of other domains. This can be the case where domain boundaries are crossed.
  • Usually each domain project has an accompanying service project

The above rules of thumb are a way of keeping the domain projects “clean” so that the domain projects do not reference the database or your favourite ORM tool like NHibernate. Instead, to access root aggregates of underlying dependend domains, we program against the repository-interfaces of those underlying domains instead of programming against the concrete implementations of the repositories in the service projects.

This calling of repositories of underlying domains can be achieved by decorating domain classes with repository-interfaces. That is, domain projects contain the interfaces of repositories or service classes while the implementation of those interfaces are in the service projects. This keeps the domain projects free of references to the database or ORM tool.

For more information and examples see http://stackoverflow.com/questions/693221/ddd-where-to-keep-domain-interfaces-the-infrastructure

With these rules in mind, we can find out how the references withih a certain solution actually are placed. A good way of looking at all the references in a solution is by creating a graph. Luckily, Jamie has written a nice .net program that can show the dependencies between projects in visual studio

The program Jamie wrote generates a .dot file for the references of all projects in a solution. A .dot file is a definition for a graph and looks something like this:

digraph G {
size="7,7";

0 [label="PollingService", shape=component, style=filled, fillcolor=Green];
1 [label="PollingService.Core", shape=component, style=filled, fillcolor=Green];
2 [label="Core", shape=component];
3 [label="Services.Core", shape=component, style=filled, fillcolor=LightBlue];
4 [label="Services.Settings", shape=component, style=filled, fillcolor=LightBlue];
5 [label="TaskService", shape=component];
6 [label="Services.AdminService", shape=component, style=filled, fillcolor=LightBlue];
7 [label="Services.TaskService", shape=component, style=filled, fillcolor=LightBlue];
8 [label="Logging", shape=component];
9 [label="Services.Logging", shape=component, style=filled, fillcolor=LightBlue];
10 [label="Airware", shape=component];
11 [label="Caching", shape=component];
12 [label="Services.Caching", shape=component, style=filled, fillcolor=LightBlue];
13 [label="Settings", shape=component];
0 -> 1 [ ];
1 -> 6 [ ];
1 -> 4 [ ];
1 -> 7 [ ];
1 -> 3 [ ];
1 -> 5 [ ];
1 -> 2 [ ];
2 -> 8 [ ];
3 -> 8 [ ];
3 -> 9 [ ];
[ cut for brevity ]

The bottom of the file is the definition of the references between the projects in the solution.

This .dot file can than be used as input in GraphViz, a tool that can generate a nice looking graph of the dependencies of your projects. Eventually, with some tweaking for colours this is the result of one of our applications:

Project dependency graph

I’ve chosen to colour the top two projects in green because those projects contain the application layer, the blue projects are the services projects that connect the domain projects with external services or the database, via ORM like NHibernate and the projects in white are the domain projects containing the business classes. As you can see this is a very “clean” solution. No domain project is referencing a service project, so no domain project has (secret) dependencies onto the database. I encourage you to try this out for the solutions in your projects. Dividing the projects up so that no domain class CAN reference a concrete repository is a good way of keeping your domain driven design clean.

Are all our applications this clean?

Of course not. It turns out that in another application, we found that certain domain projects were referencing some service projects, giving them an indirect relation to the ORM or database.

Only showing a small part of the projects from that big application gives us a peek into the wrong dependencies:

Project dependency graph for hotels

The red lines telling us what dependencies we do not want. Maybe it is more clear if we group the domain projects and the services projects together like this:

Domain projects depend on services projects

…Dependencies from our domain classes to our services, ouch! Not what we want! We need to create interfaces for the LocationsRepository and SettingsRepository and put those interfaces in the locations-domain and settings-domain- projects. After that, remove the dependencies (from Hotels and the Dal.Hotels projects) onto the service projects.

Basically it means that domain-code like this:

public void GetHotels()
{
Setting setting = SettingRepository.Get(SettingName.MaxHotels)
...
}

is to be changed to:

public void GetHotels()
{
Setting setting = ISettingRepository.Get(SettingName.MaxHotels)
...
}

Where the interface ISettingRepository is in the Settings domain project instead of the (database dependend) services.settings project.

Build domain classes by using interfaces of service classes

Build domain classes against the interfaces of service classes instead of the concrete (underlying) services they depend on. The benefit of that will be:


  • Gets rid of unncessary dependencies
  • Gets rid of leaking database enabled code into your domain projects
  • In .Net: will make your code compile faster

This will also need us to buildup a good infrastructure project that will tie the projects together at program startup, initializing all Repository-interfaces with the right Repository-classes (not the mocked ones)… but that is a different concern.

Enjoyed this read? Let me know your thoughts!


Comments

2 responses to “Project references in DDD”

  1. Hi Melle,

    Thanks for the mention. I’ve updated that project and put it up on GitHub at http://github.com/jamiepenney/VS-Dependency-Viewer I’m glad someone has a use for these little projects I create. I might do a little more work to make it easier to do the colouring you’ve done in your blog post – did you add this manually to the .dot file or did you do some analysis in the project loading code?

    Cheers, Jamie

  2. Hi Jamie,

    I’ve done the colour and styling manually; I’ve changed the styling to “component” instead of “ellipse” and the colouring was also changed for the different kind of projects. Although, now that you mention it, it would be possible to do extra analysis in the projectloading code by determining the colour based on the references the project has. In our case, all the services projects have a relation to the NHibernate.dll so those projects would be the repository/services while the others will be the Plain domain projects.

    Also, within GVEDIT I have changed a few settings before generating the picture like the “ratio” flag; that way the layout of the projects in the picture is not too flat. Thanks for putting the project on github!

    Cheers, Melle