Skip to the content.

Documentation with Comments

CSA Unit 1.8: Documentation with Comments\n”,

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());
}
|       this.name = normalizeName(name.trim());

non-static variable this cannot be referenced from a static context



|       this.name = normalizeName(name.trim());

cannot find symbol

  symbol: variable name



|       this.name = normalizeName(name.trim());

cannot find symbol

  symbol:   method normalizeName(java.lang.String)

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.

// Does stuff with numbers
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 total sum of all positive even integers in the specified array.
 *
 * <p>This method scans through each element in the array {@code nums}.
 * If an element is both greater than zero and divisible by two, it is
 * added to a cumulative sum. The method then returns the final sum.</p>
 *
 * <p>This operation does not modify the input array.</p>
 *
 * @param nums an array of integers to analyze
 * @return the sum of all positive even values found in {@code nums};
 *         returns 0 if no such elements exist
 *
 * @precondition
 * {@code nums} must not be {@code null}.
 *
 * @postcondition
 * The array {@code nums} remains unchanged after execution.
 * The return value equals the sum of all positive even numbers within {@code nums}.
 */
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() { } }

Check your answer below!

/**
 * The {@code GradeBook} class manages a student's assignments, category weights,
 * and calculates a final grade based on weighted categories.
 * 
 * <p>This class allows users to:
 * <ul>
 *   <li>Add assignments with scores organized by category (e.g., Homework, Tests, Projects)</li>
 *   <li>Assign weights to categories to reflect their importance in the overall grade</li>
 *   <li>Calculate the final weighted grade</li>
 *   <li>Generate a report summarizing all assignments and the student's performance</li>
 * </ul>
 * 
 * <p><b>Example Usage:</b></p>
 * <pre>{@code
 * GradeBook gb = new GradeBook();
 * gb.setCategoryWeight("Homework", 0.4);
 * gb.setCategoryWeight("Tests", 0.6);
 * gb.addAssignment("Homework", "HW1", 95);
 * gb.addAssignment("Tests", "Unit Test 1", 88);
 * double finalGrade = gb.calculateFinalGrade();
 * System.out.println(gb.generateReport());
 * }</pre>
 * 
 * @author Rohan
 * @version 1.0
 * @since 2025-10-13
 */
public class GradeBook {
    private HashMap<String, Double> assignments;
    private HashMap<String, Double> categoryWeights;
    private double extraCredit;

    /**
     * Adds a new assignment and its score under the specified category.
     *
     * @param category the name of the category (e.g., "Homework", "Tests")
     * @param name the name of the assignment
     * @param score the score earned on the assignment (0–100)
     *
     * @precondition {@code category} and {@code name} are not null, and {@code score} ≥ 0
     * @postcondition The assignment is stored in the {@code assignments} list under its category
     */
    public void addAssignment(String category, String name, double score) { }

    /**
     * Sets the weight of a specific category used for calculating the final grade.
     *
     * @param category the name of the category (e.g., "Homework", "Projects")
     * @param weight the weight of the category (e.g., 0.3 for 30%)
     *
     * @precondition {@code weight} must be between 0.0 and 1.0
     * @postcondition The category and its weight are recorded in {@code categoryWeights}
     */
    public void setCategoryWeight(String category, double weight) { }

    /**
     * Calculates and returns the student's final weighted grade.
     *
     * @return the overall grade as a percentage (0–100)
     *
     * @precondition Categories and assignments must have been added
     * @postcondition Returns the weighted average grade, including any extra credit applied
     */
    public double calculateFinalGrade() { return 0.0; }

    /**
     * Generates a formatted report of all assignments, category weights, and the final grade.
     *
     * @return a String summary of the student's grade information
     *
     * @precondition At least one assignment has been added
     * @postcondition Returns a non-null report string summarizing student performance
     */
    public String generateReport() { return ""; }
}

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:
/**
 * The {@code Stuff} class demonstrates a simple addition operation.
 * <p>
 * It contains a method to add two integers and prints the result.
 * </p>
 * 
 * <p><b>Example:</b></p>
 * <pre>{@code
 * int result = Stuff.add(5, 10); // result = 15
 * }</pre>
 * 
 * @author Rohan
 * @version 1.0
 * @since 2025-10-13
 */
public class Stuff {

    /**
     * The main method serves as the entry point of the program.
     * It demonstrates using the {@link #add(int, int)} method
     * to add two numbers and print the result.
     *
     * @param args command-line arguments (not used)
     * @precondition none
     * @postcondition prints the sum of two integers to the console
     */
    public static void main(String[] args) {
        int x = 5;
        int y = 10;
        int z = add(x, y);
        System.out.println("Answer is " + z);
    }

    /**
     * Adds two integers and returns the result.
     *
     * @param a the first integer
     * @param b the second integer
     * @return the sum of {@code a} and {@code b}
     * @precondition none
     * @postcondition the return value equals the sum of the input integers
     */
    static int add(int a, int b) {
        return a + b;
    }
}

// I improved the code by following Java naming conventions, renaming the class to Stuff and formatting it with proper indentation and spacing for readability. I added Javadoc comments for the class and methods, including descriptions, parameters, return values, and preconditions/postconditions, so the purpose and behavior are clear. The print statement was made more descriptive, and variable spacing was standardized. Overall, these changes make the code more professional, readable, and easier to maintain.

Submit:

  1. Your improved version
  2. A brief explanation of what you improved

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; }

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.

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


/**
 * Attempts to enroll a student in a specified course for a given semester.
 * 
 * <p>This method verifies multiple conditions before enrollment:
 * it ensures that the student and course exist, the course is not full,
 * the student’s schedule does not conflict, prerequisites are met, 
 * and total credit hours do not exceed the allowed limit (18).</p>
 * 
 * <p>If all checks pass, the method enrolls the student in the course,
 * updates both the student and course records, and logs the transaction.</p>
 *
 * @param studentId the unique identifier of the student to enroll
 * @param courseCode the code of the course to enroll in
 * @param semester the semester number or ID for which enrollment is requested
 * @return {@code true} if the student is successfully enrolled; 
 *         {@code false} if any condition prevents enrollment
 *
 * @precondition 
 * - {@code studentId} and {@code courseCode} are valid identifiers  
 * - The {@code semester} is within the valid academic schedule  
 * - Both {@code findStudentById()} and {@code findCourseByCode()} return valid objects
 *
 * @postcondition 
 * - If enrollment is successful, the student and course records are updated,
 *   and a transaction is recorded.  
 * - If enrollment fails, no data is modified.
 */
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;
}

// 1. Why is documentation more important in team projects than solo projects?
// Documentation is crucial in team projects because multiple developers need to understand, maintain, and extend each other’s code. Without clear documentation, team members waste time deciphering logic or risk introducing bugs when modifying code. It ensures consistency, transparency, and efficient collaboration throughout the project.
// 2. Give an example of when a method SHOULD be documented and when it SHOULD NOT.
// A method should be documented when it performs a non-trivial operation, involves multiple steps, or has specific preconditions or side effects (e.g., a database update method).
// A method does not need documentation when it’s very simple and self-explanatory, such as a basic getter or setter (getName() or setAge()).

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.


/**
 * Computes the factorial of a given non-negative integer recursively.
 *
 * <p><b>Base Case:</b> When n == 0 or n == 1, returns 1.</p>
 * <p><b>Recursive Case:</b> Returns n multiplied by factorial(n - 1).</p>
 *
 * <p><b>Time Complexity:</b> O(n), since one recursive call is made per decrement of n.</p>
 * <p><b>Space Complexity:</b> O(n), due to the call stack depth.</p>
 *
 * @param n The non-negative integer for which the factorial is calculated
 * @return The factorial of n
 * @throws IllegalArgumentException if n is negative
 */
public static long factorial(int n) {
    if (n < 0) {
        throw new IllegalArgumentException("Input must be non-negative");
    }
    if (n == 0 || n == 1) {
        return 1;
    }
    return n * factorial(n - 1);
}

Team Documentation Style Guide
When to Document:
Document all public methods, constructors, and complex private methods.
Do not over-document simple getters/setters unless they include logic.
Required Tags:
@param for each parameter
@return for return values
@throws for exceptions
@precondition and @postcondition for complex logic
@author, @version, @since for class-level Javadoc
Example Template:
/**
 * Brief description of what the method does.
 *
 * @param paramName Description of the parameter
 * @return Description of the return value
 * @throws ExceptionType Description of when exception occurs
 */
// handles users
public void addUser(User u) {
    users.add(u);
}
/**
 * Adds a new user to the system’s user list.
 *
 * <p><b>Preconditions:</b> The user object must not be null.</p>
 * <p><b>Postconditions:</b> The user is stored in the system for future operations.</p>
 *
 * @param u The User object to be added
 * @throws IllegalArgumentException if the user object is null
 */
public void addUser(User u) {
    if (u == null) throw new IllegalArgumentException("User cannot be null");
    users.add(u);
}