Возможно, вам не хватает понятия SeminarSchedule .Сначала давайте зададим пару вопросов, которые повлияют на модель
Если у вас есть семинар, разделен ли он на какую-то лекцию, презентацию и т. Д., Или это семинар по тому же принципу?только для разных людей в разное время?
Можете ли вы сначала подписать человека на семинар, а затем решить, во сколько этот человек будет присутствовать?
Я приведу пример в псевдокоде.
ПРИМЕЧАНИЕ: я пропущу приемы пищи, так как вопрос о расписании, но они вписываются в эту модель.Я также расскажу о логике, связанной с ними, просто пропустите их в коде
Сначала давайте скажем, каковы наши требования.
Это семинар с одной стороны(лекция, тренировка все что угодно) разделить на временные интервалы.Одна и та же лекция будет прочитана для разных людей, начиная с разных времен.
Участники могут подписаться, не будучи запланированными на определенное время.
Когда участник подписывается, нам нужно приготовить ему едуна основе предпочтений (например, он / она может быть вегетарианцем или веганом).
Планирование будет выполняться в определенное время от пользователей системы.Они будут принимать информацию участников при выполнении графика.Например, мы можем захотеть, чтобы люди одного возраста были в одном временном интервале или по некоторым другим критериям.
Вот код:
class Seminar {
UUID ID;
// other info for seminar like description, name etc.
}
class Participant {
UUID ID;
UUID SeminarID;
// other data for participant, name, age, meal preferences etc.
}
class TimeSlot {
Time StartTime;
TimeInterval Duration;
ReadonlyCollection<UUID> ParticipantIDs;
void AddParticipant(UUID participantID) { }
}
class SeminarSchedule {
UUID SeminarID;
Date Date;
Time StartTime;
TimeInterval Duration;
ReadOnlyCollection<TimeSlot> TimeSlots;
void ChangeDate(Date newDate) { }
void ChangeStartTime(Time startTime) { }
void ChangeDuration(TimeInterval duration) { }
void ScheduleParticipant(Participant p, Time timeSlotStartTime) { }
void RemoveParticipantFromSchedule(Participant p) { }
void RescheduleParticipant(Participant p, Time newTimeSlotStartTime) { }
}
Здесь мы имеем3 агрегата: Seminar
, Participant
и SeminarSchedule
.
Если вам нужно изменить какую-либо информацию, относящуюся к Seminar
или Participant
, вы ориентируетесь только на эти агрегаты.
С другой стороны, если вам нужно что-то сделать с расписанием, агрегат SeminarSchedule
(являющийся границей транзакций для планирования) будет обрабатывать эту команду, обеспечивая согласованность.Вы также можете применить параллельный контроль над расписанием.Возможно, вы не захотите, чтобы несколько человек меняли расписание одновременно.Например, одно изменение StartTime
, а другое изменение Duration
или два пользователя добавляют одного и того же участника в расписание.Вы можете использовать Оптимистическая автономная блокировка в совокупности SeminarSchedule
Например, изменение Duration
из StartTime
для SeminarSchedule
повлияет на все TimeSlots
.
Если вы удалите Participant
из Seminar
, вам придется удалить его и из расписания.Это может быть реализовано с возможной последовательностью и обработкой события ParticipantRemoved
, или вы можете использовать Saga .
Еще одна вещь, которую мы должны принять во внимание при моделировании агрегатов, - это также логика подписина семинар работает.
Предположим, что участник должен подписаться на семинар, прежде чем планировать их.Возможно планирование будет выполнено позже, определяя группы людей по некоторым критериям.Вышеуказанная модель будет работать нормально.Это позволит пользователям подписать Participant
на Seminar
.Позже, когда расписание назначено, другие пользователи смогут составить расписание, посмотрев, какие участники подписали.
Давайте рассмотрим противоположный случай и скажем, что незапланированные участники не могут присутствовать на семинаре.
В этом случае мы можем добавить сущность Participant
к совокупности SeminarSchedule
, но это приведет к загрузке всей этой совокупности, даже если вам потребуется изменить некоторую информацию для одного участника.Это не очень практично.
Поэтому, чтобы сохранить хорошее разделение, которое у нас есть, мы можем использовать Saga или ProcessManager для обеспечения согласованности.Мы также можем добавить концепцию ReservedPlace
в совокупности SeminarSchedule
.Таким образом, вы можете зарезервировать место, затем добавить участника в расписание и затем удалить ReservedPlace
, назначив участника временному интервалу.Поскольку это сложный процесс, охватывающий несколько агрегатов, Saga
определенно на месте.
Другой способ сделать это - определить концепцию SeminarSignRequest
, которую может создать человек.Позже этот запрос может быть одобрен, если есть питание и / или место.Возможно, мы достигли максимального числа людей или не имеем достаточного количества пищи и т. Д. Это, вероятно, также процесс, поэтому вам также может потребоваться Saga
здесь.
Для получения дополнительной информации см. эту статью и это видео .