Teacher Guide: Methods & Modularization

Student page: Methods & Modularization IB Syllabus: B2.3.4 Estimated periods: 2 (70-90 min each) Prerequisites: Selection, Iteration, 1D Arrays

Contents

  1. Lesson Plans
  2. Differentiation
  3. Integration Notes
  4. Answer Keys
  5. GitHub Classroom Answer Key

Lesson Plans

Period 1: Method Basics + Refactoring Activity

Phase Time Activity Student Page Section
Hook 5 min Show monolithic MiniProj/GradeArray code. “Would you debug this?”
Objectives 2 min Learning objectives slide
Teach 10 min What is a method, anatomy, parameter vs argument, void vs return, boolean return Key Concepts, Worked Examples 1-2, 4
Quick Check 5 min Students open EduCS.me, answer Q1-Q5 Quick Check
Teach 5 min Methods calling methods (printReport example) Worked Example 3
Hands-on 15 min Refactor RefactorGrades.java in Codespaces – extract 6 methods Practice Exercise 8 / GH Classroom
Teach 7 min Scope: local vs global, pass-by-value Scope section
Quick Check 5 min Trace exercise + output predictions on EduCS.me Trace Exercise, Output Prediction
Discussion 6 min Benefits of modularization – students share what they experienced Why Modularize
Practice 10 min Core exercises 1-4 on EduCS.me (or start in GH Classroom) Practice Exercises

Teaching notes:

  • The hook is critical. Show familiar code they wrote (MiniProj). Let them feel the pain of a 120-line main before showing the solution.
  • Introduce parameter vs argument terminology explicitly – this appears on IB exams.
  • During the refactoring activity, students will naturally encounter scope errors when they move code into methods and variables are no longer visible. Use this as the teachable moment for scope instead of teaching it abstractly first.
  • The printReport example shows methods calling methods – emphasize that main (or any orchestrating method) should read like a high-level summary.
  • Pass-by-value: the output prediction exercise (change: 15, main: 5) is the key demonstration. Ask students to predict BEFORE revealing.

Period 2: Practice + GH Classroom Homework

Phase Time Activity Student Page Section
Warm-up 10 min Review: “Name 3 benefits of modularization” + quick scope question
Practice 30 min Extension exercises 5-7 (temperature converter, array statistics, password checker) Practice Exercises
Challenge 15 min Exercise 9: Mini calculator (methods + loop + String comparison) Practice Exercises
Wrap-up 15 min Review GH Classroom submission process. Show test results. Assign deadline. GitHub Classroom

Teaching notes:

  • Extension exercise 6 (array statistics) is the most important – it combines void methods, return methods, and array parameters in one program.
  • Exercise 7 (password checker) requires iterating through characters with charAt() – connect back to Strings topic.
  • Exercise 9 (mini calculator) requires .equals() for string comparison in the quit condition – reinforce this.
  • Students who finish early can start StringHelper.java or MathUtils.java from the GH Classroom template.

Differentiation

Supporting weaker students:

Strategy When to use Example
Start with void only Can’t grasp return values yet Write printSeparator() and greet(name) first – no return
Method header template Can’t write signatures Give: public static ___ methodName(___) { } with blanks to fill
Pair refactoring Stuck on RefactorGrades Pair with a stronger student; one drives, one navigates
Reduce to Core 1-3 Overwhelmed printSeparator, sum, isEven – simplest patterns

Extending stronger students:

Strategy When to use Example
MathUtils.java Finishes Extension early isPrime, gcd, countPrimes (methods calling methods)
StringHelper.java Wants String practice isPalindrome, toTitleCase, summarize (calls other methods)
Refactor their own code After exercise 8 “Go back to any previous assignment and extract methods”
Discuss method design After Challenge “When should you use void vs return? When should a method do one thing vs two?”

Integration Notes

Connects backward to:

  • Selection (B2.3.2): conditions inside methods (isValidGrade, isEven)
  • Iteration (B2.3.3): loops inside methods (calculateAverage, findMax)
  • 1D Arrays (B2.2.2): arrays as method parameters (all RefactorGrades methods)

Connects forward to:

  • OOP (B3.1): methods become instance methods instead of static; this keyword replaces parameter passing
  • Searching/Sorting (B2.4): linear search, binary search, bubble sort, selection sort are all methods
  • File Processing (B2.5): file reading/writing logic extracted into methods
  • IA: modularization is assessed in Criterion C (development) – “limited discussion of approach” is a common weakness

IB exam relevance:

  • Exam questions often provide a method header and ask students to complete the body
  • “Explain the benefits of modularization” is a common 4-6 mark question – students need at least 3 named benefits with explanations
  • Trace tables with method calls: students must track which method is executing, what parameters receive, and what is returned
  • Scope questions: “What is the value of x after this code runs?” where a method modifies a local copy

Answer Keys

Core 1: Print separator
public class SeparatorDemo {
    public static void main(String[] args) {
        printSeparator();
        System.out.println("Your Name Here");
        printSeparator();
    }

    public static void printSeparator() {
        for (int i = 0; i < 30; i++) {
            System.out.print("-");
        }
        System.out.println();
    }
}

Expected output:

------------------------------
Your Name Here
------------------------------

Common mistakes: Hardcoding the string "------------------------------" instead of using a loop. Both are acceptable but the loop approach is more flexible.

Marking notes: Accept any approach that prints 30 dashes. The key skill is defining and calling a void method.

Core 2: Sum of two
public class SumDemo {
    public static void main(String[] args) {
        System.out.println("3 + 5 = " + sum(3, 5));
        System.out.println("10 + 20 = " + sum(10, 20));
        System.out.println("-4 + 4 = " + sum(-4, 4));
    }

    public static int sum(int a, int b) {
        return a + b;
    }
}

Expected output:

3 + 5 = 8
10 + 20 = 30
-4 + 4 = 0

Common mistakes: Printing inside the method instead of returning. Students may write System.out.println(a + b) and make the method void.

Marking notes: The method MUST return int, not print. Deduct if void + print instead of return.

Core 3: Is even
public class EvenCheck {
    public static void main(String[] args) {
        System.out.println("4 is even: " + isEven(4));
        System.out.println("7 is even: " + isEven(7));
        System.out.println("0 is even: " + isEven(0));
    }

    public static boolean isEven(int n) {
        return n % 2 == 0;
    }
}

Expected output:

4 is even: true
7 is even: false
0 is even: true

Common mistakes: Using if (n % 2 == 0) return true; else return false; – works but verbose. Encourage the direct return of the boolean expression.

Marking notes: Accept the if/else version but point out the simpler return n % 2 == 0 pattern.

Core 4: Greeting
public class GreetingDemo {
    public static void main(String[] args) {
        greet("Alice");
        greet("Bob");
        greet("Charlie");
    }

    public static void greet(String name) {
        System.out.println("Hello, " + name + "! Welcome to CS.");
    }
}

Expected output:

Hello, Alice! Welcome to CS.
Hello, Bob! Welcome to CS.
Hello, Charlie! Welcome to CS.

Common mistakes: Hardcoding the name instead of using the parameter.

Marking notes: Accept any greeting format as long as the name comes from the parameter.

Extension 5: Temperature converter
public class TempConverter {
    public static void main(String[] args) {
        System.out.println("0C = " + celsiusToFahrenheit(0) + "F");
        System.out.println("100C = " + celsiusToFahrenheit(100) + "F");
        System.out.println("32F = " + fahrenheitToCelsius(32) + "C");
        System.out.println("212F = " + fahrenheitToCelsius(212) + "C");
    }

    public static double celsiusToFahrenheit(double celsius) {
        return celsius * 9.0 / 5.0 + 32;
    }

    public static double fahrenheitToCelsius(double fahrenheit) {
        return (fahrenheit - 32) * 5.0 / 9.0;
    }
}

Expected output:

0C = 32.0F
100C = 212.0F
32F = 0.0C
212F = 100.0C

Common mistakes: Integer division – using 9/5 gives 1, not 1.8. Must use 9.0/5.0 or cast to double.

Marking notes: Formulas must be correct. Accept (double) 9 / 5 or 9.0 / 5 as alternatives.

Extension 6: Array statistics
public class ArrayStats {
    public static void main(String[] args) {
        int[] grades = {85, 92, 78, 95, 88, 73, 91};
        System.out.println("Max: " + findMax(grades));
        System.out.println("Min: " + findMin(grades));
        System.out.println("Average: " + calculateAverage(grades));
    }

    public static int findMax(int[] arr) {
        int max = arr[0];
        for (int i = 1; i < arr.length; i++) {
            if (arr[i] > max) {
                max = arr[i];
            }
        }
        return max;
    }

    public static int findMin(int[] arr) {
        int min = arr[0];
        for (int i = 1; i < arr.length; i++) {
            if (arr[i] < min) {
                min = arr[i];
            }
        }
        return min;
    }

    public static double calculateAverage(int[] arr) {
        int total = 0;
        for (int i = 0; i < arr.length; i++) {
            total = total + arr[i];
        }
        return (double) total / arr.length;
    }
}

Common mistakes:

  • Starting loop at 0 instead of 1 for findMax/findMin (works but unnecessary comparison with self)
  • Integer division in calculateAverage – forgetting the (double) cast

Marking notes: This is the most important Extension exercise. All three methods must return values (not print). Accept loop starting at 0.

Extension 7: Password checker
public class PasswordChecker {
    public static void main(String[] args) {
        System.out.println("Abc12345: " + isStrongPassword("Abc12345"));
        System.out.println("abc: " + isStrongPassword("abc"));
        System.out.println("abcdefgh: " + isStrongPassword("abcdefgh"));
        System.out.println("ABCD1234: " + isStrongPassword("ABCD1234"));
        System.out.println("abcd1234: " + isStrongPassword("abcd1234"));
    }

    public static boolean isStrongPassword(String password) {
        if (password.length() < 8) {
            return false;
        }
        boolean hasDigit = false;
        boolean hasUpper = false;
        for (int i = 0; i < password.length(); i++) {
            char c = password.charAt(i);
            if (c >= '0' && c <= '9') {
                hasDigit = true;
            }
            if (c >= 'A' && c <= 'Z') {
                hasUpper = true;
            }
        }
        return hasDigit && hasUpper;
    }
}

Expected output:

Abc12345: true
abc: false
abcdefgh: false
ABCD1234: false
abcd1234: false

Common mistakes:

  • Using Character.isDigit() / Character.isUpperCase() – these work and are acceptable, but not required knowledge
  • Checking only the first character instead of iterating through all

Marking notes: Accept Character.isDigit()/Character.isUpperCase() as alternatives to manual range checks. The key skill is iterating through characters and tracking boolean flags.

Challenge 8: Refactor the GradeArray

This is the in-class RefactorGrades.java activity. The answer key is the completed version with all 6 methods filled in.

import java.util.Scanner;

public class RefactorGrades {
    public static void main(String[] args) {
        Scanner input = new Scanner(System.in);
        String[] studentNames = {"Alice", "Bob", "Charlie", "Diana", "Eve"};
        int[] grades = {85, 92, 78, 95, 88};

        printSeparator();
        System.out.println("Student Grades:");
        printGrades(studentNames, grades);
        printSeparator();
        System.out.println("Average: " + calculateAverage(grades));
        System.out.println("Highest: " + findMax(grades));
        System.out.println("Lowest: " + findMin(grades));
        printSeparator();

        System.out.print("Enter student name to search: ");
        String searchName = input.nextLine();
        int foundIndex = searchStudent(studentNames, searchName);
        if (foundIndex != -1) {
            System.out.println(searchName + "'s grade: " + grades[foundIndex]);
        } else {
            System.out.println("Student '" + searchName + "' not found.");
        }
    }

    public static void printSeparator() {
        System.out.println("~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~");
    }

    public static double calculateAverage(int[] grades) {
        int total = 0;
        for (int i = 0; i < grades.length; i++) {
            total = total + grades[i];
        }
        return (double) total / grades.length;
    }

    public static int findMax(int[] arr) {
        int max = arr[0];
        for (int i = 1; i < arr.length; i++) {
            if (arr[i] > max) {
                max = arr[i];
            }
        }
        return max;
    }

    public static int findMin(int[] arr) {
        int min = arr[0];
        for (int i = 1; i < arr.length; i++) {
            if (arr[i] < min) {
                min = arr[i];
            }
        }
        return min;
    }

    public static void printGrades(String[] names, int[] grades) {
        for (int i = 0; i < names.length; i++) {
            System.out.println(names[i] + ": " + grades[i]);
        }
    }

    public static int searchStudent(String[] names, String target) {
        for (int i = 0; i < names.length; i++) {
            if (names[i].equalsIgnoreCase(target)) {
                return i;
            }
        }
        return -1;
    }
}

Common mistakes:

  • Forgetting to pass arrays as parameters (trying to access grades from inside a method without a parameter)
  • Using == instead of .equalsIgnoreCase() for string search
  • Integer division in calculateAverage

Marking notes: The refactored main should be significantly shorter and readable. Methods should each do one job. Accept minor style variations.

Challenge 9: Mini calculator
import java.util.Scanner;

public class MiniCalculator {
    public static void main(String[] args) {
        Scanner input = new Scanner(System.in);
        boolean running = true;

        while (running) {
            System.out.print("Enter first number (or type quit): ");
            String first = input.nextLine();

            if (first.equals("quit")) {
                running = false;
            } else {
                double a = Double.parseDouble(first);
                System.out.print("Enter operation (+, -, *, /): ");
                String op = input.nextLine();

                if (isValidOperation(op)) {
                    System.out.print("Enter second number: ");
                    double b = Double.parseDouble(input.nextLine());
                    double result = 0;

                    if (op.equals("+")) {
                        result = add(a, b);
                    } else if (op.equals("-")) {
                        result = subtract(a, b);
                    } else if (op.equals("*")) {
                        result = multiply(a, b);
                    } else if (op.equals("/")) {
                        result = divide(a, b);
                    }
                    System.out.println("Result: " + result);
                } else {
                    System.out.println("Invalid operation.");
                }
            }
        }
        System.out.println("Goodbye!");
    }

    public static double add(double a, double b) {
        return a + b;
    }

    public static double subtract(double a, double b) {
        return a - b;
    }

    public static double multiply(double a, double b) {
        return a * b;
    }

    public static double divide(double a, double b) {
        return a / b;
    }

    public static boolean isValidOperation(String op) {
        return op.equals("+") || op.equals("-") || op.equals("*") || op.equals("/");
    }
}

Common mistakes:

  • Using == to compare strings instead of .equals()
  • Division by zero not handled (acceptable for this exercise – not required)
  • Using break to exit the loop – should use loop condition (running flag)

Marking notes: The key skills are: method design (each operation as a method), boolean return (isValidOperation), and string comparison with .equals(). Accept variations in input handling. Do not require division-by-zero handling unless students add it voluntarily.


GitHub Classroom Answer Key

The GitHub Classroom template has 4 files. Complete solutions for auto-graded methods:

TemperatureConverter.java (5 methods)
public class TemperatureConverter {
    public static double celsiusToFahrenheit(double celsius) {
        return celsius * 9.0 / 5.0 + 32;
    }

    public static double fahrenheitToCelsius(double fahrenheit) {
        return (fahrenheit - 32) * 5.0 / 9.0;
    }

    public static boolean isBelowFreezing(double celsius) {
        return celsius < 0;
    }

    public static String getCategory(double celsius) {
        if (celsius < 0) {
            return "Freezing";
        } else if (celsius < 15) {
            return "Cold";
        } else if (celsius < 25) {
            return "Comfortable";
        }
        return "Hot";
    }

    public static void printConversionTable(int startC, int endC) {
        for (int c = startC; c <= endC; c += 10) {
            System.out.println(c + "C = " + celsiusToFahrenheit(c) + "F");
        }
    }
}
StringHelper.java (5 methods)
public class StringHelper {
    public static int countVowels(String text) {
        int count = 0;
        String lower = text.toLowerCase();
        for (int i = 0; i < lower.length(); i++) {
            char c = lower.charAt(i);
            if (c == 'a' || c == 'e' || c == 'i' || c == 'o' || c == 'u') {
                count++;
            }
        }
        return count;
    }

    public static boolean isPalindrome(String text) {
        String lower = text.toLowerCase();
        int left = 0;
        int right = lower.length() - 1;
        while (left < right) {
            if (lower.charAt(left) != lower.charAt(right)) {
                return false;
            }
            left++;
            right--;
        }
        return true;
    }

    public static String toTitleCase(String text) {
        String lower = text.toLowerCase();
        String result = "";
        boolean capitalizeNext = true;
        for (int i = 0; i < lower.length(); i++) {
            char c = lower.charAt(i);
            if (c == ' ') {
                result += c;
                capitalizeNext = true;
            } else if (capitalizeNext) {
                result += (char) (c - 32);
                capitalizeNext = false;
            } else {
                result += c;
            }
        }
        return result;
    }

    public static String maskString(String text) {
        if (text.length() <= 4) {
            return text;
        }
        String masked = "";
        for (int i = 0; i < text.length() - 4; i++) {
            masked += "*";
        }
        masked += text.substring(text.length() - 4);
        return masked;
    }

    public static String summarize(String text) {
        return text + " has " + text.length() + " chars, " + countVowels(text) + " vowels, palindrome: " + isPalindrome(text);
    }
}
MathUtils.java (6 methods)
public class MathUtils {
    public static boolean isPrime(int n) {
        if (n <= 1) {
            return false;
        }
        for (int i = 2; i <= n / 2; i++) {
            if (n % i == 0) {
                return false;
            }
        }
        return true;
    }

    public static int gcd(int a, int b) {
        while (b != 0) {
            int temp = b;
            b = a % b;
            a = temp;
        }
        return a;
    }

    public static int[] everyOther(int[] arr) {
        int size = (arr.length + 1) / 2;
        int[] result = new int[size];
        int index = 0;
        for (int i = 0; i < arr.length; i += 2) {
            result[index] = arr[i];
            index++;
        }
        return result;
    }

    public static int countPrimes(int max) {
        int count = 0;
        for (int i = 2; i <= max; i++) {
            if (isPrime(i)) {
                count++;
            }
        }
        return count;
    }

    public static boolean isSorted(int[] arr) {
        for (int i = 0; i < arr.length - 1; i++) {
            if (arr[i] > arr[i + 1]) {
                return false;
            }
        }
        return true;
    }

    public static int range(int[] arr) {
        int max = arr[0];
        int min = arr[0];
        for (int i = 1; i < arr.length; i++) {
            if (arr[i] > max) {
                max = arr[i];
            }
            if (arr[i] < min) {
                min = arr[i];
            }
        }
        return max - min;
    }
}

© EduCS.me — A resource hub for Computer Science education

This site uses Just the Docs, a documentation theme for Jekyll.