Review and Refactor
By the end of this lesson, you'll be able to:
- Read a finished class critically for opportunities to simplify
- Apply a small refactor without changing external behavior
- Explain why review-and-refactor is a normal, expected step, not a sign something was done wrong
Prerequisites: "Handle Errors Gracefully"
The finished class, before refactoring
public class CourseRoster {
private String courseName;
private Integer maxSize;
private List<Student> enrolledStudents = new List<Student>();
public CourseRoster(String courseName, Integer maxSize) {
this.courseName = courseName;
this.maxSize = maxSize;
}
public Boolean enroll(Student student) {
if (student == null) {
return false;
}
for (Student existing : enrolledStudents) {
if (existing.getStudentId() == student.getStudentId()) {
return false;
}
}
if (enrolledStudents.size() >= maxSize) {
return false;
}
enrolledStudents.add(student);
return true;
}
public Integer getRemainingSeats() {
return maxSize - enrolledStudents.size();
}
}
This works correctly — but the enroll() method is doing three separate jobs (null-check, duplicate-check, capacity-check) inline. That's a candidate for refactoring.
Refactoring: extract a private helper method
public class CourseRoster {
private String courseName;
private Integer maxSize;
private List<Student> enrolledStudents = new List<Student>();
public CourseRoster(String courseName, Integer maxSize) {
this.courseName = courseName;
this.maxSize = maxSize;
}
public Boolean enroll(Student student) {
if (student == null || isAlreadyEnrolled(student) || isFull()) {
return false;
}
enrolledStudents.add(student);
return true;
}
private Boolean isAlreadyEnrolled(Student student) {
for (Student existing : enrolledStudents) {
if (existing.getStudentId() == student.getStudentId()) {
return true;
}
}
return false;
}
private Boolean isFull() {
return enrolledStudents.size() >= maxSize;
}
public Integer getRemainingSeats() {
return maxSize - enrolledStudents.size();
}
}
enroll() now reads almost like a sentence: reject if null, already enrolled, or full — otherwise add. isAlreadyEnrolled() and isFull() are private, since they're internal implementation details, not part of the class's public contract. External behavior hasn't changed at all — every existing call to enroll() behaves identically.
Why this step matters
Getting something working first, then reviewing it with fresh eyes, is the normal shape of real development — not a sign the first version was wrong. A method with three unrelated checks jammed together isn't a bug, but it is harder to read, test, and extend than three named, focused pieces. Refactoring after it works, rather than trying to write the "perfect" version first, keeps each step small and verifiable.
Exercise
Refactor this method into two private helper methods, hasValidName and hasValidEmail, called from a single validate() method.
Show hint
Extract each condition into its own aptly-named private method.
Review and Refactor Quiz
My Notes
Log in to keep private notes on this lesson.
Questions about this lesson
No questions yet — be the first to ask.
Log in to ask a question about this lesson.
Summary
The final lesson steps back and reviews the whole CourseRoster class built across this module, tightening it up without changing how it behaves from the outside.