Contents:
NOTE: Problem 1 must be done before 8pm on the first day of class (Monday, March 29)! The whole assignment is due by 9am on Wednesday, March 31.
Welcome to CSE 331. You may notice that this Problem Set has a number of sections. DON'T PANIC! If you follow the instructions, you will find it very easy to complete, and you will learn a lot about the tools you will use this quarter. Most of the problems consist of following instructions to set up the configuration of your development environment and some simple exercises to help you become familiar with the tools that you will use for the rest of the course.
You are free to choose your own Java development environment. We provide instructions and support only for Eclipse and the Unix command line. If you plan to work on your own laptop, you may wish to bring the laptop to the Allen Center and do the problem set there, since TAs will be available to help you out if you run into problems. Please note that if you choose to use your own home machine instead of an instructional workstation and you have problems, then you are again generally on your own.
Students who do not complete this problem set on time will be dropped from the class roster. (The reason is that it is very easy to get behind, and people who don't finish problem set 0 tend to drop out of the class, but only after suffering quite a bit. We don't want that to happen to you.)
You are free to get help from anyone, on any portion of this problem set. (The standard collaboration policy does not apply to this problem set.) However, the skills that you learn will stand you in good stead in the rest of the quarter, so ensure that you understand the tools and concepts.
In this assignment, you will learn how to edit, run and test Java code. We will introduce several tools to help you with these tasks, namely SVN and JUnit. These are tools commonly used by developers both in academia and in industry, so your familiarity with them will be a valuable skill. We will provide instructions for working effectively in Eclipse and on the Linux command line.
Though we provide some instructions on how to complete CSE 331 assignments on your own computer with your own tools, you are strongly encouraged to complete this assignment first on the instructional workstations (IWS) in one of the Allen Center software labs using exactly the tools we describe here. If you plan to work on a home computer, you should do the problem set on a software lab machine and also on your home computer since there will be slight differences in the setup. See the Working at Home handout for tips on getting set up. If you plan to work on your own laptop, you may wish to bring the laptop to the Allen Center and do the problem set there, since TAs will be available to help you out if you run into problems. Please note that if you choose to use your own machine instead of the Allen Center software lab machines, and you have problems, then you are again generally on your own, unless you are running either Linux or Windows.
If you get stuck on something in this problem set, you should first check the FAQs/corrections for the problem set. Next, check the forum to see if someone else had earlier posted a similar question. If you can't find what you need, ask a TA in person, post to the forum, or send mail to nte staff.
Note: If you would like to get more practice with Java, then we recommend walking through Sun's Java Tutorial. If possible, try to complete Problem Set 0 first so you can use the tools we describe here when doing the examples in Sun's tutorial.
You must do this step FIRST, even if you are working from home.
Before doing any work (problem sets, labs, etc.) for CSE 331, you need to run the CSE 331 initial setup script. This script will create a version control repository for you.
The script must be run before 8pm on Monday, March 29 (the day of the first lecture).
You are free to choose your development environment for CSE 331 problem sets. We recommend Eclipse. We provide instructions and support for Eclipse on the Linux and Windows machines in the Allen Center software labs. This is completely sufficient for your needs this quarter. Once you have chosen a development environment, you should set it up for CSE 331 use. See Starting the environment for instructions on how to do this for Eclipse and Emacs. (Note: you are free to switch development environments in future problem sets. Do so by following the setup instructions in the above link for the other environment.)
Important: Generally speaking, Eclipse is a widely-used Java development environment with a number of excellent features (including integration with SVN, Ant, and JUnit — tools that we use in CSE 331). However, it is also known to be a resource-intensive application, and uses its own Java compiler which may differ in its behavior (in incorrect ways, at times) from the official Java compiler ("javac") from Sun. All grading in CSE 331 will be based on javac, so it is your responsibility to make sure that your code will compile properly in javac. If you are using Eclipse, one way to verify this is to use the Ant build file we provide for each problem set to compile your code with javac. See the Compiling Java Source Files document for details.
In this problem, you will obtain a copy of various files needed to complete this problem set.
You will not be able to successfully complete this step until 9am on Tuesday, March 30.
Follow the instructions in the Tools: Version Control handout to checkout the cse331 directory.
The cse331 repository directory will be gradually populated by the staff to contain the staff-provided code, as well as a copy of this assignment handout, for every problem set this quarter. You only have to check this out once (if you work from home, you will need to check this out again on your home computer or laptop). You can obtain subsequent changes by running SVN's "update" command.
SVN, which stands for Subversion, is a tool that manages and archives file revisions by one or more users. The Version Control handout describes how to perform the standard operations of checking out, updating, and modifying files on SVN. Instructions are provided for using SVN within Eclipse and on the command line.
For this problem, you will fix some buggy code we provide.
Try to compile the provided code in HolaWorld.java
.
You should be notified of compilation errors in the file. (And
possibly in ps0/test/RandomHelloTest.java
as well. Do
not worry about errors in RandomHelloTest
; these
errors will be fixed in the next problem when we create
RandomHello.java
.) In particular, the lines:
System.out.println(world.);
and:
return spanishGree;
are problematic. (Note that if you're using the the Ant builder, you may only see one of the two errors until you fix it.). Also, if you are using Eclipse, these errors will be marked with red squiggly lines in HolaWorld.java, and HolaWorld.java itself will be marked with a red crossmark in the Package Explorer.
Fix these errors and run HolaWorld
.
After you've fixed the errors and run the HolaWorld code, it would be a good time to commit your changes to SVN.
In this problem, you create your first Java class. Your class' main method will randomly choose, and then print to the console, one of five possible greetings. The text of the 5 possible greetings is up to you.
Create the file RandomHello.java which will define a Java class named RandomHello. It will reside in the Java package ps0, so its file name is YourWorkspaceDirectory/cse331/src/ps0/RandomHello.java.
Java requires every runnable class to contain a main method whose signature is public static void main(String[] argv) (which is identical to the signature of the main method in HelloWorld and HolaWorld).
A code skeleton for the RandomHello class is shown below. Eclipse will generate some of this skeleton for you when you create the new RandomHello class.
RandomHello.java:
package ps0; /** * RandomHello selects a random greeting to display to the user. */ public class RandomHello { /** * Uses a RandomHello object to print * a random greeting to the console. */ public static void main(String[] argv) { RandomHello randomHello = new RandomHello(); System.out.println(randomHello.getGreeting()); } /** * @return a random greeting from a list of five different greetings. */ public String getGreeting() { // YOUR CODE GOES HERE } }
Please note that this skeleton is meant only to serve as a starting point for students who are not familiar with Java. If you have some Java programming experience, you are free to organize RandomHello as you see fit.
Instead of writing your own random number generator to decide which greeting will be written to the console, you should take advantage of Java's Random class. (This is a good example of the adage "Know and Use the Libraries" as described in Chapter 7 of Joshua Bloch's Effective Java.)
Type the following into the body of your getGreeting() method:
Random randomGenerator = new Random();
This line creates a random number generator. If you're using Eclipse, your code may be marked with a red underline, indicating an error. This is because the Random class lies in a package that has not yet been imported (java.lang and ps0 are the only packages that are implicitly imported). Java libraries are organized as packages and you can only access Java classes in packages that are imported (this is similar to #include in C). To explicitly import java.util.Random and avoid the compilation error, you can add the following line under the line package ps0; at the top of your file (after the package ps0; declaration):
import java.util.Random;
The above line will import the class Random into your file. If you are using Eclipse, you can also hit CTRL-SHIFT-O to Organize your imports. Because there is only one class named Random, Eclipse can figure out that you mean to import java.util.Random and will add the above line of code automatically. (If the name of the class that needs to be imported is ambiguous — for example, there is a java.util.List as well as a java.awt.List — then Eclipse will prompt you to choose the one to import.)
Find the documentation for nextInt(int n) and read it. You don't have to understand all the details of its behavior specification, only that it returns a random number from 0 to n-1. You should use this method to choose your greeting.
One way to choose a random greeting is using an array. This approach might look something like:
String[] greetings = new String[5]; greetings[0] = "Hello World"; greetings[1] = "Hola Mundo"; greetings[2] = "Bonjour Monde"; greetings[3] = "Hallo Welt"; greetings[4] = "Ciao Mondo";
The main method in the skeleton code above is written to print the value returned by getGreeting to the console. Thus, you only need to insert code in getGreeting, and the class will will print a message when run.
If you haven't used Java before, or are having trouble with the language or syntax, a good reference is The Java Tutorial from Sun's website. When you are finished writing your code and it compiles, run it several times to ensure that all 5 greetings can be displayed. Congratulations — you have written and compiled your first Java class!
Again, now it would be a good idea to add your new class to version control and commit your code.
Part of your job as a software engineer is to verify that the software you produce works according to its specification. One form of verification is testing. JUnit is a framework for creating unit tests in Java. A unit test is a test for verifying that a specific method in a class conforms to its specifications. You will learn more about unit testing in the next problem set. In this problem, we will provide you with a quick overview of how JUnit works with a simple example.
Open both ps0/Fibonacci.java and ps0/test/FibonacciTest.java. From the comments, you can see that FibonacciTest is a test of the Fibonacci class.
Now run the JUnit test ps0.test.FibonacciTest.
A window (or in Eclipse, a panel) with a menacing red bar will appear, indicating that not all of the tests in FibonacciTest completed successfully. The top pane displays the list of tests that failed, while the bottom pane shows the Failure Trace for the highlighted. The first line in the Failure Trace should display an error message that explains why the test failed (it is the responsibility of the author of the test code to produce this error message).
As shown in the figure above, if you click on the first failure testThrowsIllegalArgumentException(), the bottom pane will automatically switch to the appropriate error message. You can see from the first line of the failure trace that Fibonacci.java threw a IllegalArgumentException for the argument zero, when it shouldn't have thrown any exception (you will have to scroll the pane to the right to see this). Once you've figured out the problem in Fibonacci.java that caused this error and fixed it, rerun the JUnit test. Note, if you are running junit from the command line, you must rebuild (compile) Fibonacci.java before you rerun Junit. This can be done by rerunning the ant command (which also compiles the files) or following the compiling instructions and then clicking the "Run" button.
Use the information in the Failure Trace box to help you continue debugging Fibonacci. Keep a record of what you did to debug Fibonacci as you will have to answer questions about your debugging experience in the next problem. After you have fixed all the problems in Fibonacci, you should see a bright green bar instead of a red one when you run FibonacciTest.
Now that you have learned to run JUnit, you should also check out the JUnit tests that we wrote for HolaWorld and RandomHello in Problem 4 earlier. They are called HolaWorldTest and RandomHelloTest, respectively. Please ensure that your modified code passes these tests before you turn in your problem set.
In this problem, you will write, in a newly created text file, the answers to some questions about the Fibonacci class. Most design projects that you will be assigned will require you to submit some sort of response or write-up in addition to your code. Follow these instructions to create a text file, named ps0/answers/problem7.txt, with answers to the following questions:
Until now, we have only been introducing tools. In this problem, we will delve into a real programming exercise. If you are not familiar with Java, we recommend working through Sun's Java Tutorial and trying out the Optional Problems provided.
The intention of this problem is to give you a sense of what Java programming entails and further demonstrate the JUnit testing tool. If you have never programmed in Java. you may find this problem somewhat challenging. Do not be discouraged, if you spend effort getting this problem right now, you will likely have less trouble later in the course.
As you work on this problem, you should also record your answers to the various questions in a file called problem8.txt in the project's ps0/answers/ directory.
As a warm up exercise, take a look at Ball.java. A Ball is a simple object that has a volume.
We have included a JUnit test called BallTest.java to help you out here. If you are using Eclipse and are paying attention to its warnings, you should be able to find at least one of the bugs without referring to the JUnit results.
Next, we want to create an class called BallContainer. As before, skeleton code is provided (see BallContainer.java). A BallContainer is a container for Balls. BallContainer must support the following methods and your task is to fill in the code that will implement all these methods correctly:
The specifications for these methods are found in the javadoc file for BallContainer.One of the nice things about Java is that it has many libraries and pre-defined data structures that you can simply use without have to write your own from scratch. One of the intentions of this problem is to expose you to the use of pre-defined Java data-structures. In BallContainer, we use a java.util.Set to keep track of the balls.
Before you proceed to implement the required method, please take a moment to read through the documentation for Set. Some of the methods that you are required to implement simply require you to call the appropriate predefined methods for Set. To help you out, we have included a JUnit test called BallContainerTest.java.
Most of the methods that you are required to implement are quite simple. Before you start coding, please take time to think about the following question (you need to turn in your answers):
There are two obvious approaches for implementing getVolume():
- Every time getVolume() is called, go through all the Balls in the Set and add up the volumes. (Hint: one solution might use a for-each loop to extract Balls from the Set.)
- Keep track of the total volume of the Balls in BallContainer whenever Balls are added and removed. This obviates the need to perform any computations when getVolume is called.
Which approach do you think is the better one? Why?
By the time you are done with BallContainer, you should be fairly comfortable with Java, so in this problem, we want you to do a little more design and thinking and a little less coding. Your final task in this problem is to create a class called Box. A Box is also a container for Balls. The key difference between a Box and a BallContainer is that a Box has only finite volume. Once a box is full, we cannot put in more Balls. The size (volume) of a Box is defined when the constructor is called:
public Box(double volume);
Since a Box is in many ways similar to a BallContainer, we internally keep track of many things in the Box with a BallContainer, allowing us to reuse code. You will notice that many of the methods in Box simply "delegate" to the equivalent in BallContainer. This design of having one class contain an object of another class and reusing many of the latter class's methods is called composition. We will be using composition throughout CSE 331.
(Note: If you are familiar with Java, you may wonder why we did not simply make Box extend BallContainer via "inheritance"; that is, why did we not make Box a subclass of BallContainer. We will discuss this much more deeply later in the course, but the key idea is that Box is not what we call a true subtype of BoxContainer because it is in fact more limited than BallContainer (a Box can only hold a limited amount); hence, a user who uses a BallContainer in his code can not simply substitute that BallContainer with a Box and assume the same behavior in his program. (The code may cause the Box to fill up, but he did not have this concern when using a BallContainer). For this reason, it is not a good idea to make Box extend BallContainer.)
In addition to the constructor described above, you will need to implement the following new methods in Box:
The specifications for these methods is found in the javadoc file for Box.
There should be no need to change your implementation of BallContainer or Ball for this problem, but if do, you should explicitly describe your changes in problem8.txt and explain why the changes were made. Additionally, don't forget to commit your code when you've gotten a significant portion of the problem working and tested.
We provide a JUnit test BoxTest.java to help you out. Before you start working on getBallsFromSmallest(), you may wish to check out the documentation on Iterator. Also, take some time to answer the following questions (which you need to turn in):
There is no one correct answer. The whole point of this exercise is help you fight that urge to code up the first thing that comes to mind, but instead spend a little more time thinking before you start coding. Remember: More thinking, less coding.
Throughout this course, you will turn in the solutions for the problem sets by checking them into your SVN repository. All the relevant files should be included, for example:
Each problem set will indicate exactly what you need to turn in a Section entitled “What to Turn In”.
If you add a new file, you must explicitly add to your SVN repository. Just adding the file to the repository is not enough; you need to commit the file. Furthermore, after making changes to a file, you must commit it so that we, the staff, can collect your most up-to-date version.
Since files like RandomHello.java, problem7.txt and problem8.txt are not in your SVN repository, you must add them. You also want to commit the changes you made to HolaWorld.java, Fibonacci.java,Ball.java, BallContainer.java, and Box.java.
After completing the above steps, all your code and materials to turn in should be in your SVN repository. The final step to turn in is to validate your solutions. The validate script performs general sanity checks on your solutions. In particular, it checks out a fresh copy of the module from your SVN repository into a temporary directory, checks that it has the required files, compiles the Java files, and tests your code against our suite of public tests (see here for more information about this testing framework, and about the test classes ps0.test.SpecificationTests and ps0.test.ImplementationTests, which you do NOT have to modify for this problem set).
To validate, execute the validate target in your Ant buildfile (build.xml). This does not work well with Eclipse's integrated Ant support, so even if you are using Eclipse as your development environment, you should validate on the command-line, by running the following on attu (NOTE: if you are working from home, you'll need to check out a copy of your code on attu using the command line before you can successfully complete this next step):
cd ~/workspace331/cse331/src/ps0/ ant validate
If validation was successful, you should see output that looks something like:
Buildfile: /homes/iws/twsugrad/workspace331/cse331/src/ps0/build.xml validate: [echo] Validate checks out a fresh copy of the pset, checks for the [echo] presence of required files, and runs all your tests to make sure [echo] they pass. This target is meant to be called from attu; don't [echo] trust it to make sure everything works unless you are on attu. [echo] Note: the test reports will be generated under the scratch [echo] directory the validate target creates. [echo] [delete] Deleting directory /homes/iws/twsugrad/workspace331/cse331/scratch [mkdir] Created dir: /homes/iws/twsugrad/workspace331/cse331/scratch [echo] /projects/instr/10sp/cse331/twsugrad/REPOS [exec] A cse331 [exec] A cse331/.classpath [exec] A cse331/.project ... [exec] Buildfile: /homes/iws/twsugrad/workspace331/cse331/scratch/cse331/src/ps0/build.xml [exec] [exec] cleancopy: [exec] [echo] Pset directory: /homes/iws/twsugrad/workspace331/cse331/scratch/cse331/src/ps0 [exec] ... [exec] BUILD SUCCESSFUL [exec] Total time: 2 seconds [exec] Buildfile: /homes/iws/twsugrad/workspace331/cse331/scratch/cse331/src/ps0/build.xml [exec] [exec] build: [exec] [exec] single.build: [exec] [echo] This pset is independent; building only this one. [exec] [javac] Compiling 23 source files to /homes/iws/twsugrad/workspace331/cse331/scratch/cse331/bin [exec] [exec] multi.build: [exec] [exec] test.impl: [exec] [mkdir] Created dir: /homes/iws/twsugrad/workspace331/cse331/scratch/cse331/src/ps0/test/reports [exec] [junit] Running ps0.test.ImplementationTests [exec] [junit] Tests run: 0, Failures: 0, Errors: 0, Time elapsed: 0.004 sec [exec] [exec] test.spec: [exec] [junit] Running ps0.test.SpecificationTests [exec] [junit] Tests run: 24, Failures: 0, Errors: 0, Time elapsed: 0.181 sec [exec] [exec] test: [exec] [echo] Records of this testing can be found in /homes/iws/twsugrad/workspace331/cse331/scratch/cse331/src/ps0/test/reports/ [exec] [exec] test.strict: [exec] [exec] BUILD SUCCESSFUL [exec] Total time: 4 seconds [delete] Deleting directory /homes/iws/twsugrad/workspace331/cse331/scratch BUILD SUCCESSFUL Total time: 9 seconds
If there is an error, the validate script should provide some information about what is wrong:
Buildfile: /homes/iws/twsugrad/workspace331/cse331/src/ps0/build.xml validate: [echo] Validate checks out a fresh copy of the pset, checks for the [echo] presence of required files, and runs all your tests to make sure [echo] they pass. This target is meant to be called from attu; don't [echo] trust it to make sure everything works unless you are on attu. [echo] Note: the test reports will be generated under the scratch [echo] directory the validate target creates. [echo] ... [exec] cleancopy.check: [exec] [echo] Found required file BallContainer.java [exec] [exec] cleancopy.check: [exec] [echo] Found required file Box.java [exec] [exec] cleancopy.check: [exec] [echo] Found required file answers/problem6.txt [exec] [exec] cleancopy.check: [exec] [exec] BUILD FAILED [exec] /homes/iws/twsugrad/workspace331/cse331/scratch/cse331/src/common.xml:81: The following error occurred while executing this line: [exec] /homes/iws/twsugrad/workspace331/cse331/scratch/cse331/src/common.xml:96: Could not find required file: answers/problem7.txt [exec] [exec] Total time: 2 seconds BUILD FAILED /homes/iws/twsugrad/workspace331/cse331/src/common.xml:129: exec returned: 1
This error would indicate that a required file, answers/problem7.txt is missing. Make sure you've committed this file to SVN.
If validate failed because the test suite failed, you can view a summary of the JUnit failures in your YourWorkspaceDirectory/cse331/scratch/src/ps0/test/reports/ directory.
Validate your problem set as many times as necessary until there are no errors. You have now successfully turned in your first CSE 331 problem set. We encourage you to give the Optional Tutorial Problems a try.
Your TA should be able to find the following when he checks your src directory of SVN:
If you have not had much experience with Java, we recommend that you do these extra Optional Problems (source code for these problems can be found in the ps0.optional package that came with your ps0 checkout). If you do not know Java, CSE 331 will require you to learn it quite quickly. The optional problems, although not required, will help you become more comfortable with Java.
We strongly encourage you to use the CSE 331 Online Forum.
None yet.
This section will list clarifications and answers to common questions about problem sets. We'll try to keep it as up-to-date as possible, so this should be the first place to look (after carefully rereading the problem set handout and the specifications) when you have a problem.