Employee records, with no framework to hide behind
A command-line program that keeps a company's employee records in a file. No Spring, no database, no library: the Java you have learned so far, made to hold up under real input.
The business problem
A small company keeps its employee list in a spreadsheet and has lost it twice. Build them a program: add an employee, list them, search by name or department, change a salary, remove someone who has left — and keep it all in a file that survives the program exiting.
The bar is not that the happy path works. It is that a duplicate id is refused, a malformed line in the file does not lose the other lines, a search on a department with nobody in it says so, and the file is never left half-written.
What you will have at the end
- A domain model with invariants the constructor enforces, not a bag of getters and setters
- Collections chosen for the questions asked: lookup by id, listing in order, grouping by department
- File I/O through Path and Files, with a write that is atomic
- Errors as exceptions with a message a user can act on, and a main() that never prints a stack trace
Milestones
Each one ends in something you can observe. Without that a milestone is a heading, and you have no way to know you finished.
The model
An Employee record with id, name, department, salary and start date. Validate in the canonical constructor: no blank names, no negative salaries, a start date that is not in the future.
done whennew Employee("", ...) throws with a message that names the field, and a test proves each rule.
The registry
An in-memory EmployeeRegistry: add, remove, findById, findByName, byDepartment, all. Choose the collection for each — a Map for the id lookup, and decide what 'all, in order' orders by.
done whenAdding an id that exists is refused with an exception, not silently overwritten, and byDepartment on an unknown department returns an empty list, not null.
The file
Persist as one line per employee in a format you design (CSV with a header, or JSON lines). Load on start; save on every change. Write to a temporary file and move it over the old one, so a crash mid-write leaves the previous file intact.
done whenKill the program during a save (a breakpoint will do) and the file is either the old version or the new one, never a torn line.
Bad input
A malformed line in the file, a salary that is not a number, a date in the wrong format. Decide, per case: skip and report, or refuse to start. Write the decision down in the README.
done whenA file with one broken line loads the others and prints exactly which line was skipped and why.
The command line
add, list, find, raise, remove, with arguments. Parse them yourself — no library — and print usage on a mistake. Salaries display with a currency and two decimals.
done whenEvery command works from a shell script that runs them in sequence, and no command ever prints a stack trace to a user.
Data
One file, one record type. The interesting decision is the id: a counter you persist, or a UUID you generate — and what happens to the counter if two copies of the program run at once.