Distrubuted domain driven design modeling

98 Views Asked by At

I am working on an events ticketing system and I am trying to use DDD. However, I am unsure about how to model some of my aggregates.

I have the main Event aggregate:

public class Event : Entity<Guid>, IAggregateRoot
{
    public string Name { get; private set; }
    public Organizer Organizer { get; private set; }
    public Venue Venue { get; private set; }
    public DateTime StartsAt { get; private set; }
    public short MinAge { get; private set; }
    public bool IsAvailable { get; private set; }
    public EventType Type { get; private set; }
    //constructor and mehtods
}

and also have the Venue and Organizer Aggregates:

public class Venue : Entity<Guid>, IAggregateRoot
    {
        public string Street { get; }
        public Venue(Guid id, string street) : base(id)
        {
            Street = street;
        }
    }


    public class Organizer : Entity<Guid>, IAggregateRoot
    {
        public Organizer(Guid id) : base(id)
        {
        }
    }

My questions are:

  • I have different services that handle creation and other operations for the Venues and Organizers. The Events service is consuming kafka messages from the other two services and persists the venues and organizers in its own database. I would like to mention that the Venues and Organizers services have a lot more information about their respective entities than the Events service, so it is not a 100% data duplication. Is this the right way to share data between different services?

  • In the events service, should the Organizer and Venue be considered an aggregate or an entity? Neither of those is accessed on itss own in the context of the Event service.

  • How should I handle persisting and retrieving entities from the database?

2

There are 2 best solutions below

0
On

An Entity is something that has an own entity, an unique identifier, that has significance. You use an aggregate when you have entities (and also value objects) with a strong dependency and has sense manage all of them like a single object. In this form, outside you work with some entity (the aggregate root) that manage all the aggregates entities.

With an example is easier to understand. Suppose you have Invoice entity and InvoiceLine entity. Both of them are important, has a unique identifier... and you may work with them as entities. You have a table in the database for invoices and for the lines. Working with the entities as is, you must control some things like, for example, the total of the invoice. When in any place you change the price of a line, you need have near the invoice, to update the total. It's a very simple example but in more complex scenaries, this kind of things ends with wrong data because in some place, you forget update some related data.

So, it's interesting have and aggregate root that contains this two aggregates and all about them are encapsulated in the root aggregate. You update line price through the aggregate root and root update the total of the invoice. Each entity have a reference to the root.

Usually, the aggregate root has a repository to manage the data of all their aggregates. Entity Framework differ a bit in this point, having a repository per entity.

0
On

It's a bit late but worth saying.

Is this the right way to share data between different services?

I think the way of sharing data wouldn't be an issue here. They share and update their data through a message broker, and it's all good. A better question would be why did you separate these bounded contexts in the first place? Creating bounded contexts costs a lot. So you must have a good reason behind creating BCs.

should the Organizer and Venue be considered an aggregate or an entity?

I think they should own their aggregates. Because the Event does not manage anything about them (all the invariants are defined in their original bounded contexts). They are just a copy of the original data.

How should I handle persisting and retrieving entities from the database?

I didn't quite catch your point, but I think the integration events are the triggers to modify the cloned data. So in the integration events handler, you should get the respective Venue/Organizer from its repository and apply the changes to them.