CSA Unit 1.8: Documentation with Comments

Lesson Plan

Learning Objectives:

  • Understand the purpose and importance of code documentation
  • Master Javadoc comment syntax and structure
  • Learn to write effective preconditions and postconditions
  • Apply documentation best practices to classes and methods

AP Exam Focus: Required for FRQ responses, demonstrates professional programming practices

We need 2 volunteers to come up to play a game!

Part 1: Why Documentation Matters

Documentation serves multiple audiences:

  • Other developers: How do I use this method? What parameters does it expect?
  • Maintainers: Why was this implemented this way? What are the edge cases?
  • Testers: What should this method do in different scenarios?
  • Your future self: Will you remember your logic in 3 months?

Think of documentation as the user manual for your code.

Types of Java Comments:

  1. Single-line comments: // - Quick notes and explanations
  2. Multi-line comments: /* */ - Longer explanations
  3. Javadoc comments: /** */ - API documentation (our focus today!)

Part 2: Javadoc Comment Structure

Javadoc uses special tags to create comprehensive documentation:

  • @param - Describes a parameter
  • @return - Describes the return value
  • @throws - Describes exceptions that might be thrown

Basic Template:

/**
 * Brief description of what the method does.
 * 
 * More detailed explanation if needed, including algorithm
 * information, usage notes, or important behaviors.
 *
 * @param paramName description of the parameter
 * @return description of what is returned
 */

/**
 * Calculates the final grade for a student based on weighted categories.
 * The grade is computed using the formula: 
 * (homework * 0.3) + (tests * 0.5) + (participation * 0.2)
 *
 * @param homework the average homework score (0.0 to 100.0)
 * @param tests the average test score (0.0 to 100.0)  
 * @param participation the participation score (0.0 to 100.0)
 * @return the weighted final grade as a percentage (0.0 to 100.0)
 */
public double calculateFinalGrade(double homework, double tests, double participation) {
    return homework * 0.3 + tests * 0.5 + participation * 0.2;
}

// Test the method
System.out.println("Final Grade: " + calculateFinalGrade(85.0, 92.0, 88.0));
Final Grade: 89.1

Part 3: Preconditions and Postconditions

Preconditions: What must be true BEFORE the method is called Postconditions: What will be true AFTER the method completes successfully

These create a contract between the method and its callers.

Why They Matter:

  • Clarify responsibilities
  • Define expected behavior
  • Help identify bugs
  • Essential for AP FRQs!

/**
 * Withdraws money from the bank account.
 * 
 * Preconditions: 
 * - amount must be positive
 * - amount must not exceed current balance
 * - account must not be frozen
 * 
 * Postconditions:
 * - balance is reduced by the withdrawal amount
 * - transaction is recorded in account history
 * - returns true if withdrawal successful
 *
 * @param amount the amount to withdraw (must be positive)
 * @return true if withdrawal successful, false otherwise
 */

public boolean withdraw(double amount) {
    // Local variable definitions
    double balance = 500.0;      // example current balance
    boolean isFrozen = false;    // example account state

    // Preconditions: amount must be positive, not exceed balance, and account not frozen
    if (amount <= 0 || amount > balance || isFrozen) {
        return false;  // Precondition not met
    }

    // Perform withdrawal
    balance -= amount;

    // Record transaction (for now, just print it)
    System.out.println("Transaction: Withdraw $" + amount);
    System.out.println("New balance: $" + balance);

    // Postcondition: balance reduced, transaction recorded
    return true;
}
withdraw(100.0);
Transaction: Withdraw $100.0
New balance: $400.0





true

Part 4: Class-Level Documentation

Classes need documentation explaining their overall purpose and usage.

Key Elements:

  • Overall purpose of the class
  • Key responsibilities
  • Usage examples
  • Important design decisions
  • Author and version information

/**
 * Represents a student in the school management system.
 * 
 * This class maintains student information including personal details,
 * academic records, and enrollment status. It provides methods for
 * updating grades, managing course enrollment, and generating reports.
 * 
 * Example usage:
 * <pre>
 * Student alice = new Student("Alice Johnson", 12);
 * alice.enrollInCourse("AP Computer Science");
 * alice.updateGrade("Math", 95.5);
 * System.out.println(alice.getGPA());
 * </pre>
 *
 * @author Your Name
 * @version 1.0
 * @since 2024-01-15
 */
public class Student {
    private String name;
    private int gradeLevel;
    private ArrayList<String> courses;
    private HashMap<String, Double> grades;
    
    // Constructor fix
    public Student(String name, int gradeLevel) {
        this.name = name;
        this.gradeLevel = gradeLevel;
        this.courses = new ArrayList<>();
        this.grades = new HashMap<>();
    }

    // Example methods
    public void enrollInCourse(String course) {
        courses.add(course);
    }

    public void updateGrade(String course, double grade) {
        grades.put(course, grade);
    }

    public double getGPA() {
        if (grades.isEmpty()) return 0.0;
        double sum = 0;
        for (double g : grades.values()) {
            sum += g;
        }
        return sum / grades.size();
    }
}
// Test the Student class
Student alice = new Student("Alice Johnson", 12);
alice.enrollInCourse("AP Computer Science");
alice.updateGrade("Math", 95.5);
System.out.println(alice.getGPA());
95.5

Part 5: Documentation Best Practices

DO:

  1. Be specific and actionable - “sets the student’s GPA to the specified value, rounded to one decimal place”
  2. Include examples for complex methods
  3. Document assumptions and limitations
  4. Update docs when code changes
  5. Focus on WHY, not just WHAT

DON’T:

  1. Over-document obvious code - Simple getters/setters don’t need documentation
  2. Use vague descriptions - “processes the data” tells us nothing
  3. Forget edge cases - What happens with null? Empty arrays?
  4. Let documentation become outdated

// BAD: Over-documentation of obvious code
/**
 * Gets the name.
 * @return the name
 */
public String getName() {
    return name;
}

// GOOD: No documentation needed for simple accessor
public String getName() { 
    return name; 
}

// GOOD: Document complex behavior
/**
 * Updates the student's name with validation and normalization.
 * 
 * Trims whitespace, converts to proper case, and validates that
 * the name contains only letters, spaces, hyphens, and apostrophes.
 *
 * @param name the new name (will be normalized)
 * @throws IllegalArgumentException if name is null, empty, or contains invalid characters
 */
public void setNameWithValidation(String name) {
    if (name == null || name.trim().isEmpty()) {
        throw new IllegalArgumentException("Name cannot be null or empty");
    }
    this.name = normalizeName(name.trim());
}

Part 6: AP Exam Connections

Multiple Choice Tips:

  • Know the difference between //, /* */, and /** */
  • Understand when documentation is most helpful
  • Recognize proper @param and @return usage

FRQ Requirements:

  • Always document complex methods - Shows programming maturity
  • Explain your logic - Helps scorers understand your intent
  • Document non-obvious design decisions
  • Specify parameter constraints

Quick Documentation Checklist:

  • ✓ Complex methods have clear purpose descriptions
  • ✓ Parameter constraints are specified
  • ✓ Return values are explained
  • ✓ Edge cases and error conditions are documented
  • ✓ Examples provided for non-obvious usage

Lesson Hack #1: Fix the Documentation

Task: The following code has poor documentation. Rewrite it with proper Javadoc comments including preconditions and postconditions.

// 
public int doSomething(int[] nums) {
    int result = 0;
    for (int i = 0; i < nums.length; i++) {
        if (nums[i] > 0 && nums[i] % 2 == 0) {
            result += nums[i];
        }
    }
    return result;
}

Your task: Write proper Javadoc documentation for this method in the code cell below.


/**
 * Computes the sum of all strictly positive, even integers contained in the given array.
 *
 * Preconditions:
 *   {@code nums} is not {@code null}.
 *
 * Postconditions:
 *   The return value equals the sum of every element {@code nums[i]} such that
 *       {@code nums[i] > 0} and {@code nums[i] % 2 == 0}.
 *   The input array {@code nums} is not modified.
 *   The return value is non-negative (≥ 0)
 */
public int doSomething(int[] nums) {
    int result = 0;
    for (int i = 0; i < nums.length; i++) {
        if (nums[i] > 0 && nums[i] % 2 == 0) {
            result += nums[i];
        }
    }
    return result;
}

/**
 * Calculates the sum of all positive even integers in the given array.
 * <p>
 * This method loops through each element of {@code nums} and adds it to a running total
 * only if the element is greater than zero and evenly divisible by two.
 * The method then returns the resulting sum.
 * </p>
 *
 * <p><b>Preconditions:</b></p>
 * <ul>
 *   <li>{@code nums} must not be {@code null}.</li>
 *   <li>{@code nums} may contain any integers (positive, negative, or zero).</li>
 * </ul>
 *
 * <p><b>Postconditions:</b></p>
 * <ul>
 *   <li>Returns the sum of all positive even numbers in {@code nums}.</li>
 *   <li>If there are no positive even numbers, returns {@code 0}.</li>
 * </ul>
 *
 * @param nums an array of integers to evaluate
 * @return the sum of all positive even integers in {@code nums}; {@code 0} if none exist
 *
 * <p><b>Example usage:</b></p>
 * <pre>
 * int[] numbers = {1, 2, 3, 4, -6};
 * int result = doSomething(numbers);  // result = 6
 * </pre>
 */
public int doSomething(int[] nums) {
    int result = 0;
    for (int i = 0; i < nums.length; i++) {
        if (nums[i] > 0 && nums[i] % 2 == 0) {
            result += nums[i];
        }
    }
    return result;
}

Popcorn Hack #2: Write Class Documentation

Your Mission: Add Javadoc comments to document this GradeBook class!

What to include:

  • What does this class do? (purpose)
  • What are the main features? (key methods)
  • How would someone use it? (example)
  • Tags: @author, @version, @since ```java // TODO: Add your class-level Javadoc here! // Hint: Start with /** and end with */

public class GradeBook { private HashMap<String, Double> assignments; private HashMap<String, Double> categoryWeights; private double extraCredit;

// TODO: Document each method too!
public void addAssignment(String category, String name, double score) { }

public void setCategoryWeight(String category, double weight) { }

public double calculateFinalGrade() { }

public String generateReport() { } }
import java.util.HashMap;

/**
 * A simple, mutable grade book for tracking assignments, weighting categories,
 * applying extra credit, computing a final grade, and generating a printable report.
 *
 * Purpose
 * Stores assignment scores organized by category (e.g., "Homework", "Quizzes", "Exams") and computes a weighted final grade based on category weights.
 * It also supports an optional extra-credit amount added to the final computed grade.
 *
 * Main Features:
 *  addAssignment(String, String, double) — record an assignment score under a category.
 *  setCategoryWeight(String, double) — define or update a category's weight used for the final grade
 *  calculateFinalGrade()— compute and return the weighted final grade (plus any extra credit).
 *  generateReport() — return a human-readable summary of categories, assignments, weights, and the final grade
 * </ul>
 */
public class GradeBook {
    private HashMap<String, Double> assignments;
    private HashMap<String, Double> categoryWeights;
    private double extraCredit;

    /**
     * Adds or records an assignment score within the specified category.
     * @param category the category label (e.g., "Homework", "Exams")
     * @param name the assignment identifier (e.g., "HW1", "Final")
     * @param score the assignment score (0–100 scale recommended)
     * @throws IllegalArgumentException if {@code category} or {@code name} is null/blank,
     *         or if {@code score} is not finite or outside an accepted range (if enforced)
     */
    public void addAssignment(String category, String name, double score) { }

    /**
     * Sets or updates the weight associated with a grading category.
     * @param category the category to define or update
     * @param weight the category weight (e.g., 0.25 for 25%)
     * @throws IllegalArgumentException if {@code category} is null/blank or if {@code weight} is negative or not finite
     */
    public void setCategoryWeight(String category, double weight) { }

    /**
     * Calculates the final grade using the recorded assignments and category weights,
     * plus any extra credit.
     * @return the weighted final grade including extra credit
     */
    public double calculateFinalGrade() { return 0.0; }

    /**
     * Generates a human-readable report summarizing categories, weights,
     * assignments, and the computed final grade.
     * @return a printable multi-line summary of the grade book state
     */
    public String generateReport() { return ""; }
}

Check your answer below!

/**
 * Manages student grades and calculates final grades based on weighted categories.
 * 
 * This class allows teachers to track assignments across different categories
 * (like homework, tests, projects) and calculate final grades using custom weights.
 * 
 * Key Features:
 * - Store assignments by category
 * - Apply custom weights to each category
 * - Track extra credit points
 * - Generate grade reports
 * 
 * Usage Example:
 * GradeBook myGrades = new GradeBook();
 * myGrades.setCategoryWeight("Homework", 0.30);
 * myGrades.setCategoryWeight("Tests", 0.70);
 * myGrades.addAssignment("Homework", "HW1", 95.0);
 * double finalGrade = myGrades.calculateFinalGrade();
 * 
 * @author Your Name
 * @version 1.0
 * @since 2025-10-06
 */
public class GradeBook {
    private HashMap<String, Double> assignments;
    private HashMap<String, Double> categoryWeights;
    private double extraCredit;
    
    /**
     * Adds an assignment score to a specific category.
     * 
     * @param category the category name (e.g., "Homework", "Tests")
     * @param name the assignment name
     * @param score the score earned (0-100)
     */
    public void addAssignment(String category, String name, double score) { }
    
    /**
     * Sets the weight for a grade category.
     * 
     * @param category the category name
     * @param weight the weight as a decimal (e.g., 0.30 for 30%)
     */
    public void setCategoryWeight(String category, double weight) { }
    
    /**
     * Calculates the final weighted grade including extra credit.
     * 
     * @return the final grade as a percentage
     */
    public double calculateFinalGrade() { }
    
    /**
     * Generates a formatted report of all grades and categories.
     * 
     * @return a String containing the grade report
     */
    public String generateReport() { }
}

Homework Assignment

Part 1: Documentation Analysis

Submission: https://docs.google.com/forms/d/e/1FAIpQLSepOCmW6KeE7jw4f80JO4Kad5YWeDUHKTpnNxnCPTtj9WEAsw/viewform?usp=header Rewrite the poorly written code. Write them with proper Javadoc comments.

  1. The original code:
/*
public class stuff{
public static void main(String args[]){
int x=5;
int y=10;
int z=add(x,y);
System.out.println("ans is "+z);
}

static int add(int a,int b){
return a+b;
}
}
 */

Submit:

  1. Your improved version
  2. A brief explanation of what you improved
/**
 * Small utility application that demonstrates adding two integers
 * and printing the result to standard output.
 *
 * <p>Run without arguments to use the built-in example values (5 and 10),
 * or pass two integers on the command line.</p>
 *
 */
public class AddClass {

    /**
     * Entry point. Adds two integers and prints the sum.
     *
     * Preconditions:
     *   If arguments are provided, {@code args.length == 2} and both args parse as {@code int}.
     *
     * Postconditions:
     *   Writes a single line to standard output showing the operands and their sum.
     */
    public static void main(String[] args) {
        int left;
        int right;

        if (args.length == 2) {
            left = Integer.parseInt(args[0]);
            right = Integer.parseInt(args[1]);
        } else {
            left = 5;
            right = 10;
        }

        int sum = add(left, right);
        System.out.printf("Sum of %d and %d is %d%n", left, right, sum);
    }

    /**
     * Returns the sum of two 32-bit signed integers.
     *
     * Preconditions:
     *   Inputs {@code a} and {@code b} are valid {@code int} values.
     *
     * Postconditions:
     *   Return value equals {@code a + b} using Java {@code int} arithmetic (wraps on overflow per the Java Language Specification).
     *   Does not modify any external state
     *
     * @param a the first addend
     * @param b the second addend
     * @return the sum {@code a + b}
     */
    public static int add(int a, int b) {
        return a + b;
    }
}

What I improved:

  • Clear class name
  • Consistent formatting
  • Added Javadoc for classes main and add

Part 2:

Problem 1: Document a Complex Method Write complete Javadoc documentation for this method:

public boolean enrollStudent(String studentId, String courseCode, int semester) { Student student = findStudentById(studentId); if (student == null) return false;

Course course = findCourseByCode(courseCode);
if (course == null) return false;

if (course.isFull()) return false;
if (student.hasScheduleConflict(course)) return false;
if (!student.hasPrerequisites(course)) return false;
if (student.getCreditHours() + course.getCreditHours() > 18) return false;

student.addCourse(course);
course.addStudent(student);
recordEnrollmentTransaction(studentId, courseCode, semester);
return true; }

MY WORK:


/**
 * Enrolls a student in a course for the given semester.
 *
 * Preconditions:
 * - studentId and courseCode refer to existing records
 * - Enrollment for the given semester is allowed
 *
 * Validation (in order):
 * 1) Student exists
 * 2) Course exists
 * 3) Course not full
 * 4) No schedule conflict
 * 5) Prerequisites satisfied
 * 6) Adding credits does not exceed 18
 *
 * Postconditions:
 * - On true: student schedule updated, course roster updated, enrollment recorded
 * - On false: no changes applied
 *
 * @param studentId unique student identifier
 * @param courseCode course code to enroll
 * @param semester numeric term identifier
 * @return true if enrollment succeeds; false otherwise
 */
public boolean enrollStudent(String studentId, String courseCode, int semester) {
    Student student = findStudentById(studentId);
    if (student == null) return false;

    Course course = findCourseByCode(courseCode);
    if (course == null) return false;

    if (course.isFull()) return false;
    if (student.hasScheduleConflict(course)) return false;
    if (!student.hasPrerequisites(course)) return false;
    if (student.getCreditHours() + course.getCreditHours() > 18) return false;

    student.addCourse(course);
    course.addStudent(student);
    recordEnrollmentTransaction(studentId, courseCode, semester);
    return true;
}

Part 3: Reflection Questions

  1. Why is documentation more important in team projects than solo projects?
  2. Give an example of when a method SHOULD be documented and when it SHOULD NOT.

MY WORK:

Documentation is more important in team projects than solo projects because it helps foster shared understanding across many people who may not understand your code. Furthermore, it leads to faster onboarding and continuity when teammates working on the project are shifted in roles.

A method should be documented when it consists of complex logic or is a custom method that is not self-explanatory. Methods should NOT be documented when they are commonly used or trivial, or when the need for documentation can be fulfilled by simply changing the name of the method.

Submit: A Jupyter notebook or Java file with all three parts completed.


Key Takeaways

  1. Documentation is communication - Write for others (and your future self)
  2. Javadoc format matters - Use /** */ with proper tags
  3. Preconditions and postconditions create contracts - Essential for reliable code
  4. Balance is key - Don’t over-document obvious code, but thoroughly document complex logic
  5. Keep it updated - Outdated documentation is worse than no documentation
  6. AP Exam success - Good documentation demonstrates programming maturity on FRQs

Remember:

“Code tells you HOW, documentation tells you WHY”

The collaborative mindset: Write documentation that you would want to find when using someone else’s code. Be specific, be helpful, and anticipate questions.


Additional Resources

Challenge Problems (Extra Credit)

Challenge 1: Document a Recursive Method

Write complete documentation for a recursive method including base case, recursive case, and complexity analysis.

Challenge 2: Team Documentation Standard

Create a documentation style guide for a team project. Include:

  • When to document (and when not to)
  • Required tags for different method types
  • Example templates
  • Common mistakes to avoid

Challenge 3: Documentation Detective

Find a poorly documented open-source project. Write improved documentation for one class and submit a comparison showing before/after.