Build a Library Management System in Java using an IDE.
Requirements
- Draw a flowchart for the borrow-a-book process and write pseudocode for the fine calculation.
- Classes: Book, Member, Library, Loan, plus an abstract class Person with subclasses Member and Librarian.
- Use encapsulation (private data with getters and setters and validation), constructors (with overloading), static and final modifiers, inheritance with overriding, an interface Borrowable, and polymorphism.
- Show aggregation (Library has Books) and composition (Loan has LoanItems, created inside Loan).
- Provide a class diagram and a test table with at least 10 test cases (normal, boundary, invalid) and the actual results.
- Debug at least one error using the IDE debugger and describe it in the report.
What a good project shows
Use this list to check your work before you hand it in:
- Design: a correct flowchart, pseudocode and class diagram that match the code.
- Classes and objects: well-designed classes, overloaded constructors and no repeated code.
- Encapsulation and modifiers: all data
privateand validated;staticandfinalused where they make sense. - Inheritance and polymorphism: the Person hierarchy with overriding, the Borrowable interface, and objects handled through their general type.
- Relationships: correct aggregation and composition, with one sentence justifying each choice.
- Testing: at least 10 test cases (normal, boundary and invalid) with actual results, and evidence of using the debugger.
- Code quality: meaningful names, consistent formatting and comments where they help.
- Demonstration: you can run the program in the IDE and explain how it works.
A starting point for the Person hierarchy. It uses validation in the constructor, final and static fields, an abstract method and overriding:
public abstract class Person {
protected final String name;
protected Person(String name) {
if (name == null || name.isBlank()) throw new IllegalArgumentException("Name is required");
this.name = name;
}
public abstract String getRole();
}
public class Member extends Person {
private static int count = 0; // how many members have joined
private final String memberId;
public Member(String name) {
super(name);
count++;
this.memberId = "M" + count;
}
@Override
public String getRole() { return "Member " + memberId; }
}Working through the project
Step 1: Design on paper
Underline the nouns and verbs in the requirements (see 3.1.1). Decide what each class is responsible for:
| Class | Knows (attributes) | Does (methods) |
|---|---|---|
| Person (abstract) | name | getRole() (abstract) |
| Member | memberId, the loans it holds | getRole(), borrow and return requests |
| Librarian | staffId | getRole(), add and remove books |
| Book | isbn, title, whether it is on loan | isAvailable(), borrow(), giveBack() (from Borrowable) |
| Library | the list of books | addBook(), findBook(), listAvailable() |
| Loan | the member, the due date, its items | fine(), addItem() |
| LoanItem | the book borrowed | (simple data) |
Then draw the flowchart for borrowing a book. It needs at least two decisions: is the book available? and is the member allowed to borrow more? Write pseudocode for the fine: for example, a fixed amount per day late, and nothing if the book is returned on time. Decide your rules and write them down, so that your tests can check them.
Step 2: Write and test each class
Start with the classes that depend on nothing else: Book and Person. Write one class, then test it straight away from main before moving on. Check every validation rule: an empty title, a negative number of days late, a duplicate ISBN.
Step 3: Add the relationships
- Aggregation: books are created outside the Library and added with
addBook(book). A book can be removed from one library and still exist. - Composition: a Loan creates its own LoanItems inside
addItem(...)and never hands them out, so they disappear with the loan. - Polymorphism: keep members and librarians together in one
List<Person>and callgetRole()on each one.
Step 4: Test and debug
Use the testing method from 1.4.2. Some rows your test table could include:
| Test | Type | Expected |
|---|---|---|
| Borrow an available book | Normal | Loan created; the book is now unavailable |
| Borrow a book that is already on loan | Invalid | Refused with a message |
| Return a book on the due date | Boundary | Fine is 0 |
| Return a book one day late | Boundary | Fine for one day |
| Create a book with an empty title | Invalid | Rejected by validation |
Use the debugger at least once, with a breakpoint in the fine calculation, and record what you found.
Step 5: Write the report
Include the class diagram, the flowchart and pseudocode, the code, the test table with actual results, and a short paragraph for each OOP concept, explaining where you used it and why. For example: "LoanItem is composition because a loan item has no meaning outside its loan."
Tip: keep the program small but complete. A short program that uses every concept correctly, with good tests, is worth more than a large one that only partly works.
End of Unit 4. Test yourself with the Unit 4 questions in the multiple-choice and structured question banks, tick the outcomes in the topic checklist, then go on to the Final Revision section.