Assignment 2: CMSμ
Due: Thursday, September 15
Learning Objectives
- Become familiar with the structure of a class
- Work with good examples of method specifications
- Learn about class invariants
- Learn about a simple data structure and how to use it
- Work with a small piece of software made of multiple classes
- Learn how to write good tests for a class or set of classes
Introduction
The CMSX system we are using in this class was developed by Cornell students over the past 20 years, and is still used by this class and other large classes at Cornell because it offers features and performance not available in commercially available tools like Canvas.
In this assignment, you will be designing a simple system, CMSμ (μ for “micro”), which provides a small subset of the features of CMSX. The CMSμ system will manage the enrollment of students in courses, allowing the user to interact with it through several different commands. When a user starts the system, they will be able to add new students and courses, enroll students in courses, drop students from courses, and view information about specific courses and students.
As part of the assignment, you will implement an abstraction for a
mutable list of students, which we will call StudentList
.
This abstract data type will be used to keep track of all students in
the system as well as all students enrolled in each course. Your
implementation of this abstraction will use a useful data
structure, the resizable array.
Academic Integrity and Collaboration Policy
You may not collaborate with anyone on the code for the classes in this assignment—this includes looking at anyone else's code or showing anyone else your code in any form. While you can talk to others, this should not be sharing code but rather discussing general strategies on how to tackle a problem. Any such discussions must be documented. You may not look at solutions to similar assignments in previous runs of 2110.
In this assignment, you will work with another student with whom you will share test cases. You and this student can work together to write test cases for testing the classes. However, you and your partner may not share any code for the classes themselves. You can choose your own partner by inviting them on CMSX. However, if you do not have a partner by Wednesday, September 7th, we will randomly assign you a partner. You may find the partner-finding social event (September 6, 4–6pm, Upson Lounge) helpful.
If you do not know where to start, are stuck, do not understand testing, or are lost, please see someone on the course staff immediately. This can be in the form of an instructor, TA, or consultant.
How to do the Assignment
Start early. This is a longer and more involved assignment than Assignment 1.
Scan the entire assignment handout before starting. The three assignment classes are commented with various TODO statements numbered 1 through 25. Please design your classes and tests in this order to avoid confusion. An important part of design is to develop your classes and test them incrementally. This means you should test each part of the code you write before continuing to write the next step. We will pin a post on Ed with FAQs about this assignment. This post will be updated regularly with answers to questions including notes about what you can or can't use in your solution. Please read this post regularly to stay up to date on this information.
-
At this point, you should have all of the release code classes in your project. The first step
is to create your test class and also develop the
Student
class. To start, open theA2Test
class in thea2
package. Here you and your testing partner will write unit tests primarily to test the methods of yourStudentList
class. You can write these tests using a similar format to those you wrote in A1.
-
In class
Student
, declare the fields listed in the release code and write their class invariant.The class invariant. Comments must accompany the declarations of all fields to describe what the fields mean, what legal values they may contain, and what constraints hold for them. For example, for
firstName
, state in a comment that the field contains the Student's first name and must be a String of at least 1 character. The collection of the comments on these fields is called the class invariant.Use Javadoc comments for both the class invariant and method specifications. A Javadoc comment is a multiline comment that starts with
/**
instead of/*
. You can find examples of this in theStudentList
andCourse
classes.For this assignment you should also implement a method
classInv()
that implements the class invariant check as described in class. The method should be package-visible to help us test it. You will likely find it help to insert calls toclassInv()
in your method code to catch bugs. -
For each method in the
Student
class you must do the following:
- Read the Javadoc specification for the method describing what the method does as well as its preconditions.
- Write the method body, implementing what the method specifications say the method should do.
- Write a test procedure in your testing class that tests this method.
- Test the method thoroughly.
Method specs do not mention fields because the user may not know what the fields are, or even if there are fields. The fields are private.
How to test the Constructor. Based on its specification. figure out what values all the fields should be to make the class invariant true. Then inA2Test
, write a test procedure that tests the constructor by calling the constructor and using the observer methods to determine if all the fields have the correct values. This also tests all the observer methods!
-
Next you will fill in the methods in the
StudentList
class. The methods you need to fill in will all be marked with a TODO comment.
It is important you also write tests inA2Test
to test each of the methods you write as you write them. We highly recommend you write and test each method before continuing to write the next method!
-
The next step is to write the
Course
class. Similar to theStudentList
class, all the methods that you have to write have a TODO comment. Some of these TODO comments have additional information that you should read. This information is very important.
-
Main.java
is a harness class containing code that processes some commands. Once you complete implementing theStudent
,Course
, andStudentList
classes, you can run the code inMain.java
successfully and use various commands to add students and courses to your CMSμ program. Additionally, you can enroll and drop students from courses and list all students and available courses. There is ahelp
command that lists all the commands available and how to use them to get you started. You should not change any of the code inMain.java
.
Commands
The system provides several different commands a user can run to manage the courses and students. Below are all the commands you will be implementing and their expected behavior. We provide a sample test script and the expected output when running that set of commands. You will also work with your testing partner to create your own test scripts to test your code. Command arguments must be separated by spaces.
-
help
: Output general usage format for all commands. -
addstudent f l yr
: Create a newStudent
with first namef
, last namel
, and yearyr
-
addcourse n p loc t
: Create a newCourse
with name =n
, professor name =p
, location =loc
, and time in 24-hour time =t
. -
enroll i j
: Enroll studenti
in coursej
. The numbersi
andj
are indices into the lists of all students and courses, respectively. -
drop i j
: Drop the studenti
from the coursej
. The numbersi
andj
are indices into the lists of all students and courses, respectively. -
students
: List all students. -
courses
: List all available courses. -
enrollment j
: List all students enrolled in course numberj
, wherej
is the position of the course in the list of all courses. -
exit
: Exit the program.
Resizable Arrays
The most technically demanding part of the assignment is to implement
the StudentList
class. This class is an abstract data type
representing a list of students. We are expecting you to implement it
as a resizable array data structure. Ordinary arrays in Java
have a fixed length, so they are not sufficient to store a list of
students that can grow to an arbitrarily large size. The Java standard
libraries do have existing classes that can keep track of such a list,
such as java.util.ArrayList
, but we are asking you to
implement your own class without relying on any classes from the
java.util
package.
A resizable array is a simple, common data structure that acts like an
array whose size can change, for example by adding new elements to the
end of the array. A resizable array is implemented on top of
fixed-length arrays. The data structure is backed by an underlying,
fixed-length array that contains all of the elements of the resizable
array. However, the underlying array is typically longer than necessary
to store the elements it contains: up to half of the elements of the
underlying array are logically “empty” and do not contain useful information.
For example, a resizable array might have an
underlying array of length 100 but only contain 70 elements at indices
from 0 to 69. The contents of the remaining locations are not important.
For example, they might contain null
.
A new element can then be added efficiently by simply
storing it at index 70, and updating the data structure to record
that the number of elements has increased. Thus, there is a difference
between the capacity of the backing array and the number of
elements in the resizable array. Viewed through the abstraction, the
client should not be able to tell how big the backing array is.
If the capacity of the backing array is exceeded, a new, larger backing array is created and the resizable array data structure is changed to refer to the new backing array. It is conventional to double the size of the backing array when its capacity is exceeded, so that it is not more than 50% empty unless elements are removed.
How to Run CMSμ with a Test Script
In order to run CMSμ with a test script, first create a tests
directory in your project by
right clicking on the project name and selecting New ⇒ Directory. Name this directory tests
.
If you name it something else, it will not work. Then create a new text file inside the tests
directory and put your test script in this file.
Next, go to Run → Edit Configurations. You should see a
run configuration for Main.java
. Then go to the Program Arguments field in the popup window
and enter the name of your test script text file. For example, if my file is called script1.txt
,
I would enter script1.txt
in the program arguments. Then click Ok and run the main method
in Main.java
. This will read the commands in the test script file and run them in order. We
will provide one example test script for you to use, but we strongly suggest that you work with your test
partner to write more test scripts.
Submission
Please make sure to fill in the time you spent using the timeSpent
field in the StudentList
class. Additionally, be sure to fill in your NetID and other information in the comment at the top of the
StudentList
class. Please also provide your testing partner's NetID after your own. Then upload
your files StudentList.java
, Course.java
, Student.java
, and A2Test.java
to CMSX before the deadline. Additionally, use zip to compress your tests folder containing all the test scripts you used
and submit it as tests.zip
to CMSX before the deadline. To locate these files on
your computer, you can right click on any of the classes and select "Open In" and then select your file
explorer. For Windows, that may be "Explorer" and for Mac, that may be "Finder." Do not submit any files
with different extensions at the end. To check if you submitted the correct files, download the files from
CMSX after you have submitted them.