Bird
Raised Fist0
LLDsystem_design~7 mins

Class design (Book, Member, Librarian, Loan) in LLD - System Design Guide

Choose your learning style10 modes available

Start learning this pattern below

Jump into concepts and practice - no test required

or
Recommended
Test this pattern10 questions across easy, medium, and hard to know if this pattern is strong
Problem Statement
When designing a library management system, poor class design leads to tightly coupled code, making it hard to maintain or extend. Without clear responsibilities, classes become bloated or overlap, causing bugs and confusion.
Solution
Divide the system into clear classes representing real-world entities: Book, Member, Librarian, and Loan. Each class handles its own data and behavior, communicating through well-defined interfaces. This separation keeps code organized and easier to update or expand.
Architecture
┌─────────┐       ┌───────────┐       ┌────────────┐       ┌─────────┐
│  Member │──────▶│    Loan   │◀──────│    Book    │       │Librarian│
└─────────┘       └───────────┘       └────────────┘       └─────────┘
       │                                                        ▲
       │                                                        │
       └────────────────────────────────────────────────────────┘

This diagram shows the relationships: Members borrow Books via Loans, Librarians manage the system, and Loans connect Members and Books.

Trade-offs
✓ Pros
Clear separation of concerns improves maintainability and readability.
Classes map closely to real-world concepts, making the system intuitive.
Easier to add new features like overdue fines or reservations by extending classes.
✗ Cons
Initial design requires careful thought to avoid missing important attributes or methods.
Too many small classes can increase complexity if not managed well.
Improper encapsulation can still lead to tight coupling if classes access each other's internals directly.
Use when building systems that model real-world entities with distinct roles and behaviors, especially if the system will grow or change over time.
Avoid for very simple scripts or prototypes where full object-oriented design adds unnecessary complexity.
Real World Examples
Amazon
Models products, customers, and orders as separate classes to manage their online marketplace efficiently.
LinkedIn
Uses clear class designs for users, connections, and messages to handle complex social networking features.
Netflix
Represents movies, users, and viewing sessions as distinct classes to personalize recommendations and track usage.
Code Example
The before code mixes all responsibilities in one class, making it hard to maintain. The after code separates entities into classes with clear roles: Book tracks availability, Member tracks loans, Loan connects them, and Librarian manages loans. This improves clarity and extensibility.
LLD
### Before: Poor class design with mixed responsibilities
class Library:
    def __init__(self):
        self.books = []
        self.members = []
        self.loans = []

    def add_book(self, book):
        self.books.append(book)

    def add_member(self, member):
        self.members.append(member)

    def loan_book(self, book, member):
        if book.available:
            book.available = False
            self.loans.append({'book': book, 'member': member})

### After: Clear class design with responsibilities separated
class Book:
    def __init__(self, title, author):
        self.title = title
        self.author = author
        self.available = True

class Member:
    def __init__(self, name):
        self.name = name
        self.loans = []

class Loan:
    def __init__(self, book, member):
        self.book = book
        self.member = member
        self.active = True
        book.available = False
        member.loans.append(self)

class Librarian:
    def __init__(self, name):
        self.name = name

    def loan_book(self, book, member):
        if book.available:
            return Loan(book, member)
        else:
            return None
OutputSuccess
Alternatives
Procedural Programming
Focuses on functions and data separately without bundling them into classes.
Use when: Choose when the system is very simple or performance-critical with minimal state management.
Entity-Component-System (ECS)
Separates data (components) from behavior (systems) rather than using classes with both.
Use when: Choose for game development or highly dynamic systems needing flexible composition.
Summary
Good class design separates system entities into distinct classes with clear responsibilities.
This separation makes the code easier to maintain, extend, and understand.
Avoid mixing unrelated behaviors in one class to prevent complexity and bugs.

Practice

(1/5)
1. Which class should be responsible for storing information about a book's title, author, and ISBN in a library system?
easy
A. Member
B. Book
C. Librarian
D. Loan

Solution

  1. Step 1: Identify the class representing a book

    The class named Book logically holds details about books such as title, author, and ISBN.
  2. Step 2: Confirm other classes' roles

    Member is for library users, Librarian manages operations, and Loan tracks borrowing, so they don't store book details.
  3. Final Answer:

    Book -> Option B
  4. Quick Check:

    Book class stores book info [OK]
Hint: Book class holds book details like title and author [OK]
Common Mistakes:
  • Confusing Member with Book class
  • Assigning book details to Loan class
  • Thinking Librarian stores book info
2. Which of the following is the correct way to define a method named borrowBook inside the Member class in Python?
easy
A. def borrowBook():
B. def borrowBook(book):
C. def borrowBook(self):
D. def borrowBook(self, book):

Solution

  1. Step 1: Understand method definition in Python classes

    Instance methods must have self as the first parameter to access object data.
  2. Step 2: Check method parameters for borrowing a book

    The method needs the book to borrow, so it should accept a book parameter after self.
  3. Final Answer:

    def borrowBook(self, book): -> Option D
  4. Quick Check:

    Instance method with self and book param [OK]
Hint: Instance methods always start with self parameter [OK]
Common Mistakes:
  • Omitting self parameter
  • Not passing book argument
  • Defining method without parameters
3. Given the following Python code snippet, what will be the output?
class Loan:
    def __init__(self, book, member):
        self.book = book
        self.member = member

loan = Loan('1984', 'Alice')
print(loan.book, loan.member)
medium
A. 1984 Alice
B. book member
C. Loan object memory address
D. Error: missing parameters

Solution

  1. Step 1: Analyze the Loan class constructor

    The constructor __init__ assigns book and member to instance variables.
  2. Step 2: Check the print statement output

    Printing loan.book and loan.member outputs the strings '1984' and 'Alice' separated by space.
  3. Final Answer:

    1984 Alice -> Option A
  4. Quick Check:

    loan.book and loan.member print values [OK]
Hint: Print instance variables to see stored values [OK]
Common Mistakes:
  • Expecting object memory address output
  • Confusing variable names with strings
  • Assuming error due to parameters
4. Identify the error in this Python class design snippet for the Librarian class:
class Librarian:
    def __init__(self, name):
        self.name = name
    def addBook(book):
        print(f"Adding {book} to library")
medium
A. Missing self parameter in addBook method
B. Incorrect print statement syntax
C. Constructor missing return statement
D. Class name should be lowercase

Solution

  1. Step 1: Check method parameters in class

    Instance methods must include self as the first parameter to access instance data.
  2. Step 2: Verify addBook method signature

    addBook lacks self, so it will cause an error when called on an instance.
  3. Final Answer:

    Missing self parameter in addBook method -> Option A
  4. Quick Check:

    Instance methods need self param [OK]
Hint: Instance methods always start with self parameter [OK]
Common Mistakes:
  • Thinking print syntax is wrong
  • Expecting constructor to return value
  • Believing class names must be lowercase
5. In designing a library system, which class should handle the logic to check if a book is currently loaned out before allowing a member to borrow it?
hard
A. Book
B. Member
C. Loan
D. Librarian

Solution

  1. Step 1: Understand responsibilities of each class

    Book stores book info, Member represents users, Loan tracks borrow records, and Librarian manages library operations.
  2. Step 2: Identify who controls borrowing rules

    The Loan class should handle checking if a book is currently loaned out before allowing borrowing, as it tracks loan records.
  3. Final Answer:

    Loan -> Option C
  4. Quick Check:

    Loan class tracks loan status [OK]
Hint: Loan class tracks if a book is loaned out [OK]
Common Mistakes:
  • Putting borrowing logic inside Book class
  • Assigning loan status check to Member
  • Expecting Librarian class to enforce borrowing rules