Team LiB
Previous Section Next Section

Revamping ScheduleOfClasses

Next, we'll retrofit the ScheduleOfClasses class that we developed in Chapter 14 with this same ability to "self-initialize" from an ASCII file. To do so, we'll start by indicating that we want ScheduleOfClasses to extend our previously defined CollectionWrapper class:

public class ScheduleOfClasses : CollectionWrapper {

By doing so, we'll inherit the InitializeObjects method of CollectionWrapper, which will give us all of the generic file manipulation capability that we need. Note that we can do so after the fact without disturbing any of the code that we've already written and tested for ScheduleOfClasses from Chapter 14!

ParseData Method

Next, we must provide a method body for the abstract ParseData method that we've inherited; since it's so similar to the ParseData methods of both the Faculty and CourseCatalog classes, we won't discuss it in detail, but simply present its code here.


  public override void ParseData(string line) {
    // We're going to parse tab-delimited records into
    // six attributes -- courseNo, sectionNo, dayOfWeek,
    // timeOfDay, room, and capacity.  We'll use courseNo to
    // look up the appropriate Course object, and will then
    // call the ScheduleSection() method to fabricate a
    // new Section object.

    // We'll use the Split method of the System.String class to split
    // the line we read from the file into substrings using tabs
    // as the delimiter.

    string[] strings = line.Split('\t');

    // Now assign the value of the substrings to the
    // appropriate local variables.

    string courseNo = strings[0];
    string sectionNumber = strings[1];
    string dayOfWeek = strings[2];
    string timeOfDay = strings[3];
    string room = strings[4];
    string capacityValue = strings[5];

    // We need to convert the sectionNumber and capacityValue
    // strings to ints.

    int sectionNo = Convert.ToInt32(sectionNumber);
    int capacity = Convert.ToInt32(capacityValue);

    // Look up the Course object in the Course Catalog.
    // Having made courseCatalog a  public static attribute
    // of the SRS class comes in handy!

    Course c = SRS.courseCatalog.FindCourse(courseNo);

    // Schedule the Section.

    Section s = c.ScheduleSection(sectionNo, dayOfWeek[0],
                               timeOfDay, room, capacity);
    string key = courseNo + " - " + s.SectionNo;
    AddSection(s);
  }

ParseData2 Method

There is one minor flaw in our application design. Unlike both the CourseCatalog and Faculty classes, which each required us to read both a primary and a secondary data file when initializing their respective Hashtables, we don't have a need at present to read and parse a secondary file when loading the ScheduleOfClasses Hashtable; all of the information that we need to process is contained within the SoC_SP2004.dat file, which is handled by the ParseData method. So, we really don't have a need for a ParseData2 method in the ScheduleOfClasses class. But, because we've chosen to extend the CollectionWrapper class, we're forced to implement such a method; otherwise, as we learned in Chapter 13, the ScheduleOfClasses class will be deemed abstract by the compiler, and we won't be able to instantiate it in the Main method of the SRS class.

To work around this dilemma, we'll "stub out" a ParseData2 method with an empty method body, as follows:

  public override void ParseData2(string line) { }

This makes the compiler happy and, since we have no intention of ever calling this method anyway, no serious harm is done. However, this breaks (or at least severely bends!) the spirit of the "is a" relationship of inheritance. Strictly speaking, if the ScheduleOfClasses class has no need for a ParseData2 method, then we shouldn't declare it to be a subclass of CollectionWrapper. But, if we didn't inherit the methods of CollectionWrapper, we'd then have to code an InitializeObjects method for the ScheduleOfClasses class from scratch to replace the one that it's no longer inheriting from CollectionWrapper, which would complicate our application in a different way by introducing code redundancy. So, doing what we've done by extending CollectionWrapper and "stubbing out" the ParseData2 method seems like a reasonable compromise.

FindSection Method

As we did for the CourseCatalog and Faculty classes, we provide ScheduleOfClasses with a convenience method for looking up a particular Section based upon the full section number, which is defined here as being a concatenation of course number and section number, separated by a hyphen; for example, "ART101 - 1":

  public Section FindSection(string fullSectionNo) {
    return (Section) sectionsOffered[fullSectionNo];
  }

Why No Test Scaffolding?

We can't provide a simple test scaffold Main method for the ScheduleOfClasses class as we did for CourseCatalog and Faculty; this is due to the fact that the ParseData method of the ScheduleOfClasses object will attempt to access the SRS.courseCatalog, which will not have been initialized.


Team LiB
Previous Section Next Section