Chapter 11 — Reps
Conditioning, not grading. This week’s reps are mostly reading — finding bugs in AI-shaped Java code. Keep your reps-prompts.txt going (you’ll need it for the few prompt-the-AI reps), and add a reps-bugs.txt where you log each bug you find with: file, line(s), category (from §11.2–§11.7), and fix.
You need:
- Java 17 + JUnit 5.
- Your AI assistant (for a few reps only).
- A patient eye.
Reps 1–4: Bug Hunting
Rep 1 — Three bugs, one method
Here is a Java method. We will tell you there are at least three bugs. Find them all. Fix them. Run your fix against test cases of your own.
public static int countVowels(String s) {
String vowels = "aeiou";
int count = 0;
for (int i = 0; i <= s.length(); i++) {
if (vowels.contains(s.substring(i, i+1))) {
count++;
}
}
return count;
}
Bugs to look for:
- Off-by-one in the loop bound.
- Null handling on
s. - Case sensitivity (does “A” count as a vowel?).
Fix and confirm with five test cases of your own.
Rep 2 — Hallucinated APIs
Here is a Java method. The AI produced it. At least two of the methods it calls do not exist in Java 17.
import java.util.List;
public class TextUtil {
public static List<String> tidy(List<String> lines) {
return lines.stream()
.map(String::trimAll) // (1)
.filter(String::hasContent) // (2)
.toList();
}
}
Identify which methods are hallucinated. Look them up in the Java 17 docs. Replace each with the real method that achieves the intent.
Hint: the intent of trimAll is probably strip(). The intent of hasContent is probably !s.isBlank().
Confirm your version compiles.
Rep 3 — Plausible but wrong
This method calculates the median of an array. It works on some inputs.
public static double median(int[] nums) {
Arrays.sort(nums);
return nums[nums.length / 2];
}
Find at least three problems:
- What happens on
{1, 2}? On{1, 2, 3, 4}? - What happens on
null? On{}? - What does this method do to the caller’s array?
Write tests that catch each. Fix the method. Re-run tests.
Rep 4 — Performance trap
This method finds duplicates in a list. It works. It is slow.
public static List<Integer> duplicates(List<Integer> nums) {
List<Integer> result = new ArrayList<>();
for (int i = 0; i < nums.size(); i++) {
for (int j = i + 1; j < nums.size(); j++) {
if (nums.get(i).equals(nums.get(j)) && !result.contains(nums.get(i))) {
result.add(nums.get(i));
}
}
}
return result;
}
Estimate the complexity. (Hint: it’s worse than O(n²).)
Rewrite the method in O(n) using a Set. Time the two versions on an input of 10,000 random integers with ~10% duplicates. Report both times in your log.
Reps 5–6: Apply the Checklist
Rep 5 — Ten questions on real AI output
Take any AI output from Project 10 (or generate a fresh small AI-produced class — your choice). Run the ten-question checklist from §11.1 on it. For each question, write one sentence: did the code pass or fail this question, and what’s the evidence?
You should end up with 10 sentences. Most will say “pass.” A few might say “fail.” If all 10 say “pass,” your spec was tight and your AI was sharp — congratulations. Find a more complex case for next time.
Rep 6 — Pair-read
Find a classmate. Trade AI outputs (from any prior project). Each of you reviews the other’s code with the ten-question checklist. Compare your findings.
Did you notice things the original author missed? Did they notice things you missed? The answer to both is almost always yes. Fresh eyes catch what familiar eyes don’t. This is the reason real teams require code review by someone other than the author.
Log what each of you caught that the other missed.
Reps 7–8: Write Tests for Bugs
Rep 7 — Bug-then-test
Pick one of the bugs you fixed in Reps 1–4. Write a JUnit test that would have caught it before the fix. Make sure the test fails on the original buggy code and passes on the fixed code.
This is the rhythm: every bug becomes a test. The test is the permanent guard against the bug returning.
Rep 8 — Test the categories
Pick any small AI-generated method. Write six tests, one for each bug category:
- A null-input test (Category 2).
- An empty-input test (Category 2).
- A boundary test — first or last index (Category 3).
- A “weird but valid” input test (Category 4 — plausible-but-wrong).
- A large-input test for performance (Category 5).
- A consistency-with-rest-of-codebase test (Category 7 — verifies your method behaves like a sibling method).
Run them. Note how many failed. Each failure is a bug the AI shipped that you can now catch.
Reps 9–10: Self-Diagnose
Rep 9 — Build your personal review checklist
Take the ten questions from §11.1. Customize them to your projects. Add 1–3 of your own questions you’ve learned to always ask. (Examples: “Are there magic numbers I should pull into constants?” or “Are there public methods that don’t belong in this class?”)
Save as my-review-checklist.txt next to your my-prompts.txt from last week. This is your toolkit. Use it for every Phase 2 review for the rest of the course.
Rep 10 — The two-pass review
Pick a 50–80 line piece of AI-generated code. Do two reviews:
- First pass — 60 seconds, fast. Skim. Write one sentence: does this look right?
- Second pass — 5–10 minutes, slow. Run your full checklist. Write one paragraph per checklist question.
Compare. What did the slow pass catch that the fast pass didn’t? Almost always, the answer is “a lot.” Log specifically what.
This rep teaches the cost of fast-read-only — a cost you now have data on.
Reps 11–12: Confront a Hard Case
Rep 11 — Prompt for buggy code on purpose
Send your AI a deliberately weak prompt for a moderately tricky problem:
Write Java code to format a phone number.
That’s it. One sentence. No signature, no examples, no constraints.
Save the response. Run your full review checklist on it. Count the things wrong. (Common: hallucinated regex, no null handling, assumed US format silently, no spec on what “format” means.)
For each thing wrong, write down: “the prompt sentence that would have prevented this is…”. Do not re-prompt. The rep is the analysis, not the fix.
Rep 12 — Break It On Purpose
Six review-discipline mistakes. Apply each, observe, learn:
- Skim and ship. Take an AI output. Don’t run the checklist. Ship it (to a private test file, not anywhere real). The next day, slow-read it. Find what you missed.
- Stop after one bug. Find one bug in AI code. Stop reviewing. Then go back and find a second bug. Notice it was there the whole time.
- Trust the compile. Take AI code that compiles. Don’t test it. Run it on weird inputs. Find a runtime bug.
- Trust the example. Test only the input the AI mentioned. Find a case the AI didn’t mention that breaks.
- Skip the docs check. See a method name you don’t recognize. Assume it’s real. (For one rep only — then go look it up.) Note how often you would have been wrong.
- Skip writing the test. Fix a bug without writing a test for it. A week later, regenerate the AI code. Notice the same bug came back because nothing was guarding against it.
Each of these is a real failure mode. Make them on purpose, in low-stakes reps, so you recognize them when they cost real time.
Done? One Last Thing.
Open my-review-checklist.txt from Rep 9. Use it on a piece of AI output you haven’t seen before. Time yourself. Make sure the checklist actually shaves time off, not adds to it. Edit until it does.
The senior’s toolkit is the tool the senior actually reaches for. Make yours reachable.
Up next: Project 11 — Project 11: Find the Bugs in AI’s Code.