Reputation: 57
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:
ExamBooking
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 ExamBooking
s (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 ExamBooking
s (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
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