How would one go about designing classes for a system in which two components depend on each other?
For a more concrete example, consider this scenario, you're designing a piece of software to manage students, teachers and classes in an educational facility. For convenience purposes, you'd like your Class
object to be able to query for the Student
s that are enrolled within its instance. At the same time, you'd like to know what Class
es a Student
is enrolled in.
A simple design may have include a container that holds instances of type Class
in the Student
object, and a container that holds instances of Student
in the Class
object. It does the job but it introduces a cyclic dependency between both classes. Usually, this is looked down upon [citation needed], but it sounds like a valid design where this could be beneficial.
Is there a reason why it would be a bad idea to do so? And how could this situation be rectified without introducing significant performance overhead?
-
3Why not use an enrollment collection mapping classes and students? It can have method that given a class it returns a collection of students in that class and a method given a student it returns a collection of classes the student is taking.Bent– Bent2015年12月15日 10:43:30 +00:00Commented Dec 15, 2015 at 10:43
-
@Bent That actually is a great idea that I somehow overlooked. Could you please rewrite your comment as an answer? This is exactly what I was looking for!Khaled Nassar– Khaled Nassar2015年12月15日 10:45:08 +00:00Commented Dec 15, 2015 at 10:45
2 Answers 2
Looking at the relationsship between classes and students it is not as simple as classes have a list of the students participating and students have a list of classes they are participating in.
You might have to model students that are no longer participating in a class, classes that have been cancelled, students on waiting lists etc.
The best solution would be a collection of enrollments. Each enrollment might be 'active', 'dropped out', 'class cancelled', 'waiting list' etc. You can add new enrollment types without ever changing the classes or student classes.
The enrollment collection then have methods to get a collection of either classes or students.
This could be something like enroll.Active(chem101)
to get the active students for chemistry 101 or enroll.DroppedOut(bent)
to get all the classes Bent has dropped out of due to spending too much time on stackexchange.
The primary reason why that might be bad idea, is to keep the two-way-relationship in sync. When you add class to a student, you also have to add student to a class. Another, minor, problem is that persistence of relationship will be only one side. So you would have to convert it if it was opposite in the model.
There are two steps to resolve this issue. First is to make the collections on Student and Class read-only. This is generally simple. Then, introduce a 3rd concept. It can be as simple as EnrollmentService, that allows to pair Students to Classes, and internally ensures the relationship is properly maintained. Or it can be it's own entity like Bent suggests.
Explore related questions
See similar questions with these tags.