2

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 Students that are enrolled within its instance. At the same time, you'd like to know what Classes 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?

  • 3
    Why 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 Dec 15 '15 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 Dec 15 '15 at 10:45
7

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.

1

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.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.