Search code examples
domain-driven-design

How to choose the proper bounds for an Aggregate in DDD?


I'm trying to follow the DDD (Domain-Driven Design) approach in my project. My domain is a barbershop and the use case that I want to implement is - book an appointment.

The problem that I have is how to correctly organize boundaries around my aggregate that should help to handle this use cases (book an appointment).

Let's say I have a barber. Barber has working days. Working day has working hours (e.g. 09:00 - 20:00), breaks, and other booked appointments.

Schematically it would look like this

Barber
 - WorkingDay
   - 09:00-20:00 <- working hours
   - Breaks
     - 13:00-14:00
     - 18:00-19:00
   - Appointments
     - 09:00-10:00
     - 12:00-13:00
 - WorkingDay
   ...
 - WorkingDay
   ...

Rules to be considered:

  1. New appointment must not overlap existing breaks
  2. New appointment must not overlap existing appointments
  3. New appointment must be within working hours
  4. Working day must exist
  5. Working day must not be in the past

I have two ideas of how to implement this:


Create WorkingDay aggregate which will contain all related breaks and appointments.

Pros:

  • All rules can be satisfied within WorkingDay aggregate
  • Single WorkingDayRepository repository

Cons:

  • Possibly large aggregate*

Create WorkingDay, Break, Appointment aggregates and verify rules in domain services

Pros:

  • Small aggreages

Cons

  • Multiple repositories (e.g. WorkingDayRepository, BreakRepository, AppointmentRepository)
  • Business logic is split between aggregates/domain-services

What other option can be used? Or what approach to follow in my case?


Solution

  • You could model this by using the concept of a Schedule. Schedule is your worker's workdays (or calendar) with appointments. It could be a decent aggregate - schedule has to be always valid.

    Then you could have AddAppointment method on the Schedule which will check the invariants.

    If you need to track changes, I'd suggest using Domain Events that could be fired and then logged.

    To avoid concurrency problems with bookings, i.e. when 2 users are trying to book the same slot, you can:

    1. Organise the DB in the way that it will not be possible to double-book, ie in your bookings table you will have a unique constraint on <time slot id>, <barber id> and when the second user is trying to book (insert a booking into the table) they will fail with unique constraint violation. Not sure how your db is structured but hope you get the idea.
    2. use DB transactions. Both will try and update the row with time slot, only one should succeed.
    3. put booking requests for the same barber into a queue.