But hang on a second. This student data will include references to course objects and section objects, won't it? Doesn't a student have to know what her courses and sections are? So isn't there something circular going on here? Are we storing sections in course objects, or in student objects? In fact, where are we storing the references to course objects? If one student takes more than one course, are we going to have a different student object for each course?
A third basic principle of software design is the following:
3. We should only have one copy of the data
The reason for this is simple: let's say we have more than one object for a student. Now let's say that the student wishes to change a course. Now, in order for our software to do this successfully, we would have to find each object for that particular student and change the information in each one. Not only is this wasteful, but what happens if we make a mistake and change the information in only some of the objects? Then our data for that student won't even be consistent, and if the student asks to see her data, what she sees will depend on which object we use to get the information.
This third principle guides a lot of our design. Since we want to have only one object for each student, we can't refer to a different student object in each section of each course that the student takes. But what we can do is to create a single student object and put a copy of the reference to this object under each section in which the student is enrolled, for example.
Now, since our specifications also require us to be able to display all the information about a student given the name of the student, it would be nice if we had some place, where all the references to the student objects were together. What we'll do to accomodate this is to make another class, called StudentList, for example, which has an array into which we'll put the references to all the student objects that we create.
We'll also be storing a copy of the reference to a Student object in each section that the student enrolls in. Doesn't this violate principle number 3? Aren't we storing data (the reference to the Student object) in more than one place? The answer is that the reference to an object is not data; only the values that we store in String objects and primitive data types are data. Clearly, if we change the address of a student for example, then every object that has a reference to that Student object will now refer to the updated address: we still only have one copy of the information.
-one student in university: sections - student many one relation - deal with many-one relation by putting reference to one in many places (each section) - many students in university: sections - students many-many - deal with many-many by making a container to hold the many references. In this case, a section will have to refer to many students, so we can make an array of Students in each section, for example. - in fact, one section having many students is a one -many relation: use container - many-many relation is dealt with in same way: each section will be one-many, so each section will have a container for references to students.
In the same way that we want to have a container (array in our case) for all the students, we want to have a container for all the courses. Where? Make a class CourseList. THis way, we can search through all the courses easily.
Another good idea is to make a separate class for data/methods that you think are going to change in the future. For example, we're going to develop our student registration system to use the standard command line input. But what if we suspect or even plan to upgrade to a GUI at some point? What design decisions should we make now in order to make this easy in the future? The major decision we should make is to put all the I/O stuff in a single class. In that way, when we upgrade all we have to do is to replace that one class, rather than go through all the classes looking for all the I/O statements that we may have written.
We've been distributing the 'knowing responsibilities' to the classes. Let's take a moment to summarize what we've decided so far. Notice that instead of 'array' I've used a more general word: 'set'. This is because we would like our design to be general enough that we can implement it in different ways. We will implement these 'sets' using arrays, but only because that's one of the few data structures that we currently know (and because we need more practice in using arrays....) The upshot is that when we know more advanced data structures, we'll be able to use the same design to implement the system with the more advanced data structure.
Course class | |
DATA (KNOWING) | METHODS (DOING) |
course name | |
set of sections for this course | |
number of sections for this course |
CourseList class | |
DATA (KNOWING) | METHODS (DOING) |
set of courses offered by university | |
number of courses offered by university |
Section class | |
DATA (KNOWING) | METHODS (DOING) |
set of students in section | |
number of students in section | |
instructor name for section | |
lecture room | |
lecture time |
Student class | |
DATA (KNOWING) | METHODS (DOING) |
name | |
st num. | |
dob | |
fees owing | |
address | |
set of courses | |
number of courses | |
set of sections | |
StudentList class | |
DATA (KNOWING) | METHODS (DOING) |
set of students enrolled in university | |
number of students enrolled in university |
Input/Output class | |
DATA (KNOWING) | METHODS (DOING) |
stuff associated with file that we'll write to / read from | |