ARCHITECTURE.md
Architecture
Nine classes in one package, in three layers: entities that model the university, support classes for input and storage, and a main class that runs the loop.
Layers#
Class map#
Class index#
| Class | Kind | Responsibility | Lines | |
|---|---|---|---|---|
User | abstract class | Abstract generic base for every account type. | 91 | source |
Student | class | Enrols, drops, checks credit hours and views grades. | 209 | source |
Instructor | class | Views rosters, grades students and edits course details. | 210 | source |
Administrator | class | Manages accounts, courses and instructor assignments. | 192 | source |
Course | class | A course: capacity, credit hours, status and roster. | 183 | source |
Assessment | class | One grade: student × course × exam type → score. | 190 | source |
Helpers | utility class | Shared input, validation, login, menus and multi-step flows. | 806 | source |
dataManager | singleton class | Singleton storage layer: five lists, five text files. | 696 | source |
SchoolCourseEnrolmentSystem | main class | Entry point: load, register the default admin, loop, save. | 195 | source |
Listings come from the project report and were re-indented when extracted from the PDF, so wrapping may differ slightly from the original files.
Design decisions#
Singleton storage
dataManager.getInstance()One synchronized factory method means every part of the program shares the same five lists.
Self-typed generics
User<T> / <T extends User<T>> T login(...)Each subclass passes itself as T, so one login flow in Helpers returns a Student, Instructor or Administrator with no casts.
Predicate validators
updateFieldWithPrompt("email", value, Helpers::ValidateEmail)Validators are passed as method references, so one prompt method handles every field.
Enums for fixed choices
Role · EnrollmentStatusEnum · ExamTypeRoles, Open/Closed and exam types can only take valid values, and valueOf() parses them from the files.
Safe removal
Iterator<Student> it = list.iterator(); it.remove();Removing through an Iterator avoids a ConcurrentModificationException while looping.
Plain-text persistence
String.join("|", ...) / line.split("\\|")Human-readable files with no database dependency, at the cost of indexing, concurrency and integrity checks.
When data is saved#
Only a few actions write to disk immediately. Everything else waits for saveAllData() at exit, which is why closing the window loses work (see Known issues).
| Who | Action | File | Written |
|---|---|---|---|
| Start-up | Register the default admin | administrators.txt | immediately |
| Student | 7 · Update personal information | students.txt | immediately |
| Instructor | 3 · Update course information | courses.txt | immediately |
| Instructor | 4 · Update personal information | instructors.txt | immediately |
| Admin | 9 · Update Student Info | students.txt | immediately |
| Admin | 10 · Update Instructor Info | instructors.txt | immediately |
| Student | 2 · Enroll / 5 · Drop | students.txt | on exit only |
| Instructor | 2 · Grade assignments | assessments.txt | on exit only |
| Admin | 1, 2 · Add / remove students | students.txt | on exit only |
| Admin | 4, 5 · Add / remove instructors | instructors.txt | on exit only |
| Admin | 7, 8, 11 · Add / close course, assign instructor | courses.txt | on exit only |
| Exit | Type exit at the role prompt | all five files | immediately |
Project layout#
treeSchoolCourseEnrolmentSystem/
├─ src/schoolcourseenrolmentsystem/
│ ├─ User.java Student.java Instructor.java Administrator.java
│ ├─ Course.java Assessment.java
│ ├─ Helpers.java dataManager.java
│ └─ SchoolCourseEnrolmentSystem.java ← main()
├─ students.txt instructors.txt administrators.txt
├─ courses.txt assessments.txt ← written next to the program
└─ web/ ← this website