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) -> Course and updateCourse(courseId, fields) -> Course
  • enroll(studentId, courseId) -> Enrollment — rejects when the course is full or the student is already enrolled
  • unenroll(studentId, courseId) -> void
  • listCoursesForStudent(studentId) -> List<Course>
  • listRoster(courseId) -> List<Student>

Core design

  • Entities: Course (id, title, instructor, capacity), Student, Instructor, and Enrollment as an explicit join entity (studentId, courseId, enrolledAt, status). Modelling Enrollment as a first-class object rather than a list inside Course is 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-memory Map-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 Enrollment rows rather than a counter on Course, 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 …
LeaderboardSalaryAccount