Unit 4 · Association, Aggregation and Composition

4.5Mini-Project: Library Management System

Build a Library Management System in Java using an IDE.

Requirements

  1. Draw a flowchart for the borrow-a-book process and write pseudocode for the fine calculation.
  2. Classes: Book, Member, Library, Loan, plus an abstract class Person with subclasses Member and Librarian.
  3. 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.
  4. Show aggregation (Library has Books) and composition (Loan has LoanItems, created inside Loan).
  5. Provide a class diagram and a test table with at least 10 test cases (normal, boundary, invalid) and the actual results.
  6. Debug at least one error using the IDE debugger and describe it in the report.
«abstract»Person# name: StringgetRole(): StringMember- memberId: StringgetRole()Librarian- staffId: StringgetRole()Library- books: ListaddBook(Book)Book- isbn, titleisAvailable()Loan- dueDatefine(): doubleLoanItem- book: Bookborrowed by«interface»Borrowableborrow()giveBack()aggregationcomposition
A possible class diagram for the Library Management System mini-project
1Design on paper→2Write and test each class→3Add the relationships→4Test and debug→5Write the report

What a good project shows

Use this list to check your work before you hand it in:

A starting point for the Person hierarchy. It uses validation in the constructor, final and static fields, an abstract method and overriding:

Java
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:

ClassKnows (attributes)Does (methods)
Person (abstract)namegetRole() (abstract)
MembermemberId, the loans it holdsgetRole(), borrow and return requests
LibrarianstaffIdgetRole(), add and remove books
Bookisbn, title, whether it is on loanisAvailable(), borrow(), giveBack() (from Borrowable)
Librarythe list of booksaddBook(), findBook(), listAvailable()
Loanthe member, the due date, its itemsfine(), addItem()
LoanItemthe 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

Step 4: Test and debug

Use the testing method from 1.4.2. Some rows your test table could include:

TestTypeExpected
Borrow an available bookNormalLoan created; the book is now unavailable
Borrow a book that is already on loanInvalidRefused with a message
Return a book on the due dateBoundaryFine is 0
Return a book one day lateBoundaryFine for one day
Create a book with an empty titleInvalidRejected 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.