T-Th 9:05
or
T-Th 11:15
in Phillips 101

CS 1110: Introduction to Computing Using Java

Spring 2012

Extending Acorn.com

Due to CMS by Tuesday, February 28

This assignment is a continuation of Assignment A1, the first Acorn.com assignment. In fact, you will be submitting the same files (AcornProfile.java, and AcornProfileTester.java) once again. However, these files will be modified to include new features, so you will probably want to save them in a different folder (and hence leave your old versions for Assignment A1 unchanged). This is doubly important if you are still revising Assignment A1, as we do not want you to submit Assignment A3 modifications as part of your revision.

The previous assignment was intended to get you introduced to the basic elements of Java, writing JUnit tests, and JavaDoc specifications. This assignment will give you practice with some of the features that we have introduced in class since you started Assignment A1:

  • How to use static variables.
  • How to use null and test for it.
  • How to use conditionals to enforce invariants.
  • How to use functions you have already written (and tested) as helper functions in order to save time and promote modularity
  • How to write boolean expressions that use short-circuit evaluation \\(look up that phrase in the text).

Table of Contents

There is a PDF version of these instructions, if you would prefer to have that instead.


Before You Get Started

Grading Policy

The revise-and-resubmit policy was for the first assignment only; we do not have the time to do this for each assignment. Therefore, you will not be allowed to resubmit. Your new functions must have suitable JavaDoc comments, there must be appropriate test cases, and all methods should be correct in order to get full credit. You can achieve all this most easily by writing and testing one method at a time.

We will be taking a few minor points off for formatting and style issues. Please see the course style guidelines, available on the course web page.

Important style issues to keep in mind are as follows:

  • Classes are capitalized, variables are lowercase.
  • Classes and variables that are compound words have the interior words capitalized.
  • JavaDoc specifications go before the class/method, not after.
  • The file should be indented properly; DrJava automatically indents a line if you type "tab" while the cursor is on the line.

Collaboration Policy

You may do this assignment with one other person. If you are going to work together, then form your group on CMS as soon as possible. If you do this assignment with another person, you must work together. It is against the rules for one person to do some programming on this assignment without the other person sitting nearby and helping.

With the exception of your CMS-registered partner, you may not look at anyone else's code or show your code to anyone else, in any form what-so-ever.

Assignment Scope

Everything that you need to complete this assignment should have been covered by Lecture 8 in class. You are now allowed to use if-statements, but only where we tell you to. Please read the instructions below carefully.

Getting Help

If you do not know where to start, if you do not understand testing, or if you are completely lost, please see someone immediately. This can be the course instructor, a TA, or a consultant. Do not wait until the last minute, particularly since this is due on a weekend. A little in-person help can do wonders. See the staff page for more information.


Enforcing Invariants with Conditionals

One of the invariants in Assignment A1 is that the name of a profile cannot be empty and it cannot be null. Indeed, this was a precondition in our constructor. However, with if-statements, we do not always need to to rely on preconditions; we can enforce invariants directly.

Write a new setter method setName with the following specification:

Setter Method Description (JavaDoc Specification)
setName(String n) Sets the name of this profile as n if n is neither null nor empty. Otherwise, it sets the name as "<unknown>".

Note the lack of preconditions in this setter. You should implement this method exactly as it says in the specification. Futhermore, you should not need to modify the constructors. The preconditions for the constructors still hold.

When you are done implementing this method, you should add new tests to the test procedure partB in AcornProfileTester, as that is the test procedure that you used to test setters. The tests should verify that this setter works correctly.

Important: This is the only part of the assignment where you will use if-conditionals.


Adding a Static Variable

Add a private static field to the class AcornProfile that contains the number of profiles that have been created so far. Whenever an AcornProfile object is created, this field should be increased by one; this will require that you change the constructors accordingly. You never delete profiles, so there is no need to be concerned with decrementing this value.

In addition, you should add a public static int function population(), with no parameters, that will return the value of the static variable. Finally, add test cases to class AcornProfileTester to test whether the static variable is properly maintained. Because you may not know the order in which the testing procedures are called when you click button Test, you cannot count on the population starting at 0. Therefore, you should test the population as follows:

  • Write a statement to save the population in a local variable which you might call pop.
  • Write a statement you expect will change the static variable and subtract pop from this new value.
  • Write an assertEquals call to test whether the change in the static variable was what you expected.
Your test cases should appear in a test procedure (e.g. not partA, partB, or partC). Remember that you should not declare fields in the class AcornProfileTester. The only variables declared in the class should be local variables of the procedures.

Adding toString

By default, when you look at an AcornProfile object in the interactions pane, you can see the "folder name" of the object. We want to change that, and have a more descriptive representation of AcornProfile instances. To do this, we write a function toString() with no parameters that produces a String representation of the AcornProfile object.

We are not going to tell you exactly how you should design the toString() method. However, the examples below give you some idea of what we are looking for in this assignment:

  • "Male profile Doug. Born 5/1963. 1 child."
  • "Female profile Ellen. Born 6/1965. 1 child."
  • "Female profile Ammie. ID 19. Born 6/2006. Mother Ellen. Father Doug. 0 children."
There are several rules that you need to follow when making toString():
  • You may not use an if-statement. However, you will use conditional expressions, and we give you one of them below.
  • This function is best written with a single return statement that consists of the catenation of several parts. For readability, you should each part on a separate line. In developing the return statement, it is best to work with one part at a time, making sure it is right before proceeding to the next part.
  • Exactly one blank appears between words (with the exception of the profile name, which can have any spacing within it, depending on what is in the field). Periods '.' are as indicated in the examples.
  • You can get the gender with a blank after it using this conditional expression:
    (isMale() ? "Male " : "Female ")
  • The word "profile" is followed by a blank, the name in the profile, a period `.', and a blank.
  • The profile identifier is given in the form " ID <integer>;. " It appears only if the profile has an identifier.
  • The birth month and year always appear, as in the examples.
  • Suppose the mother of a profile is known and has the name "xxx ". Then "Mother xxx. " appears should appear in the child profile, as in the examples. Similarly for the father. If the mother (father) is not known, nothing should be said about it. The mother appears first.
  • The number of children appears as shown in the examples, with a period after it. When it is 1 child, use "child"; otherwise, use "children".

You should write a separate test procedure (e.g. outside of partA, partB, and partC) to test that toString() works properly. In testing toString(), you need enough test cases to ensure that each different way of evaluating a conditional expression is tested. For example, to test whether the gender appears correctly, you need at least two test cases, for a female AcornProfile and for a male AcornProfile.

When making up a test case, construct it by hand, based on what you read above. Then, write an assertEquals statement that compares this expected value to the computed one. This is what we will do in our test program.


Comparison Functions

Write the functions in the table below. Each produces a boolean value. You should do one at a time. For each funtion, write it, and then test it with test cases in class AcornProfileTester before proceeding to the next function. You should put all the test cases for these methods in one single (new) test procedure.

The comparison functions all obey the following rules:

  • The names of your methods much match those listed above exactly, including capitalization. The number of parameters and their order and types must also match. The best way to ensure this is to copy and paste. Our testing will expect those method names and parameters, so any mismatch will cause our testing program to fail. Parameter names are never tested, so you can change the parameter names if you want.
  • Each method must be preceded by an appropriate specification, as a Javadoc comment. The best way to ensure this is to copy and paste from this handout. After you have pasted, be sure to do any necessary editing.
  • You may not use if-statements, conditional expressions, or arithmetic operations (e.g. addition, multiplication, division). The purpose is to practice using boolean expressions, with operators && (AND), || (OR), and ! (NOT).
  • The function isParent must be written using isMother and isFather as helper methods. We want you to learn to call methods already written instead of doing duplicate work, saving you time and avoiding redundant code. Similarly, the static function isSister (the second one in the table) should be written using a call on the non-static version of isSister.

The methods for this part of the assignment are as follows:

Setter Method Description (JavaDoc Specification)
isMother(AcornProfile p) Yields: "p is not null and p is this profile's mother".
Note: The notation above means that the value of the function is true if p is not null and p is this profile's mother; it is false otherwise. So, e may be null (in which case, the function call's value should be false).
The same comment holds for the remaining specifications.
isFather(AcornProfile p) Yields: "p is not null and p is this profile's father".
isParent(AcornProfile p) Yields: "p is not null and p is this profile's parent".
isSister(AcornProfile p) Yields: "p is not null and p is this profile's sister".
Precondition: p is not null
Note: B is A's sister if (1) B and A are different profiles, (2) B is female, and (3) B and A have at least one parent in common (though not necessarily both).
isSister(AcornProfile p,
           AcornProfile q)
Yields: "p is q's sister".
Precondition: p and q are not null.
Make this function static and write it using the previous isSister(AcornProfile) as a helper method.
isYounger(AcornProfile p,
                AcornProfile q)
Yields: "p is younger than q".
Precondition: p and q are not null.
Make this function static.


Finishing the Assignment

We do not require that you check the JavaDoc this time, but we will be grading that your specifications (e.g. JavaDoc comments) are correct. A good way to see if your JavaDoc comments are correct is to press the JavaDoc button. Look at the list of methods in the web page that it generates. Are your specifications there? If not, then you need to go back and fix your specifications.

In addition, please make sure that you have ample test cases. Is each function tested enough? For example, if an argument can be null, is there at least one test case that has a call on the function with that argument being null? If not, points will be deducted.

Turning it In

Upload files AcornProfile.java and AcornProfileTester.java on the CMS by the due date: Tuesday, February 28th at 11:59PM. Do not submit any files with the extension/suffix .java~ (with the tilde) or .class. It will help to set the preferences in your operating system so that extensions always appear.