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) {
    if (amount <= 0 || amount > balance || isFrozen) {
        return false;  // Precondition not met
    }
    
    balance -= amount;
    recordTransaction("Withdrawal", amount);
    return true;  // Postcondition satisfied
}

🏛️ 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 and methods...
}

💡 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.

/** Sorts through an array of numbers and returns the sum of the positive even integers
 * 
 * Goes through @param nums and adds each number that is greater than 0 and evenly divisible by 2 to a total
 * Returns that total at the end of the method
 * 
 * Preconditions:
 * - @param nums cannot be null
 * 
 * Postconditions:
 * - the sum of the positive numbers is returned 
 * 
 * @param nums is the array of numbers that is sorted through
 * @return sum of positive numbers
 * 
 * Example Usage:
 * int[] nums = {1, 4, -7, 8, 2};
 * int sum = doSomething(nums); // sum = 15
 * System.out.println(sum); // outputs 15
 * 
 */
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.


/**
 * 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 */

/**

  • Manages each grade a student gets
  • Calculates final grade based on category weightage
  • Allows one to track their grades throughout a schoolyear
  • Key methods:
    • adds an assignment and its grade into its category
    • changes the weightage of a category
    • calculates the final grade based on each grade while taking into account the category weightage
    • generates a report of all the grades for a student
  • Usage example:
  • GradeBook studentGrades = new GradeBook();
  • studentGrades.setCategoryWeight(“Homework”, 0.2);
  • studentGrades.setCategoryWeight(“Tests”, 0.3);
  • studentGrades.addAssignment(“Tests”, “Test 3: Newton’s Laws”, 120);
  • double finalGrade = studnetGrades.calculateFinalGrade()’
  • @author Arnav Mittal
  • @version 1.0
  • @since 2025-10-13 */ public class GradeBook { private HashMap<String, Double> assignments; private HashMap<String, Double> categoryWeights; private double extraCredit;

    // TODO: Document each method too! /**

    • Adds an assignment to a category
    • @param category selects the category to enter your assignment into
    • @param name is the name of your assignment
    • @param score is the grade you recieved on the assignment out of 100 */ public void addAssignment(String category, String name, double score) { }

    /**

    • Changes the weightage of a category
    • @param category selects the category to edit
    • @param weight is the weightage to give to the category */ public void setCategoryWeight(String category, double weight) { }

    /**

    • Calculates a student’s overall grade based on assignments in their categories */ public double calculateFinalGrade() { }

    /**

    • Generates a report of a student’s grades */ public String generateReport() { } }

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

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;
}
}
 */
/**
 * Allows you to find the sum of predefined variables as well as the sum of user-entered variables
 * 
 * Key features:
 * - initializes integers and prints their sum
 * - has a {@code add} method that can sum user-inputted integers
 * 
 * Usage example:
 * stuff.main(new String[]{});
 * int result = stuff.add(5, 12); // result = 17
 * System.out.prinln(result); // outputs 17
 */
public class stuff {
    /**
     * Initalizes two variables and outputs their sum
     */
    public static void main(String args[]) {
        int x = 5;
        int y = 10;
        int z = add(x, y);
        System.out.println("ans is " + z)
    }

    /**
     * Gets two variables through user input adds them
     * 
     * @param a is an integer added
     * @param b is an integer added
     * @return a + b 
     */
    static int add(int a, int b) {
        return a + b;
    }
}

I added a description of the overall purpose of the class and each of its methods as well as example usage of the class and described parameters and returns whenever necessary.

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.


/**
 * Tries to add a student to a selected course in a specific sememster based on their studentId
 * 
 * Preconditions:
 * - studentId is valid
 * - courseCode is valid
 * - course is not full
 * - no schedule conflict
 * - prerequisites are filled
 * 
 * Postconditions:
 * - student is added to course for certain semester
 * 
 * Example usage:
 * - enrollStudent("1968012, "18869", 2") 
 * 
 * @param studentId is the id of the student given by the school
 * @param courseCode is the identifying number of the course
 * @param semester is the semester in which the student wants to join the calss
 * @return true if student is successfully added 
 */
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

  1. Documentation is far more important in team projects than solo because in a solo project you will likely know what your code does or at least what you intend for it to do, while in a team project others may not know what a variable or method is used for, for example, and then they will need to refer to your documentation.
  2. An example where you shouldn’t document is when code is extremely simple with detailed variable names to the point where doing documentation would be like writing the method. An example where you should document is when a code is not immediately understandable or contains weird variable names or something of that sort, where people may need extra help understanding what each part does.

🎯 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.


End of Lesson - Happy Documenting! 📚✨