Skip to main content
Logo image

Section 13.2 Documentation and invariants

Another two important, and related aspects of program design are internal documentation of the program with comments and especially documenting the invariants that the program relies on.

Subsection 13.2.1 Comments

We learned about the syntax of comments in Java way back in Sectionย 1.1ย What is programming? What is Java?. Commentsโ€”text included in the source code of a program meant for humans to read and ignored by the compilerโ€”can help make code more readable and maintainable.
In real-world software development, most code is worked on by teams of programmers over the course of years. While the code itself is unambigious about what it does, comments can be essential for explaining why it written the way it is.
Even when we write programs by ourselves, it can be easy to forget all the details of why we wrote the code the way we did or assumptions that we made about how the pieces fit gother. A few well-placed comments can help us remember those things when we come back to a section of code after a few months or a few years. Good comments are a gift to other programmers who might have to understand and modify the code including our future selves.
There are three types of comments in Java:
  1. Single line comments, marked with //
  2. Multiline comments, enclosed in /* and */ markers.
  3. Java documentation, or Javadoc, comments which are multiline commens where the first marker is /**
Single line comments are typically used within the body of methods to explain details of how the code works. Many coders also use multiple lines each starting with // to write multiline comments. Also // can be put at the beginning of a line of code to โ€œcomment it outโ€, usually as a temporary debugging technique so see how the program works if certain code isnโ€™t there without actually deleting it.
Multi-line comments marked with /* and */ are typically used for higher-level comments at the top level of classes. And in Java the most important for of these comments are the Javadoc variation which start with /** rather than /*. These comments are placed before instance and class variables, methods, constructors, and classes to document their purpose. A tool called javadoc that comes with the Java JDK can pull out all of these comments to make documentation of a class as a web page.
This is the tool used to generate the official documentation of Javaโ€™s built in classes, for example for the String class. While you donโ€™t need to know about the details of how to format Javadoc comments for the AP Exam, it is useful to get in the habit of adding at least brief Javadoc-style comments before each class you write and each public method even if you donโ€™t plan to generate the web-based documentation.
Hereโ€™s an example of how Javadoc comments and a single line comment might be used.
/**
 * A scorekeeper that can track the maximum score achieved.
 *
 * @author My Name
 * @since Date
 * @version 0.0.1
 */
public class Scorekeeper()
{
   // The maximum score obtained.
   private int max = 0;

   /**
    * Record a new score, updating the maximum score if new score is greater.
    *
    * @param score the new score. Must be positive.
    */
   public recordScore(int score) {
     max = Math.max(max, score);
   }

   /**
    * Return the current maximum score.
    *
    * @return the current maximum score.
    */
   public int getMaximum() {
     return max;
   }

   /**
    * Priints the maximum score achieved.
    */
   public printMaxScore() {
      System.out.println(max);
   }
}
The example above shows some special tags that you can use in Javadoc comments. They are mostly important if you actually want to generate online documentation for your classes as the Javadoc tool will use them to extract the different parts of the Javadoc comment and put them in the right place in the generated documentation. If you are just writing Javadocs to be read in the code itโ€™s less important to use thes tags. Some of the main Javadoc tags are:

Activity 13.2.1.

Activity 13.2.2.

The code below will read in two numbers entered by the user (here in the box below the code) and multiply them. Add a multiline comment above the public class to describe what the class does. Then think about whether there are any parts of the code that need short, single-line comments to explain what they do? Add any you think are necessary. Then talk compare your comments with your neighbor? Who wrote more? Is more always better?

Subsection 13.2.2 Invariants

One of the most important things to think about as we write programs and often to document in comments are the invariants of our program. Invariant means โ€œconstant or unchangingโ€ and in a program invariants are the things that should always be true. If something we think is an invariant is ever not true then we have a bug in our program and we can focus on tracking down how that invariant was violated. But the rest of the time we can write code assuming our invariants hold which reduces the number of things we have to worry about.
Some invariants are enforced for us by Java. When we declare a variable to be an int we can rely on the fact that that the value of that variable will always be an integer. And when we write a method that takes two arguments it will always be true that any code that calls that method will have to provide two arguments of the right types because otherwise the code wouldnโ€™t compile.
But there are also things that we might want to always be true that the compiler canโ€™t guarantee for us. Those are the things we normally think of as invariants.
One of the two most important kinds of invariants are related to methods and are called a methodโ€™s preconditions and postconditions. A precondition is something that must be true for the methodโ€™s code to work.
For instance the version the String classโ€™s substring method that takes a single int argument has a further precondition that the argument be in the bounds of the string index (not negative and not larger than the length of the string. If called with an invalid argument it throws an IndexOutOfBoundsException and crashes your program rather than returning a substring.
The beauty of establishing a precondition for a method (even just in your mind) is that it tells you where the bug is if it is violated: it has to be in the code that is calling the method. By establishing a precondition you are saying, this method doesnโ€™t have to work at all unless this thing is true.
A methodโ€™s postcondition is the flip side of its precondition; it is the thing, or things, that must be true after the method calls. In other words, the postconditinos of a method describe what the method promises to do. Those might be facts about the value returned by the method or facts about any side effects the method has.
Unlike a precondition which frees a method from having to deal with certain situations, a postcondition puts responsibility on the method. If a method is called with its preconditions met and fails to meet its postconditions, then the method is buggy and we know what code we need to debug.
Preconditions and postconditions are related to comments because they are some of the most important things to document about our code. We donโ€™t need to document things like variable types that are enforced by the compiler but the interesting preconditions and postconditions of our methods are things that the compiler canโ€™t enforce but our code implicitly relies on so its important to make them explicit in comments.

Activity 13.2.3.

Here is an example of how preconditions and postconditions can be document in a Javadoc comment from the Turtle code that we use for animating turtle drawings. The Turtle forward methodโ€™s precondition is that the amount of pixels forward should be between 0 and the width and height of the world. If it receives value out of this range, it sets pixels to the closest legal values that it can so that the turtle appears just at the edge of the world.
/**
 * Method to move the turtle forward the given number of pixels
 * @param pixels the number of pixels to walk forward in the heading direction
 * Preconditions: parameters pixel is between 0 and
 *    the width and height of the world.
 * Postconditions: the turtle is moved forward by pixels amount
 *   but stays within the width and height of the world.
 */
public void forward(int pixels) {
  /* code to move the turtle forward */
}
Try to break the preconditions of the Turtle forward method below. Try to make the turtle go completely off screen by changing the number of pixels given to the forward method. What happens if you put in negative numbers? (If the code below does not work for you, you can copy the code into this replit.com link (refresh page after forking and if it gets stuck) or download the files here to use in your own IDE.)

Subsection 13.2.3 Software validity and use-case diagrams

Preconditions and postconditions are covered on the AP CSA exam. Software validity, testing, and use-case diagrams which are discussed in this subsection are not covered on the AP CSA exam, but they are described here because they use preconditions and postconditions and are used by professional programmers.
Determining the preconditions and postconditions help us to test our code and determine the validity of our software. Software validity tests whether the software does what it is supposed to do before it is released. This is sometimes very important. For example, if the code is part of a satellite going to outer space or is going to be used in a medical device, we want to test it thoroughly and make sure it works and is valid before it is put into use.
Good software testers actually try to break the code! They try all kinds of input to see what the software will do because you never know what users will try or what conditions there will be. So, always think what the preconditions of your code are and see what happens when you break them, and then see if you can protect or warn against that.
Preconditions and postconditions can also help us to design better software systems. Software designers often first draw a high-level use-case diagram of a system that shows the different ways that a user might interact with a system before they build it. Here is a simple use-case diagram of a restaurant system. It shows two actors in the system: the customer and the staff at the restaurant, and three use-cases in circles. A use-case is a particular user interaction or situation in the system or software, and they often become methods in the program.
Use Case Diagram
Figure 13.2.1. Use-case diagram of a restaurant system
After drawing a Use-Case Diagram, designers write down the preconditions and the postconditions for each use-case. Often the successful postcondition for one use-case becomes the preconditions for the next use- case. For example, for the โ€œOrder Foodโ€ and โ€œEat Foodโ€ Use Cases:
  • Preconditions for โ€œOrder Foodโ€: Customer enters restaurant. Staff is ready to take the order.
  • Postconditions for โ€œOrder Foodโ€: Customer orders the food. Staff takes the order.
  • Preconditions for โ€œEat Foodโ€: Customer has already ordered food. Staff has delivered food.
  • Postcondition for โ€œEat Foodโ€: Customer eats the food.

Activity 13.2.4.

What are the preconditions and postconditions of the use-case โ€œPay for foodโ€? Remember that these are often related to the other use-case conditions โ€œorder foodโ€ and โ€œeat foodโ€.

Subsection 13.2.4 Agile software development

There are many different models for software development. The term waterfall model was first used in the 1970s to critique existing step-by-step models where each phase such as requirements gathering, coding, and testing is finished before the next phase begins. Such models despite their many flaws were nontheless was adopted by some large organizations such as the U.S. Department of Defense. But these days many developers use some flavor of an Agile development model that involves iterative, incremental development where teams works in short two to three week sprints to completely develop, test, and release a component of the project to the customer for feedback. It is very adaptable as project requirements change because of early testing, immediate customer feedback and collaboration.
Figure 13.2.2. Waterfall vs agile models
One very popular type of agile development is called Scrum. The following short video describes software development with Scrum.
Try the Wake Up In the Morning Game in groups to practice the iterative and incremental agile development process.

Subsection 13.2.5 Coding Challenge: Preconditions in Algorithms

Working in pairs or groups, come up with four steps that a user must do to purchase a product, for example a book on Java, in an online store, and list the preconditions and postconditions for each step. You could pretend to buy something online to come up with the steps. (You could use an online drawing tool like Creately.com (choose Use-Case Diagrams) to draw a Use-Case diagram for the Online Store System, but it is not required). Donโ€™t forget to list the preconditions and postconditions for each step. You can type in your answer below.

Project 13.2.5.

Write down four steps that a user must take to purchase a product, for example a book on Java, in an online store, and list the preconditions and postconditions for each step.

Subsection 13.2.6 Summary

  • (AP 1.8.A.1) Comments are written for both the original programmer and other programmers to understand the code and its functionality, but are ignored by the compiler and are not executed when the program is run.
  • (AP 1.8.A.1) Three types of comments in Java include /* */, which generates a block of comments, //, which generates a comment on one line, and /** */, which are Javadoc comments and are used to create API documentation.
  • (AP 1.8.A.2) A precondition is a condition that must be true just prior to the execution of a section of program code in order for the method to behave as expected. There is no expectation that the method will check to ensure preconditions are satisfied.
  • (AP 1.8.A.3) A postcondition is a condition that must always be true after the execution of a section of program code. Postconditions describe the outcome of the execution in terms of what is being returned or the current value of the attributes of an object.

Subsection 13.2.7 AP Practice

Activity 13.2.6.

Consider the following method.
/** method to add extra-credit to the score **/
public double computeScore(double score, double extraCredit) {
    double totalScore = score + extraCredit;
    return totalScore;
}
Which of the following preconditions are reasonable for the computeScore method?
  • /* Precondition: score <= 0 */
  • No, score should not be negative. Preconditions do not usually enforce negative values.
  • /* Precondition: score >= 0 */
  • Correct. It is reasonable that the score should be a positive value.
  • /* Precondition: extraCredit >= 0 */
  • Correct. It is reasonable that the extraCredit should be a positive value.
  • /* Precondition: extraCredit <= 0 */
  • No, extraCredit should not be negative. Preconditions do not usually enforce negative values.
  • /* Precondition: computeScore >= 0 */
  • computeScore is a method, not a variable. Preconditions are usually for variables.
You have attempted of activities on this page.