navix1337
navix1337

Reputation: 57

DDD - Aggregate context, consistency

I am trying to design a project management system students. Basically there is a given period of time in which a project has to be finished by students. Generally, students need to work on the project every day of the week which will be verified in some way.

However, students are allowed to take a limited amount of vacation times and register exams that free them from work on certain days. There are some rules as to how you can choose your vacation times. Especially it is also dependent on the exams you have registered the same day.

The whole application is a web app based on Spring Boot MVC and adheres to DDD principles.

So far I modeled the system like this:

The core/domain consists of the following classes: Student, Exam, Vacation and ExamBooking. Exams are globally added to the system by tutors or students and then remain in the system. Vacations and ExamBookings belong to a specific student and describe the "free of work" time periods:

class Student {
  private String name;
  private int vacationTimeLeft;
  private List<ExamBooking> examBookings;
  private List<Vacation> vacationBookings;
  
  public void addVacation(...) { ... } // performs logic and adds vacation to vacationBookings
  public void addExam(...) { ... } // performs logic and adds exam booking to examBookings

  // ctors, getters, setters, ...
}
class Exam {
  private int examId; // external exam id referencing the exam in the university's own system
  private String moduleName;
  private LocalDate examDate;

  // ctors, getters, setters, ...
}
class Vacation {
  private TimeRange bookedTime;
  private LocalDate day;
  
  // ctors, getters, setters, ...
}
class ExamBooking {
  private Exam exam; // general exam info (module, professor, ...)
  private TimeRange bookedTime;

  // ctors, getters, setters, ...
}

My problem is that a Student can interact in two contexts with exams:

  1. Adding/Removing an ExamBooking
  2. Adding an Exam (globally)

In the first case, the Student class is the Aggregate Root, whereas in the second case the Exam is the object with which the outer layers interact. (in this case a StudentService invoked from the StudentController).

I have two main concerns:

Aggregate consistency: I know that one should not reference an Aggregate Root inside of another one directly, i.e. it would be better to reference Exams by ID. But at the same time the logic in the Student class depends on actual ExamBookings (and thus also on Exam) objects. However, an ExamBooking is only used in the context of booking vacation/exams, not for registering exams globally.

Persistence/Data layer: When persisting/saving a Student, we need to also modify the corresponding ExamBookings table in the database. When loading a Student from the database, we need to build the actual domain object from multiple tables, so again needing to reference another Aggregate.

Would it make sense to introduce redundancy, i.e. embed/copy the data from the global Exam into ExamBookings (so there is no need to reference Exam from inside an ExamBooking), to underline the fact that we have two bounded contexts here?

Upvotes: 0

Views: 232

Answers (1)

VoiceOfUnreason
VoiceOfUnreason

Reputation: 57194

Would it make sense to introduce redundancy, i.e. embed/copy the data from the global Exam into ExamBookings (so there is no need to reference Exam from inside an ExamBooking), to underline the fact that we have two bounded contexts here?

It might; there are cases where it makes sense for autonomous components to cache a copy of information that is under the authority of some other component. See Immutability Changes Everything (Pat Helland, 2012)

That said... you may want to reconsider your aggregate design.

For example: an ExamBooking appears to describe a relationship between a Student, and Exam, and some flavor of Clock/Calendar/Schedule. Any of those four things could reasonably be "the" aggregate, depending on the nature of the data relationships.

The important place to focus (warning: opinion ahead) is the way information changes over time and how quickly you need information to propagate through your system.

Upvotes: 2

Related Questions