C# Design Patterns – Recreating Complex Aggregates from a Persistence Source

aggregatecdesign-patternsdomain-driven-designobject-oriented-design

I'm building a web application with C#, and I have an aggregate root which has several entities and value objects. Then I have a repository object which persists the aggregate to the database (I'm using ADO.NET as my infrastructure persistence layer).

The aggregate also has several events attached to its methods, so that other actions can be taken outside the aggregate (for example, the method OpenRequisition of a Customer aggregate fires the event RequisitionCreatedEvent, and a handler then queues an action to update statistics regarding the customer.

This is a simplified sample.

class Customer {
    private Guid _id;
    private string _shortName;
    private string _legalName;
    private TaxCode _taxCode;
    private ContactInfo _primaryContact;
    private List<Requisitions> _requisitions; //Requisition is an entity
    private IDomainEvents _events;
    // and so many other fields

    public Requisition OpenRequisition(RequisitionDefinition definition, User requestedBy) 
    {
        Requisition req = ... // create the new requisition somehow
        _requisitions.Add(req);
        _events.Invoke(new RequisitionCreatedEvent(this, req));

        return req;
    }

    // and so on
}

The problem I'm facing is not with how to persist, but how to reconstruct the aggregate object from the database. Many of the customer's fields have setters, such as the ShortName or LegalName, or even TaxCode. Others does not, such as the _requisitions field. I have no direct way of reconstructing existing requisitions. If I expose _requisitions somehow (as an List property), then I could simple do something like this in my repository:

var requisitions = ... // get requisitions for this customer
var customer = new Customer(id);
customer.Requisitions.AddRange(requisitions);

But then elsewhere one could do:

customer.Requisitions.Add(new Requisition());

bypassing the logic and validations set in OpenRequisition method. On the other hand, if I invoke OpenRequisition method from my repository, then the event handler will get called each time, and it shouldn't, because I'm reconstructing the object from the database, not actually opening a new requisition.

What I have so far, is to create a constructor and then pass all these parameters in there, something like this:

public Customer(IDomainEvents events, Guid id, IEnumerable<Requisition> requisitions, ... and so on) 
{
    ... // perform validations
    _events = events;
    _id = id;
    _requisitions = new List<Requisition>(requisitions);
    ... // and so on
}

However, this aggregate has several other children nodes, and so the constructor is growing and growing, and it doesn't feel right. At one point I tried to create factory class, but I still need the large constructor, or something like having internal setters even for _events and _requisitions, and it still doesn't seem right.

Hence, my question is: how to reconstruct complex aggregate roots, how to pass all the parameters the aggregate needs to keep functioning without having the object to perform already made work (such as firing the event handler). Otherwise, what options would you consider on scenarios such as this?

Best Answer

This is a common issue when implementing aggregates. It usually gives rise to separating aggregate state onto a another object. That object can be a pure data bucket with public getters/setters for convenience. Outside callers could be aware of the aggregate's state class, but it remains private to the aggregate (as a private field, for instance). The repository could directly load aggregate's state, which can be passed as a single object to the aggregate's constructor.

You would have:

public CustomerState
{
    public Guid Id { get; set; }
    public string ShortName { get; set; }
    public string LegalName { get; set; }
    public TaxCode TaxCode { get; set; }
    public ContactInfo PrimaryContact { get; set; }
    public List<Requisitions> Requisitions { get; set; }
}

public Customer
{
    private readonly CustomerState _state;
    private readonly IDomainEvents _events;

    public Customer(CustomerState state, IDomainEvents events) 
    {
        _state = state;
        _events = events;
    }
}

...

public Requisition OpenRequisition(RequisitionDefinition definition, User requestedBy) 
{
    Requisition req = ... // create the new requisition somehow
    _state.Requisitions.Add(req);
    _events.Invoke(new RequisitionCreatedEvent(this, req));

    return req;
}

Notice that I placed IDomainEvents in the aggregate instead of the state class, because it has some behavior (likely dispatching). For your state object, you only want pure data.

In a very surface way, this organizationally resembles an Anemic Domain Model because the state is separated, and the aggregate essentially just contains methods, similar to a Facade pattern. But the difference being that an anemic domain allows the user to directly manipulate state and run a Transaction Script on their manipulations. But with this, user is not allowed to directly manipulate state... we retain control of validated state changes through domain methods, but add easier loading (and saving).

Now, separating the state in this way does present it's own challenges. Usually naming confusion is one initially. You probably don't want to name your data table CustomerState (and it's probably already named Customer). But naming the table Customer will result in confusion when the aggregate of the same name is structurally dissimilar. If you're up for some reorganization, you might consider naming your aggregate Sales or Ordering or the like (based on what area it deals with) and keep the customer's state named as Customer. You might find that leads to better organizational clarity for your use cases anyway.

Related Topic