6.005 — Software Construction
Tasks 0, 1, & 2 due : before class Friday, September 5, 2014, 1:00 pm ---- Beta due : Monday, September 8, 2014, 10:00 pm Code reviews due : Wednesday, September 10, 2014, 10:00 pm Final due : Monday, September 15, 2014, 10:00 pm
## Before you start coding **Install the software you'll need on your laptop.** You need to install three things for 6.005 problem sets: + **[JDK 8]** (for Windows, Linux, or Mac): From this web page, download Java SE Development Kit (JDK) 8 (you don't need NetBeans or Java EE). The latest version of Java is required. + **[Eclipse 4.4]** (a.k.a. Eclipse Luna): Choose "Eclipse IDE for Java Developers," which will download a .zip file. These links will help you determine if you should download 32-bit or 64-bit Eclipse: [Windows], [Mac]. Unpack the .zip file, go inside the resulting folder, and run Eclipse. The latest version of Eclipse is required. Make sure Eclipse is configured to use Java 8: 1. **Windows**: Click *Window → Preferences → Java → Installed JREs* **Mac**: Click *Eclipse → Preferences → Java → Installed JREs* Ensure that "Java SE 8" is the only one checked. If it's not listed, click Search. 2. Also in Preferences, click *Java → Compiler* and set "Compiler compliance level" to 1.8. Click OK and Yes on any prompts. + **[Git]**: We will be using the command-line version of Git. If you already have Git installed, there is no need to install the latest version. **Windows** users should look for the Git shell. **Mac & Linux** users should try running `git` in a terminal. The Git site should prompt you to download the appropriate version. Follow the instructions in the README file in the downloaded .zip or .dmg file. **Windows**: choose "use Git from the windows command prompt", "checkout windows-style, commit unix-style line endings", and select to add a shortcut to Desktop during installation (this creates a Git Bash shortcut which you will use for all Git commands). **Mac**: if you receive an "unidentified developer" warning, right-click the .pkg file, select *Open*, then click *Open*. [JDK 8]: http://www.oracle.com/technetwork/java/javase/downloads/jdk8-downloads-2133151.html [Eclipse 4.4]: http://www.eclipse.org/downloads/ [Git]: http://www.git-scm.com/ [Windows]: http://support.microsoft.com/kb/827218 [Mac]: http://support.apple.com/kb/HT3696 ## Eclipse The Eclipse integrated development environment (IDE) is a powerful, flexible, complicated, and occasionally frustrating set of tools for writing, modifying, and debugging programs. It is especially useful for working in Java. When you run Eclipse, you will be prompted for a "workspace" directory, which is where Eclipse will store its configuration and metadata. The default location is a directory called `workspace` in your home directory. **You should not run more than one copy of Eclipse at the same time** with the same workspace, or the metadata will become corrupted. The first time you run Eclipse, it will show you a welcome screen. Click the button to go directly to the "Workbench" and you're ready to begin. You may also store your code in the workspace directory, but this is not required, and is occasionally confusing. On the left side of your Eclipse window is the Package Explorer, which shows you all the projects in your workspace. **The Package Explorer looks like a file browser, but it is not.** Don't be fooled — it rearranges files and folders, includes things that are not files or folders, and can include projects stored **anywhere on disk** that have been added (but not copied into) to the workspace.
Read: [Getting Started with Eclipse](http://web.mit.edu/6.005/www/fa14/tutorial/eclipse/)
### Tab policy At this time you should configure your editor to use spaces instead of tabs. This will ensure that your code looks the same in all editors, regardless of the configured width of a tab character in each editor. Go to *Window* (*Eclipse* if you're running a Mac) *→ Preferences...* In the sidebar go to *Java → Code Style → Formatter*. Click the "Edit..." button next to the active profile. In the new window you should change the Tab policy to "Spaces only." Keep the Indentation size and Tab size at 4. Enter a new name for the policy and press OK. ## Git To turn in this problem set, you will commit and push your code to a [Git](http://en.wikipedia.org/wiki/Git_(software)) repository. The last code committed *and* pushed before the problem set due date will be used for grading. Git is a Version Control System (VCS). If you have used other version control software before, like SVN or CVS, many of the concepts and procedures of git will be familiar to you. The "Pro Git" book is available from the [git documentation page](http://git-scm.com/book); it describes what git is and how to use it. Quote: > What is version control, and why should you care? Version control is a system > that records changes to a file or set of files over time so that you can > recall specific versions later. [...] It allows you to revert files back to a > previous state, revert the entire project back to a previous state, compare > changes over time, see who last modified something that might be causing a > problem, who introduced an issue and when, and more. Using a VCS also > generally means that if you screw things up or lose files, you can easily > recover. Quite simplified, below are some important git concepts to know about: + **repository:** A folder containing all the files associated with a project (e.g. a 6.005 problem set or team project), as well as the entire history of *commits* to those files. + **commit (or "revision"):** A snapshot of the files in a repository at a given point in time. + **add (or "stage"):** Before changes to a file can be *committed* to a repository, the files in question must be *added* or *staged* (before each commit). This lets you commit changes to only certain files of your choosing at a time, but can also be a bit of a pain if you accidentally forget to add all the files you wanted to commit before committing. If you are committing to git using Eclipse, Eclipse will help you select which files to add before committing. + **clone:** Since git is a "distributed" version control system, there is no concept of a centralized git "server" that holds the latest official version of your code. Instead, developers "clone" remote repositories that contain files they want access to, and then commit to their local clones. Only when they *push* their local commits to the original remote repository are other developers able to see their changes. + **push:** The act of writing your local commits to a remote repository. Again, until you add, commit *and* push your changes, no one else can see them. + **pull:** The act of retrieving commits made to a remote repository and writing them into your local repository. This is how you are able to see commits made by others after the time at which you made an initial clone. We will discuss Git in more depth as the course goes on. For now, you can simply follow the instructions in this handout. If you want to go through an interactive tutorial, Code School's [**Try Git**](http://try.github.com/) will show you these commands with a remote repository on GitHub.
Read: [Getting Started with Git](http://web.mit.edu/6.005/www/fa14/tutorial/git/)
**Optional: try Gitless**
[**Gitless**](http://gitless.com) is a version control tool built on top of Git, designed to be as *simple* as possible. You can use Gitless with your repos in 6.005, although the course staff will not be able to answer questions about it. [See more info about Gitless on the Getting Started with Git page](http://web.mit.edu/6.005/www/fa14/tutorial/git/).
## Git in 6.005 problem sets {#clone} For each problem set in 6.005, we will create a git repository for you at:

/mit/6.005/git/[semester]/psets/ps[pset number]/[Athena username].git

Initially this "remote" repository will contain some template code that we provide. To work on a problem set, you need to *clone* this remote repository into a local repository in your Eclipse workspace. To hand in your work, you need to both *commit* your changes to the local repository and *push* them to the remote repository. When the time comes for grading your assignments, we will clone the remote repository (at the location above), and look at the last commit you made and pushed there before the deadline. ### Cloning your repository Step 1: open the terminal (or the Git Bash for Windows) and change to the directory where you would like to store your code; for example, your Eclipse workspace directory. Step 2: you will access the remote repository over SSH from your laptop. In the terminal, run **(all on one line)**:
git clone ssh://[username]@athena.dialup.mit.edu/mit/6.005/git/fa14/psets/ps0/[username].git ps0
If you are a **listener or not taking 6.005 for credit**, you can clone a problem set repository using a slightly modified command: replace the *last* instance of `[username]` with the word `starting`. You will not be able to push to this repository, it's a read-only remote. The result should be a directory named `ps0`. This directory contains the starting code for the problem set. Keep the terminal open—you will need it to commit your code (you can always close your terminal and come back to the same directory to commit, of course). ### Configuring Git Now that you have set up your first Git repository, there are a few ways in which you should configure Git on your computer before continuing. Please follow the instructions described in [Getting Started with Git] under [Configuration & Editors] to configure Git. [Getting Started with Git]: http://web.mit.edu/6.005/www/fa14/tutorial/git/ [Configuration & Editors]: http://web.mit.edu/6.005/www/fa14/tutorial/git/config.html ### Editing in Eclipse After cloning your repository, you need to add the project to Eclipse so you can work on it. + In Eclipse, go to *File → Import... → Git → Projects from Git* + On the "Select Repository Source" page, select "Existing local repository" + On "Select a Git Repository," click Add..., and Browse... to the directory of your clone + The "Search results" list should show your clone, with ".git" at the end; click "Finish" + On "Select a wizard" for importing, choose "Import existing projects" + Finally, on "Import projects," make sure ps0 is checked, and click "Finish" Note: if you encounter issues with Git support in Eclipse, you can import without telling Eclipse that your project is a Git repository: + Go to *File → Import... → General → Existing Projects into Workspace* + Choose "Select root directory" and Browse... to the directory containing your project (it will be the directory containing the src directory and a hidden .project file) + Make sure the project is checked, make sure "Copy projects into workspace" is **not** checked, and click "Finish" ## Task 0: Setup * Install and configure Java, Eclipse, and Git according to all the instructions above. * Clone your `ps0` repository and import it into Eclipse according to the instructions above. ---- ## Task 1: Warm-up with `may­Use­Code­In­Assignment()` Look at the source code contained in `RulesOf6005.java` in package `rules`. Your warm-up task is to implement: ```java mayUseCodeInAssignment( boolean writtenByYourself, boolean availableToOthers, boolean writtenAsCourseWork, boolean citingYourSource, boolean implementationRequired) ``` You can find the policy under [General Information](http://web.mit.edu/6.005/www/fa14/general/) on [Stellar](https://stellar.mit.edu/S/course/6/fa14/6.005/materials.html). Once you've implemented the method, run the `main` method in `RulesOf6005.java`. `public static void main(String[] args)` is the entry point for Java programs. In this case, the `main` method calls the `mayUseCodeInAssignment` method with input parameters. To run `main` in `RulesOf6005`, right click on the file `RulesOf6005.java` in either your Package Explorer, Project View, or Navigator View, go to the *Run As* option, and click on *Java Application*. ## Unit testing Right now, we can use the `main()` method plus some visual inspection to verify that our implementation is correct. More generally, programs will have many dozens of methods that need to be tested; visually inspecting output for each one is fragile, time-consuming, and inherently non-scalable. Instead, we will use *automated unit testing*, which runs a suite of tests to automatically test whether the implementations are correct. For this problem set, we will write unit tests for methods that do not draw graphics on the screen; unit-testing GUIs is a more complex problem. ###Automated unit testing with JUnit [JUnit](http://www.junit.org/) is a widely-adopted Java unit testing library, and we will use it heavily in 6.005. A major component of the 6.005 design philosophy is to decompose problems into minimal, orthogonal units, which can be assembled into the larger modules that form the finished program. One benefit of this approach is that each unit can be tested thoroughly, independently of others, so that faults can be quickly isolated and corrected as code is rewritten and modules are configured. Unit testing is the technique of writing tests for the smallest testable pieces of functionality, to allow for the flexible and organic evolution of complex, correct systems. By writing thoughtful unit tests, it is possible to verify the correctness of one's code, and to be confident that the resulting programs behave as expected. In 6.005, we will use JUnit version 4. ### Anatomy of JUnit JUnit unit tests are written method by method. There is nothing special a class has to do to be used by JUnit; it only need contain methods that JUnit knows to call, which we call *test methods*. Test methods are specified using *annotations*, which may be thought of as keywords (more specifically, they are a type of metadata), that can be attached to individual methods and classes. Though they do not themselves change the meaning of a Java program, at compile- or run-time other code can detect the annotations and make decisions accordingly. Though we will not deeply explore annotations in 6.005, you will see a few important uses of them. Look closely at `RulesOf6005Test.java`, and note the `@Test` that precedes method definitions. This is an example of an annotation. The JUnit library uses this annotation to determine which methods to call when running unit tests. The `@Test` annotation denotes a test method; there can be any number in a single class. Even if one test method fails, the others will be run. Unit test methods can contain calls to `assertEquals`, which is an assertion that compares two objects against each other and fails if they are not equal, `assertTrue`, which checks if the condition is true, and `assertFalse`, which checks if the condition is false. [Here is a list of all the assertions supported by JUnit](http://junit.org/javadoc/latest/index.html?org/junit/Assert.html). If an assertion in a test method fails, that test method returns immediately, and JUnit records a failure for that test. ### Running existing tests To run the tests in `RulesOf6005Test`, simply right click on the `RulesOf6005Test.java` file in either your Package Explorer, Project View, or Navigator View, and go to the *Run As* option. Click on *JUnit Test*, and you should see the JUnit view appear. If your implementation of `mayUseCodeInAssignment` is correct, you should see a green bar, indicating that all the tests (there's only 1 test, containing 2 assertions) passed. Try *breaking* your implementation and running `RulesOf6005Test` again. You should see a red bar in the JUnit view, and if you click on `testMayUseCodeInAssignment`, you will see a *stack trace* in the bottom box, which provides a brief explanation of what went wrong. Double-clicking on a line in the failure stack trace will bring up the code for that frame in the trace. This is most useful for lines that correspond to your code; this stack trace will also contain lines for Java libraries or JUnit itself. Enough breaking: fix your implementation so it's correct again. Make sure the tests pass. Passing the JUnit tests we provide does **not** necessarily mean that your code is perfect. You should still look over the function specifications carefully, and always write your own JUnit tests to verify your code. For a more thorough introduction, [O'Reilly has a JUnit and Eclipse tutorial](http://onjava.com/pub/a/onjava/2004/02/04/juie.html), with screenshots to help you get acquainted with using JUnit in Eclipse. Unfortunately, the guide was written for JUnit 3, so the code samples use an older (but still supported) JUnit API. ---- ## Task 2: commit and push `Rules­Of­6005` After you've finished implementing the function and verified it is correct, let's do a first commit. First, in the terminal, change directory (`cd`) to your clone, and take a look around with > `git status` which shows you files that have been created, deleted, and modified in the project directory. You should see `RulesOf6005.java` listed under "Changes not staged for commit." This means Git sees the change, but you have not (yet) asked Git to include the change as part of your next commit. You can run the command > `git diff` to see your changes. (**Note**: when the diff is more than one page long, use the arrow keys. Press `q` to quit the diff.) Before committing, files must be *staged* for commit. Staging a file is as simple as > `git add <filename>` so use > `git add src/rules/RulesOf6005.java` to stage the file. You should also stage the test file if you've added more tests. In addition, it's always a good idea to review your commits before committing to them. Run > `git status` again to see that your changes are now listed under "Changes to be committed." If you run > `git diff` those changes are no longer shown! Use > `git diff --staged` to see exactly what Git will record if you commit now. Ready? To perform the commit, > `git commit` will actually commit the changes locally, after opening your default editor to allow you to write a commit message (which you should always do!). Your message should be formatted according to the [Git standard](http://git-scm.com/book/ch5-2.html#Commit-Guidelines): a short summary that fits on one line, followed by a blank line and a longer description if necessary. **Note**: you may be asked to configure your default identity if this was not done earlier. Use the commands on [Configuration & Editors]. You can use the command > `git log` to see the history of commits in your project. Right now, you should see two of them: the initial commit to create your problem set repository with the starting code, and the commit you made just now. **Important:** only the local history has the new commit at this point; it is not stored in your remote repository. This is one important aspect where Git is different from centralized systems such as Subversion and CVS. In order to share the changes with your remote repository (which is the one we will be using for grading), you need to *push* to the remote repository, with > `git push origin` At this point, the remote repository now has the same history as your local repository. It is important to remember that we will be grading the history in the repository on Athena; if you forget to push, we won't see your commits. When you push your commit, you should see a piece of 6.005 infrastructure called Didit wake up and run a *subset* of the autograder on your code. Didit works by making its own copy of your code from what you've pushed to Athena. Most everything will fail since you've only implemented one method, but, as the deadline approaches, this should give you feedback to make sure we can correctly compile and run your code. ---- ## Turtle graphics and the Logo language [Logo](http://en.wikipedia.org/wiki/Logo_%28programming_language%29) is a programming language created at MIT that originally was used to move a robot around in space. Turtle graphics, added to the Logo language, allows programmers to issue a series of commands to an on-screen "turtle" that moves, drawing a line as it goes. Turtle graphics have also been added to many different programming languages, [including Python](http://docs.python.org/2/library/turtle.html), where it is part of the standard library. In the rest of problem set 0, we will be playing with a simple version of turtle graphics for Java that contains a restricted subset of the Logo language: + `forward(units)` Moves the turtle in the current direction by *units* pixels, where units is an integer. Following the original Logo convention, the turtle starts out facing up. + `turn(degrees)` Rotates the turtle by angle *degrees* to the right (clockwise), where degrees is a double precision floating point number. You can see the definitions of these commands in `Turtle.java`. **Do NOT use any turtle commands other than `forward` and `turn` in your code for the following methods.** ## Task 3: `drawSquare()` Look at the source code contained in `TurtleSoup.java` in package `turtle`. Your task is to implement `drawSquare(Turtle turtle, int sideLength)`, using the two methods introduced above: `forward()` and `turn()`. Once you've implemented the method, run the `main()` method in `TurtleSoup.java`. The `main()` method in this case simply creates a new turtle, calls your `drawSquare()` method, and instructs the turtle to draw. Run the method by going to *Run → Run As... → Java Application* in Eclipse. A window will pop up, and, once you click the "Run!" button, you should see a square drawn on the canvas. ## Tasks 4—9: polygons and headings **For detailed requirements, read the specifications of each function to be implemented above its function signature in `TurtleSoup.java`. Be careful when dealing with mixed integer and floating point calculations.** You should not change any of the *method signatures* ([what's a signature?](http://docs.oracle.com/javase/tutorial/java/javaOO/methods.html)) below. If you do so, you risk receiving **zero points** on the problem set. ### Drawing polygons + Implement `calculateRegularPolygonAngle()` There's a simple formula for what the inside angles of a regular polygon should be; try to derive it before googling/binging/duckduckgoing. + Run the JUnit tests in `TurtleSoupTest` The method that tests `calculateRegularPolygonAngle()` should now pass and show green instead of red. + Implement `calculatePolygonSidesFromAngle()` This does the inverse of the last function; again, use the simple formula. However, **make sure you correctly round** to the nearest integer. Instead of implementing your own rounding, look at Java's [`java.lang.Math`](java:java/lang/Math) class for the proper function to use. + Implement `drawRegularPolygon()` Use your implementation of `calculateRegularPolygonAngle()`. To test this, change the `main()` method to call `drawRegularPolygon()` and verify that you see what you expect. ### Calculating headings + Implement `calculateHeadingToPoint()` This function calculates the parameter to `turn()` required to get from a current point to a target point, with the current direction as an additional parameter. For example, if the turtle is at (0,1) facing 30 degrees, and must get to (0,0), it must turn an additional 150 degrees, so `calculateHeadingToPoint(30, 0, 1, 0, 0)` would return `150.0`. + Implement `calculateHeadings()` Make sure to use your `calculateHeadingToPoint()` implementation here. For information on how to use Java's `List` interface and classes implementing it, look up [`java.util.List`](java:java/util/List) in the Java library documentation. Note that for a list of _n_ points, you will return _n-1_ heading adjustments; this list of adjustments could be used to guide the turtle to each point in the list. For example, if the input lists consisted of `xCoords=[0,0,1,1]` and `yCoords=[1,0,0,1]` (representing points (0,1), (0,0), (1,0), and (1,1)), the returned list would consist of `[180.0, 270.0, 270.0]`. ## Task 10: Personal art + Implement `drawPersonalArt()` In this function, you have the freedom to draw any piece of art you wish; we will run a poll where your fellow students will rate your art and the winner will win a prize: a gift certificate to Toscanini's. Your picture will be judged both on aesthetics and on the code used to draw it. Try to utilize helper methods, loops, etc. rather than simply listing forward and turn commands. **For `drawPersonalArt` only, you may also use the `color()` method of `Turtle` to change the pen color.** You may only use the provided colors. [Here are some examples](https://www.google.com/search?q=python+turtle+example+images) of the kinds of images you can generate procedurally with turtle graphics, though note that many of them use more commands than what we've provided here. Modify the `main()` method to see the results of your function. ---- ## Submitting **Make sure you commit AND push your work** to your repository on Athena. We will use the state of your repository on Athena as of 10:00pm on the deadline date. When you `git push`, the continuous build system attempts to compile your code and run a **subset** of the autograder tests. You can always review your build results at [didit.csail.mit.edu](https://didit.csail.mit.edu). Didit feedback is provided on a best-effort basis: + There is no guarantee that Didit tests will run within any particular timeframe, or at all. If you push code close to the deadline, the large number of submissions will slow the turnaround time before your code is examined. + You do not need to have a successful Didit run before the deadline in order to be properly graded. + Passing some or all of the **public tests** on Didit is no guarantee that you will pass the full battery of autograding tests --- but failing them is almost sure to mean lost points on the problem set.