I recently started reading Evan's book about DDD, and I decided to try and apply some of the principles from that book on a bounded context of a project I've been working on.
The context of interest deals with appointment and appointment scheduling. I will present some of the business requirements, as well as the current model.
We have Employees, Appointments and Rooms. An appointment can have at most 1 employee per role, for example 1 counselor, 1 doctor. These employees all start and finish their part of the appointment at a different time. For example, a counselor can be present from x1 till y1, and a doctor can be present from x2 till y2 (these can overlap, or be disjointed). The appointment is considered to start at the earliest x, and end at the latest y. An appointment can also have only 1 patient. An appointment must take place in a room. Employees cannot have overlapping appointments (regarding to their own start and finish times). An appointment cannot take place in a room if that room is occupied for a different appointment.
This is the model I came up with:
In addition to the previous invariants, these business rules must be upheld: A patient can have only 1 scheduled appointment at a given time (assume there is a status attribute in Appointment).
The model should support the following use-cases:
- Scheduling an appointment.
- Updating an appointment schedule's start/end time
- Assigning a different employee to an appointment
- Adding/removing appointment schedules from an appointment
I have trouble defining the aggregates, their roots and boundaries. From the given constraints, I think it is pretty obvious that the DailySchedule aggregate needs to encompass the Availability and AppointmentSchedule value objects. However, Appointment also needs to encompass AppointmentSchedule in order to maintain the invariant that there should be only 1 employee role per appointment. Furthermore, Room and Patient both need to encompass Appointment in order to maintain their invariants.
Supposing that Patient's invariant can be modeled as a business rule/policy object, that still leaves DailySchedule and Appointment sharing a reference to a value object, without going through its aggregate root.
It seems to me that this model does not allow for clearly defined aggregate boundaries. I was considering exposing SERVICES for each of the use-cases, that would span between the aggregate boundaries and maintaining the invariants from there. I am interested to know if there is any other, possibly more elegant/simple solution to this problem.
AppointmentSchedule
aggregate containing all appointment invariants could do the job. IsAvailability
an external factor or can it be entirely derived from usage of a specific room in Appointments?