I'm not even sure how to ask this, but here goes:
Let's say I have a Web application that incorporates Teachers, Courses and Students in such a way that I can do things like this (pseudocode):
teacherQuery = new TeacherQuery;
teacher = teacherQuery.getById(teacherId); // teacher is a Teacher object
foreach (course in teacher.getCourses()) {
course.printName();
foreach (student in course.getStudents()) {
student.printName();
}
}
studentQuery = new StudentQuery;
students = studentQuery.getAllForCourse(courseId); // students is a
collection of Student objects
foreach (student in students) {
foreach (teacher in student.getTeachers()) {
// getTeachers() returns of a Collection of unique Teachers for all the
// Courses for the Student.
teacher.printName();
}
}
There are a lot of ways to handle this, but my question is about change.
Let's say that once we have the Teacher/Course/Student application working, the client says they want to let the students form study groups, such that each Student can have multiple StudyGroups, and each StudyGroup can have multiple Students, but each StudyGroup belongs to only one Course.
I've been chewing this over, and it feels like inevitably adding StudyGroups (or the equivalent) means making changes to a whole bunch of classes. Apart from creating StudyGroup and StudyGroupQuery, you're going to have to add getStudyGroups() to Student and Course and maybe even Teacher, and you're going to have to add getAllForStudyGroup() to StudentQuery and maybe some other stuff.
And, more to the point, every time you add a new table, you're going to have to add new methods to every class that has a relation to that table.
One approach would be to paramaterize it, so that instead of teacher.getStudyGroups() you have:
genericQuery.get('StudyGroups').by('Teacher').with('id',teacher.getId()).through('Courses').unique()
...or something along those lines, but you're not going to want to copy and paste that every place you need to list the StudyGroups overseen by a given Teacher (are you?) so that means you're still going to want to create getStudyGroupsByTeacher() someplace, which means that you're going to have to edit that "someplace" when it's time to add getTextbooksByTeacher().
I'm tempted to conclude that sometimes there are changes that just tell the Open/Closed principle to go to hell, and that's all there is to it. Am I missing something?
(A couple obligatory notes: The code above is just an example, and I'm not literally looking for a way to incorporate study groups into an existing course application. I am interested in hearing about architecture, but in the context of "What architecture best allows for incorporating new types of entities/tables?" not "What is the best architecture for a Web application?")