Skip to content

Library Management#

Problem statement (interviewer prompt)

Design a library management system: catalogue of books (with multiple copies + ISBN), members, borrow / return / reserve flow, due dates with fines, search by title/author/subject, and admin functions (add/remove copies, manage members).

classDiagram
  class Library
  class Book
  class BookItem
  class Member
  class Reservation
  class Loan
  Library "1" *-- "many" Book
  Book "1" *-- "many" BookItem
  Library "1" *-- "many" Member
  Member "1" -- "many" Loan
  Member "1" -- "many" Reservation
classDiagram
  direction TB

  class Library {
    +name
    +branches
    +catalog: Catalog
    +loanSvc: LoanService
    +fineSvc: FineService
  }

  class Catalog {
    +search(query) List~Book~
    +addBook(b)
    +removeBook(b)
  }

  class Book {
    +isbn
    +title
    +authors
    +subject
  }

  class BookItem {
    +barcode
    +status: ItemStatus
    +location
    +book: Book
  }

  class ItemStatus {
    <<enumeration>>
    AVAILABLE
    RESERVED
    LOANED
    LOST
    DAMAGED
  }

  class Member {
    +id
    +name
    +type: MembershipType
    +loans: List~Loan~
    +reservations: List~Reservation~
  }

  class Librarian
  class Loan {
    +item
    +member
    +issueTs
    +dueTs
    +returnTs
  }

  class Reservation {
    +item
    +member
    +ts
    +status
  }

  class Fine {
    +loan
    +amount
    +paid
  }

  class LoanService {
    +issue(item, member) Loan
    +returnItem(loan)
    +renew(loan)
  }

  class FineService {
    +compute(loan) Fine
    +collect(fine)
  }

  Library *-- Catalog
  Catalog *-- "many" Book
  Book *-- "many" BookItem
  BookItem --> ItemStatus
  Member "1" -- "many" Loan
  Member "1" -- "many" Reservation
  Loan --> BookItem
  Reservation --> BookItem
  Library --> LoanService
  Library --> FineService
  Librarian --> Library

Detailed class diagram with multiplicities#

The earlier sketch shows the rough shape; the next diagram pins down cardinalities and adds Fine, Notification, and the subtype hierarchy that interviewers usually probe.

classDiagram
  direction TB

  class Library {
    +id
    +branches: List~Branch~
  }
  class Branch {
    +id
    +address
  }
  class Book {
    +isbn
    +title
    +authors
    +subject
  }
  class PhysicalBook
  class EBook {
    +licenseUrl
    +concurrentLimit
  }
  class AudioBook {
    +runtimeMin
    +format
  }
  class BookItem {
    +barcode
    +status: ItemStatus
    +condition
    +location
  }
  class Member {
    +id
    +name
    +tier
    +activeLoans
    +blocked: bool
  }
  class Loan {
    +id
    +issuedAt
    +dueAt
    +returnedAt
    +renewals: int
  }
  class Reservation {
    +id
    +createdAt
    +expiresAt
    +priority
    +status
  }
  class Fine {
    +id
    +amount
    +paid: bool
  }
  class Notification {
    +id
    +channel
    +payload
    +sentAt
  }

  Library "1" *-- "1..*" Branch
  Branch "1" o-- "0..*" BookItem
  Library "1" *-- "1..*" Book
  Book <|-- PhysicalBook
  Book <|-- EBook
  Book <|-- AudioBook
  Book "1" *-- "0..*" BookItem
  Library "1" *-- "0..*" Member
  Member "1" -- "0..*" Loan
  BookItem "1" -- "0..*" Loan
  Member "1" -- "0..*" Reservation
  BookItem "1" -- "0..*" Reservation
  Loan "1" -- "0..1" Fine
  Member "1" -- "0..*" Notification

Multiplicities matter for the lending invariants: a BookItem has at most one open Loan at a time (the others are historic); a Member can hold many overlapping Reservation rows but only one per BookItem; a Loan either has zero or one Fine (created lazily on a late return).

Core lending workflow in Java#

The two hot paths interviewers ask you to code are issueBook and returnBook. The snippet below is deliberately compact; production code adds transactions, optimistic locking on BookItem.status, and persistence.

public class LoanService {
    private final BookItemRepo items;
    private final LoanRepo loans;
    private final ReservationService reservations;
    private final FinePolicy finePolicy;
    private final Clock clock;

    public Loan issueBook(String barcode, Member member) {
        if (member.isBlocked()) {
            throw new MemberBlockedException(member.getId());
        }
        if (member.activeLoans() >= member.getTier().loanLimit()) {
            throw new LoanLimitException(member.getId());
        }
        BookItem item = items.lock(barcode);
        if (item.getStatus() == ItemStatus.RESERVED
                && !reservations.heldFor(item, member)) {
            throw new ItemReservedException(barcode);
        }
        if (item.getStatus() != ItemStatus.AVAILABLE
                && item.getStatus() != ItemStatus.RESERVED) {
            throw new ItemUnavailableException(item.getStatus());
        }
        item.setStatus(ItemStatus.LOANED);
        items.save(item);

        Loan loan = new Loan(item, member,
                clock.instant(),
                clock.instant().plus(member.getTier().loanDuration()));
        loans.save(loan);
        reservations.consumeIfAny(item, member);
        return loan;
    }

    public Fine returnBook(Loan loan) {
        loan.setReturnedAt(clock.instant());
        BookItem item = loan.getItem();
        item.setStatus(ItemStatus.AVAILABLE);
        items.save(item);
        loans.save(loan);

        Fine fine = null;
        if (loan.getReturnedAt().isAfter(loan.getDueAt())) {
            long daysLate = Duration.between(
                    loan.getDueAt(), loan.getReturnedAt()).toDays();
            fine = finePolicy.compute(loan, daysLate);
            loan.getMember().attachFine(fine);
        }
        reservations.promoteNext(item);
        return fine;
    }
}

The flow leans on three collaborators: FinePolicy (Strategy), ReservationService.promoteNext (Observer trigger), and the ItemStatus setter that enforces State transitions. Each is covered next.

Design patterns used#

Library Management is a textbook problem because four classic patterns map cleanly onto its responsibilities:

  • Strategy for fine calculation. FinePolicy is an interface with implementations such as FlatPerDayPolicy, TieredPolicy (rate grows after N days), and WaiverPolicy (free for students). Libraries swap policies per branch or per membership tier without touching LoanService.
  • Observer for overdue and ready-for-pickup notifications. A NotificationBus subscribes channels (EmailNotifier, SmsNotifier, PushNotifier); the LoanService and a scheduled OverdueScanner publish LoanOverdueEvent and ReservationReadyEvent. Channels filter by the member's preferences.
  • State for BookItem. The status is a small state machine: AVAILABLE to RESERVED (when the next holder is promoted) or LOANED (when issued), RESERVED to LOANED (when the holder picks up) or AVAILABLE (when the hold expires), LOANED to AVAILABLE (return) or LOST. Encoding transitions in one place prevents impossible states such as a LOST item being issued.
  • Factory for the Book subtype hierarchy. BookFactory.create(metadata) picks PhysicalBook, EBook, or AudioBook from the catalog feed. Each subtype enforces its own invariants: EBook caps concurrent loans via concurrentLimit; AudioBook exposes a streaming URL; PhysicalBook requires at least one BookItem to be useful.

Two supporting patterns also show up but are usually expected without prompting: Repository for BookItem, Loan, and Reservation persistence, and Command for librarian operations (AddBookCommand, WaiveFineCommand) to support audit logs and undo.

Common variants & follow-ups#

Interviewers rarely stop at the single-branch model. The follow-ups below are where the grading separates good answers from great ones:

  • Multi-branch library. Each Branch owns its BookItem pool but shares the global Book catalog. Add a HomeBranch on Member and a pickupBranch on Reservation; introduce an inter-branch transfer flow that swaps a BookItem between locations before the hold deadline.
  • Holds queue and reservation priority. Switch from FIFO to a priority queue: faculty before students, premium tier before free, paid expedite holds first. Encode priority on Reservation and have promoteNext peek the head of the priority queue. Combine with a holdExpiresAt deadline so the queue does not stall on a no-show.
  • E-book licensing limits. An EBook exposes concurrentLimit; the lending service treats it as a semaphore. The model becomes: lend if activeDigitalLoans(ebook) < concurrentLimit, else queue a reservation. License renewals decrement an availability counter rather than mutating a physical copy.
  • Inter-library loan (ILL). Members can request books the home library does not stock. Model a Request aggregate that fans out to peer libraries, accepts the first match, and tracks shipping. The fine policy uses the lending library's rate; the borrowing library is liable for damaged items.
  • Digital vs physical lifecycle. Physical copies retire (DAMAGED, LOST, WITHDRAWN) and need replacement orders. Digital copies expire by license term, not condition; the model tracks licenseExpiresAt and pulls the title from search once it lapses. A RetentionPolicy decides whether to renew the license based on circulation history.

Edge cases#

The cases below are the ones that crash early implementations; an interviewer who likes follow-ups will hit at least three:

  • Returning a lost copy. The member reports a book lost, pays a replacement fine, and the BookItem.status moves to LOST. If the copy is later found, do not silently flip back to AVAILABLE: open a RecoveredItem workflow that refunds the replacement fine and re-shelves the item.
  • Fine on a member with an active reservation. A member with an unpaid fine should not be able to consume a reservation. The issueBook precondition checks both member.isBlocked() and outstanding fines above a threshold; on rejection, the reservation falls to the next member rather than expiring outright.
  • Member with overdue blocking new loans. Mirror the rule above: a single overdue beyond a grace period blocks all new loans for that member, but their existing reservations stay valid (so they do not lose their place in queue). The block lifts automatically on return + fine settlement.
  • Reservation expiry. When a held copy is not picked up by expiresAt, the system fires ReservationExpiredEvent, demotes the reservation, and promotes the next holder. A common bug is to mark the copy AVAILABLE and forget to scan the queue: always run promoteNext after any status flip.
  • Race on the last available copy. Two members hit issueBook for the same BookItem in the same second. The fix is optimistic locking on BookItem.status with a version column: the second writer fails, the service retries by selecting another available copy of the same Book, or queues a reservation if none exist. Without this guard, both loans persist and the inventory desyncs.

Glossary & fundamentals#

Concept What it is Fundamentals
MVCC / CAS item status transitions mvcc-isolation-levels
Idempotency loan / return idempotency-retries
Pub/Sub due-date reminders pub-sub-pattern

Quick reference#

Functional#

  • Catalog search, by title/author/subject/isbn.
  • Issue / return / renew / reserve.
  • Fines for overdue.
  • Membership tiers.
  • Multi-branch.

Patterns#

  • Repository (catalog).
  • Strategy (FinePolicy).
  • Observer (notifications).
  • State (BookItem).

Refs#

  • Grokking OOD; classic Larman / Riel OOP texts.

FAQ#

Why split Book and BookItem in the class model?#

Book holds bibliographic data shared by every copy (title, author, ISBN); BookItem represents a physical copy with its own barcode, condition, and loan history.

How is borrow and return modelled?#

A Loan ties a Member to a BookItem with issued_at and due_at timestamps; return sets returned_at, flips the BookItem to Available, and triggers fine calculation if late.

How does book reservation work?#

When a copy is unavailable, members enqueue a Reservation. On return, the first waiting reservation is notified and the copy is held for them until a hold deadline.

How are fines calculated?#

Fine equals days_overdue times the per-day fee from the lending policy, often capped at the book's replacement cost so members are not punished indefinitely.

How do you search the library catalogue?#

Index Book by title, author, subject, and ISBN in an inverted index or database with full-text search so members can query by any combination of fields.

Video walkthrough

Library Management System LLD (Google Interview Question) : via Soumyajit Bhattacharyay