CS102 Lab 1:
Packages, Protection and APIs

Assigned: Tuesday, January 19
Design (5 points) due in lab section: Monday, January 25
Demonstration (5 points) in lab section: Monday, February 1
Hard copy of code (10 points) due to the CS102 mailboxes: Tuesday, February 2

Goals:

By the end of this lab, you should...


Motivation:

In CS 101, you learned, among other things, how to create class definitions for objects that encapsulate data, and how to create hierarchies of classes in order to benefit from inheritance and polymorphism. However, in each case, you defined classes as part of complete working application. In other words, you worked "top down," knowing the final application specification and then implementing objects as needed.

Much of application development today rests upon the creation of general class libraries that can be used by multiple programmers to create a variety of applications. In fact, all of Java is built of libraries, called packages, and Java allows you to create your own packages as well. The real trick to developing a good package is to provide enough generality in the application programmer interface (API), so a lot of applications can benefit from it, but to resist the temptation to make it bulky by throwing in everything but the kitchen sink. A good package designer provides flexibility without bulk through package extensibility, which means designing a package so that classes can be easily extended (subclassed) by the package user when specialized behavior is needed. This kind of design, where the final application specification is unknown at the time components are being built, is sometimes called "bottom up" design. Another important aspect of package design is ensuring that each class, method, and instance variable has the proper protection, so that users of the package can do what they need to do without compromising consistency of the data or unnecessarily constraining the package implementor regarding future changes to the internal representation and implementation details.


Overview:

In this lab, you are to create a thoughtfully designed and carefully implemented package for the construction of surveys. Your package will contain a survey class, a variety of question classes whose instances can be added to a survey object, and a variety of option classes (such as "check off" and "fill in the blank") whose instances can be added to questions. Each question will have a unique label (a String) which which will be used by methods of the survey look up that particular question, for the purpose of calling various methods on it. Within each question, each option will also have a unique label (a String), which will be used by methods of the question look up that option and call methods on it (for example, to set and get the value of that option.) Lab 2, you will create the graphics to go along with the survey, but for now we'll ignore the problems of displaying the survey and getting user responses. Instead, you'll provide a toString method for each class so you can test and demonstrate your package's functionality.

We'd love to tell you exactly what what classes and methods should be in the API, how to arrange the class hierarchies, how to represent the data, and how to set the protections (it would certainly simplify grading!). However, the real learning in this lab is the design part, so saying too much would spoil your chance to do the design yourself. Therefore, the following specification is intentionally somewhat vague. Decisions regarding anything left unspecified are completely up to you.


Specification:

  1. Your package should provide a survey class whose purpose is, not surprisingly, to create surveys. It should provide a method for adding questions and should keep an ordered collection of these questions, based on the order they were added to the survey. Each question will contain a number of "options," which the end-user will eventually be able to check, fill in, etc. Each option will hold a current value (e.g., the end-user's response to that option), and the survey should provide methods for setting and getting the current value from the various question options. As described above, each question instance will have a unique label assigned by the creator of that survey. The label (which is just a String) is never seen by the end-user, but is intended to be used internally by the survey program to identify the question. Similarly, each option within a question will have a different label (also a String). For example, for a question with label "personal-data" might contain an options with a labels "first-name", "last-name", and "phone-number".

    The survey should provide methods for extracting survey data from the question options according to the labels. For example, one should be able to call a method on the survey object to find out the current value stored in the option labeled "first-name" in the question "personal-data". Similarly, one should be able to call methods of the survey to set the values of various options according to these labels. Therefore, the survey will need to keep some kind of mapping from question labels to questions, and each question will need a mapping from option labels to options, so the data can be accessed as needed.

    Finally, the survey and should keep track of the current question and provide methods for survey navigation:

    The result of the toString method of the survey class should be a concatenation (separated by blank lines "\n") of all the questions in the survey, in order.

  2. Your package should also provide a variety of question classes, arranged in an appropriate class hierarchy. At a minimum, each question must keep track of a String which is the text of the question, and a collection of one or more options (see below). Various types of questions may need to store other information as well. The following types of questions should be provided:

    Note: For some kinds of questions (like yes/no and short answer), the options (with their unique labels) will automatically created by the constructor. For the other types of questions, the user of the package will need to provide their own options and supply labels, so an addOption method should be provided in those questions to support this. If a question can only hold certain kinds of options, its addOption method(s) should restrict the parameter type(s) appropriately. For example, a multiple choice question would not permit a fill-in option to be added, since it is not selectable. (Hint: You may want to use Java interfaces in connection with this.)

    For questions in which exactly one check off option is allowed, such as alternative choice and yes/no, a method should be provided to associate a "skip to question label" with each alternative. The purpose of this is to allow the survey designer to specify which question should be asked next if this particular alternative is selected by the person taking the survey. (This automates support for surveys with directions like, "If you answered no, skip to question 37.") For yes/no questions, the labels could be provided as parameters to constructor. For alternative choice, the label can be provided as an extra parameter to the addOption method. The user is not required to provide a skip to question label for every option. If the skip to question label is null or invalid (doesn't exist in the survey), then if the end-user selects that option, the survey will simply go on to the next question in its ordered collection.

    The result of the toString method for question should include both the unique label and text of the question, as well as the result of calling toString on each of the question's options. Put a "/n" before each option's toString result, so the lines don't run together.

  3. To represent the components of the questions, your package should provide a variety of option classes in a sensible class hierarchy, including:

    Depending on the type of option, methods should be provided to set a "default" (initial) answer and/or to specify whether the option should be selected initially. Support should also be provided for making an option "uneditable" so that its values cannot be changed by the person taking the survey. However, since no one will be taking the survey and in Lab 1, for now is enough to have some methods for recording and finding out whether given option editable or not.

    The toString method for an option should include its string description, its unique label, and its current value. (The current value is the textual answer for a fill-in option, a String "selected" or "unselected" for a check off option, and the concatenation of both strings (with a space in between) for the combined option.)


Design:

Create a 1-page (front and back) paper design as follows. After carefully reading the above specification, design the API and class hierarchies for your package.

  1. On the front side of the page, draw a diagram of the hierarchies. By each class in the diagram, list the public methods provided by that class, with its parameters and return type. (If a class inherits a method, you need not list it again for that class, unless it overrides the method.)

    As you do the design, think carefully about each class hierarchy, trying to push shared functionality as high as possible in the hierarchy so it can be inherited. In order to capture the right relationships, you may define additional classes, abstract classes, and interfaces where they make sense. For flexibility in creating objects, you may want to provide multiple constructors with different parameter lists. However, don't go overboard. Try to keep things relatively simple.

  2. On the back side of the page, describe (in sentences or with a clear diagram) the internal data structures you plan to use to keep track of all the survey questions, options, labels, etc. and how they will be used. Before deciding on your internal representation, read the Java API documentation for the classes java.util.Vector and java.util.Hashtable, since they are likely to come in handy. We want you to practice reading this kind of APIs documentation so you can take advantage of things built into the language and save yourself from writing code for things that the language already provides. The Java API documentation can be found on the CS102 Java reference page.

Bring your design to your lab section on January 25. At that time, you should go over the design with a TA and ask the TA to sign and date the design. Note: By signing the design, the TA only signifies that he/she has discussed it with you and tried to give you useful feedback. The signature is not a guarantee that it is a good design, or even that it will work at all. Therefore, if things aren't working out when you do the implementation, you may want to reconsider the design. If you need to, you can change your design after January 25. There is no penalty for changing your design, but be sure to turn in both the original signed design and the new design with your completed lab.


Implementation:

Implement the classes of the survey package according to your design. Carefully choose the appropriate protection modifiers for each class, method, and instance variable according to the guidelines described in class.


Testing:

Write a simple application that imports your survey package and creates a survey for testing purposes. The survey should include at least one of each type of question and at least one of each type of option. Your application should exercise the various methods of the survey class to get and set the values of certain question options according to the labels. Finally, the program should have a loop that steps through the survey using reset(), getCurrentQuestion(), and advance(). Inside the loop, just print each question using its toString method. In your testing, be sure to include and test questions that skip to other questions based on the option selected.

You can use System.out.println instead of Terminal.println to print text to the console window. (Note, however, that a file will not be generated. If you want to create a file, you can use the cs101.Terminal class. Later in CS102, you'll learn how to create files in Java.)


Demonstration:

In your lab section on February 1, you will demonstrate your complete working lab. The TA may ask you to add new questions or options to your survey, and to demonstrate the results.

Bring your signed design with you to the demo, and have a completed CS102 cover sheet ready for the TA to record your demo grade and demo comments (what worked and didn't work).


Hard Copy:

After your demo, take some time to clean up your code, add documentation, and generally make it beautiful. If there was a problem during the demo, you should mark on your code where you think the problem is. If you have time, you can try fixing it, and you should describe how you fixed it and whether or not you were able to get it to work. However, you will not be able to replace your demo grade by doing another demo unless you use a late coupon or a rewrite coupon.


Extra credit option:

Using javadoc comments, add thorough documentation of your API to the java files in your survey package. Then run javadoc to create html pages describing your package. View the javadoc documentation pages for each class of your package in your web browser, and print one of them from your browser as a sample to turn in with your lab. (We will see the javadoc comments in the source files for the others.) See pages 254-255 in Flanagan for a brief summary of the javadoc command options. Javadoc can be run on UNIX (in a telnet session) but you must type the line pkgadd java_1.1 at the beginning of your session to be able to access the javadoc program on CEC.


What to turn in:

By 5:00pm on February 2, you should turn in the following items to the CS102 mailbox:
  1. Your cover sheet (with the demo grade recorded on it).
  2. Your design, signed and dated by a TA.
  3. Your final design (if different from the signed one).
  4. A printed copy of all the code in your survey package.
  5. A printed copy of your test program (and output, if you created a file).
  6. (for extra credit) The javadoc pages for one class in your API, printed from your web browser.


Kenneth J. Goldman (kjg@cs.wustl.edu)