Search code examples
c#eventsarchitecturedomain-driven-designevent-sourcing

Event Sourcing Aggregate Root User


I'm new in event sourcing, and I started a new project to learn about it but I have a couple of questions about architecture.

My first question is about aggregate root. I have a UserAggregateRoot. Did this aggregate should contain properties that are typically recognizable to user entities?

I mean my Aggregate looks like that

public class UserAggregateRoot : AggregateRoot
{
    public Login Login { get; private set; }
    public Password Password { get; private set; }
    public Name Name { get; private set; }
    public DateTime BirthDate { get; private set; }
    public UserId UserId { get; private set; }
    public Status Status { get; private set; }

    private void Apply(UserCreatedEvent e)
    {
        Version = e.Version;
        Login = e.Login;
        Password = e.Password;
        Name = e.Name;
        BirthDate = e.BirthDate;
        Key = e.Key;
    }

    private void Apply(UserActivatedEvent e)
    {
        Version = e.Version++;
        Status = e.Status;
        Key = e.Key;
    }

    private void Apply(UserDeletedEvent e)
    {
        Version = e.Version++;
        Key = e.Key;
    }

    private void Apply(UserLogedEvent e)
    {
        Version = e.Version++;
        Key = e.Key;
    }

    private void Apply(UserUpdatedEvent e)
    {
        Version = e.Version++;
        Login = e.Login;
        Password = e.Password;
        Name = e.Name;    
        Key = e.Key;
     }
} 

Or maybe UserAggregateRoot should store user entity looks likes that

public class UserAggregateRoot : AggregateRoot
{
    public User User { get; private set; }

    private void Apply(UserCreatedEvent e)
    {
        User = e.User;
        Key = e.User.Key;
    }

    private void Apply(UserActivatedEvent e)
    {
        Version = e.Version++;
        User = e.User;
        Key = e.User.Key;
    }

    private void Apply(UserDeletedEvent e)
    {
        Version = e.Version++;
        Key = e.User.Key;
        User = e.User;
    }

    private void Apply(UserLogedEvent e)
    {
        Version = e.Version++;
        Key = e.User.Key;
    }

    private void Apply(UserUpdatedEvent e)
    {
        Version = e.Version++;
        User = e.User;
        Key = e.User.Key;
    }
}

Second question is if UserAggregateRoot stores some orders, should I store the order entity list inside this UserAggregateRoot?

What if orders are AggregateRoot something like OrderAggregateRoot? Should I store AggregateKey inside my UserAggregateRoot to point this OrderAggregateRoot?

Third question is should Aggregate root have business logic inside or should business logic be inside entity passed to this Aggregate and inside value objects?


Solution

    1. Either way is fine, as I see it
    2. Hard to answer without more domain knowledge. Most likely it'd be an OrderAggregateRoot with a property that contains the AggregateKey of the UserAggregateRoot. OrderAggregateRoot might even be an entirely different bounded context. If you want more details on defining aggregate roots I suggest looking for defining transactional boundaries.
    3. Depends on what you mean by business logic and its specific scope, but Entities and Value Objects can have behaviors of their own.