Course Management System
Problem Implement a course management system that models courses, students, and instructors, and supports enrollment with capacity limits and roster/schedule queries.
Requirements
createCourse(title, instructorId, capacity) -> CourseandupdateCourse(courseId, fields) -> Courseenroll(studentId, courseId) -> Enrollment— rejects when the course is full or the student is already enrolledunenroll(studentId, courseId) -> voidlistCoursesForStudent(studentId) -> List<Course>listRoster(courseId) -> List<Student>
Core design
- Entities:
Course(id, title, instructor, capacity),Student,Instructor, andEnrollmentas an explicit join entity (studentId, courseId, enrolledAt, status). ModellingEnrollmentas a first-class object rather than a list insideCourseis what makes waitlists, drop dates, and grades addable later. - Layering:
Controller(input parsing/validation of shape) ->Service(business rules) ->Repository(persistence). Keep the layers separate even in a small exercise. - The repository is an interface (
CourseRepository,EnrollmentRepository) so an in-memoryMap-backed implementation can be swapped for a database one without touching the service. - Business rules live in the service, never the controller: capacity enforcement, no double-enrollment, course must exist and be open, instructor must exist.
- Enrollment count is derived from
Enrollmentrows rather than a counter onCourse, avoiding a second source of truth that can drift.
Discussion points
- Concurrency: two students racing for the last seat can both pass the capacity check. Discuss synchronizing per-course, an atomic conditional insert, or optimistic locking with a version column — and why the naive read-check-write is wrong.
- Edge cases: unenrolling someone never enrolled, re-enrolling after a drop, deleting a course with a live roster (cascade vs. reject), capacity lowered below current enrollment.
- Testability: interface-backed repositories let the enroll/capacity rules be unit-tested with no database. Cover the boundary — enrolling at capacity-1, at capacity, and past it.
- Trade-off: in-memory maps are fast to build and test but lose transactional guarantees the capacity rule actually depends on.
- Extension: waitlists with automatic promotion on a drop, prerequisites, per-term course offerings, and instructor schedule-conflict checks.
asked …