Question

I've designed my classes using CRC cards and I have a lovely set of objects that contain domain/business logic AND data (properties). Some of the classes require saving to and reading from a database.

My repository should exist in a separate project to my domain objects, but needs to reference them in order to create them.

However, the domain objects/entities need to be able to reference the repository.

I could put the objects in the repository, but as they contain domain functionality, that doesn't feel right at all.

I could put the objects that require persistence in a common shared project, but again it feels wrong to single them out.

Where should I put them? I cant help feeling I'm missing something obvious.

Was it helpful?

Solution

Domain objects/entities should not use repositories. Its domain/applications services should use repositories. And that's done very simple - you should define repository interfaces in your Domain Model assembly and use them in domain/application services.

Domain library should contain

  • Domain Model
  • Repository Interfaces
  • Domain Services (use only interfaces of repositories)

This library does not reference other libraries - it sits at the core of your system.

Persistence library should contain implementation of repositories specific to your data provider. E.g. it can use Entity Framework. This library should reference your domain library. Thus it will know about interfaces it should implement and about entities it should work with.

OTHER TIPS

However, the domain objects/entities need to be able to reference the repository.

Do they? Or do they need to reference the interface of the repository? Then the repository itself is just an implementation of that interface, a low-level detail not needed by the domain logic code.

The way I normally structure a repository pattern in my projects is:

  • Domain Core Project (business models, core business logic, interfaces for dependencies)
  • Dependency Projects (references Domain Core Project, implements interfaces)
  • Application Projects (references Domain Core Project, references Dependency Projects either directly, or through configuration, or through an intermediary project which handles dependency injection)

As an example, suppose I'm using a Service Locator for my dependency injection (which I very often do). Then the business models only need to reference the Service Locator object (which itself is supplied by a factory and can be injected). So internal to a business model I might have something like this:

public class SomeBusinessModel
{
    private ISomeDependency SomeProperty
    {
        get
        {
            return DIFactory.Current.Resolve<ISomeDependency>();
        }
    }
}

The DIFactory has a static property called Current which is basically a factory method returning a dependency injection resolver, and its interface has a method called Resolve which takes a type and returns an instance.

So in this case...

  • SomeBusinessModel is in the Domain Core Project
  • ISomeDependency is in the Domain Core Project
  • IDIContainer (the return type for Current) is in the Domain Core Project
  • DIFactory is in the Domain Core Project, and is initialized (it has an Initialize method that sets the current injection container) by the Application Project for a specific dependency injection container
  • SomeDependency (the actual instance type being returned by the resolver) is in a Dependency Project

In this setup, the business models know that there needs to be a repository, and require that one be supplied, but they don't have a hard dependency on them. The application supplies the actual implementations for those repositories, either directly by providing an instance or indirectly by configuring a dependency injection container to provide an instance.

All actual dependencies point inward from the implementation details (applications and dependencies) to the core business logic. Never outward.

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