In my doctor's appointment booking system, I identified the following entities:
- Doctor
- Patient
- Appointment
I also identified an aggregate, which is Doctor (aggregate root) and Appointment. It's an aggregate, as it has to hold an invariant of making sure that appointments assigned to them do not overlap. In pseudocode the model looks as follows:
- class Patient(id, name, lastname)
- class Doctor(id, name, lastname, upcomingAppointments: List)
- class Appointment(id, patient_id, start_date_time, duration)
Now, the requirement to my system is:
- schedule an appointment
- retrieve all appointments for the given patient
Question 1: scheduling an appointment
I see 2 ways to model scheduling an appointment:
a) Have a Doctor#schedule method, that would return a copy (I strive for immutability) of the Doctor with a new valid (non-operlapping) appointment. Then I'd have a DoctorRepository.update method, that would store this aggregate. Pseudocode:
transaction boundary start;
doctor = DoctorRepository.get(doctorId);
doctorWithNewAppointment = doctor.schedule;
doctorRepository.update(doctorWithNewAppointment);
transaction boundary end;
but in this way I'd have to update the whole aggregate and also the other appointments, that were not updated. This would be bad performance-wise.
b) Have a Doctor#schedule method, that would return just a new valid (non-operlapping) appointment (I strive for immutability in my system). Then I'd have AppointmentRepository#insert to insert this new appointment. Psuedocode:
transaction boundary start;
doctor = DoctorRepository.get(doctorId);
newAppointment = doctor.schedule;
appointmentRepository.insert(newAppointment);
transaction boundary end;
Which one should I choose?
Question 2: retrieving all appointments for the given patient
I have a problem, because I've read, that entities, that are referenced from an aggregate cannot be referenced from the outside of the aggregate by other entities. That means (if I understand it correctly), that I cannot retrieve appointments outside of the Doctor aggregate. My requirement says I need to retrieve all appointments for a given patient. Now I have 2 options:
a) Have a findAllAppointments(PatientId patientId) method inside DoctorRepository, but is it OK to retrieve entities, that belong to different instances of the same aggregate?
b) Have a separate AppointmentRepository with findAll(PatientId patientId) method, but given I have an aggregate, is it fine to have a separate repository for an entity, that is a part of an aggregate?
Which one should I choose?