How to identify entities and model relationships
A systematic approach to discovering classes and relationships from requirements, using noun extraction, responsibility testing, and relationship classification.
You just read "Design a library management system" on the whiteboard. You know you need classes and relationships, but which nouns become classes, which become fields, and which are just noise? A common failure mode is either freezing at this point or typing class Book before the model has a clear purpose.
Entity discovery gives the rest of an LLD design its shape. If the model misses a lifecycle or relationship, later patterns and services have to work around it. This guide gives you a repeatable process for turning requirements into a small domain model without treating every noun as a class.
TL;DR
The purpose of this article is to help you derive entities, attributes, responsibilities, and relationships from requirements in a way that remains easy to revise.
- 30-second idea: Treat nouns as candidates, not verdicts. Filter them by identity, lifecycle, behavior, and responsibility; then use verbs to find relationships and hidden "through" entities.
- Mental model:
requirements → nouns → filters → hidden entities → relationships/multiplicity → responsibilities → scenario check. - Repeatable process: extract nouns, filter vague/primitive/duplicate terms, promote concepts that carry state or behavior, classify ownership, and test the model against one end-to-end use case.
- Adapt to constraints: keep only the concepts needed by the stated use cases; use an attribute or value object for a simple concept, and promote it later if its lifecycle, rules, or relationships become independent.
Why entity discovery matters
Entities are the skeleton of your design. Classes, interfaces, and relationships should trace back to the use cases and concepts you identify early. If you pick the wrong entities, the rest of the design has to compensate for a misplaced responsibility or missing lifecycle.
A common example is merging Book and Library into one class. A later Strategy pattern cannot repair that model; the ownership and responsibilities need to be separated first.
Think of entities like the concepts behind a database schema: a poor boundary makes later operations awkward, while a clear boundary gives the rest of the design a more stable shape.
Entity discovery is partly mechanical, but it still needs judgment. Read the requirements, highlight candidate nouns, filter out noise, and then check each candidate against behavior, lifecycle, and relationships.
Interview tip: make it visible
Write your entity list on the whiteboard before coding anything. A visible list of entities, attributes, and assumptions makes the model easier to review and revise before implementation.
The noun-extraction technique
This is the core technique for many LLD prompts. The process has three steps: extract, filter, promote.
Step 1: Extract all nouns
Read the requirements and underline every noun or noun phrase. Do not judge yet. Do not ask "is this a class?" Just collect.
Here is a sample requirement for a library system:
"The library has multiple branches. Each branch has a collection of books. Members can borrow up to 5 books at a time and must return them within 14 days. A librarian can add or remove books from the catalog. The system tracks fines for overdue books. Each book has a title, author, ISBN, and publication year."
Extracted nouns: library, branches, books, members, librarian, catalog, fines, title, author, ISBN, publication year, days.
That is twelve nouns from one paragraph. Not all of them will become classes. The next step separates signal from noise.
Step 2: Filter the noise
Apply three filters to your noun list:
| Filter | Rule | Examples dropped |
|---|---|---|
| Too vague | System-level or abstract nouns that do not map to a concrete thing | "system", "collection", "time" |
| Primitive attribute | Things that are best represented as a field on another class | "title", "ISBN", "publication year", "days" |
| Duplicate / synonym | Same concept with different names | "catalog" = "collection of books" |
After filtering, our library example shrinks from twelve nouns to a focused set:
| Noun | Verdict | Reasoning |
|---|---|---|
| Library | Entity | Top-level container, has branches |
| Branch | Entity | Distinct location with its own book collection |
| Book | Entity | Core domain object with its own identity and lifecycle |
| Member | Entity | Actor who borrows books |
| Librarian | Entity | Actor who manages the catalog |
| Fine | Entity | Has its own amount, status, calculation rules |
| Catalog | Drop | Synonym for "the set of books in a branch" |
| Title | Attribute | String field on Book |
| Author | Promote? | Could be an entity if books share authors. Explore further. |
| ISBN | Attribute | String field on Book |
| Publication year | Attribute | int field on Book |
| Days | Drop | Constraint (14-day limit), not a thing |
Step 3: Promote hidden entities
Some nouns start as attributes but deserve promotion to full entities. The author example above is a good case. If books share authors and you need to query "all books by this author," then Author should be its own class with a name, biography, and a list of books. If authors are just a display string, keep it as a field.
The verb "borrow" also hides an entity. A borrowing event has a start date, due date, return date, and status. That is too much state for a simple field. It deserves its own class: Loan or BorrowRecord.
Look for hidden entities in the verbs. "Reserve," "borrow," and "pay" are actions that may carry state. When an action has a date, status, participants, or multiple attributes, consider modeling it explicitly.
With practice, this three-step process can be done quickly. Write it down before you touch code so that later classes follow an intentional model.
Entity vs. attribute: when something deserves its own class
This is a common modeling question. Is "Address" a class or a group of fields on Member? Is "Author" its own class or a String? The following heuristic helps make the choice explicit.
Promote to a class when any of these are true:
-
It has its own identity. Can two different instances of this thing exist with different attributes? Two authors can have the same name but different biographies. That is identity. A title string does not have identity.
-
It participates in multiple relationships. If
Authoris referenced byBookand also byEvent(author signing events), it needs to be shared. Shared things need to be entities. -
It has behavior. An
Addressthat just holds street/city/zip is a value object (or even just fields). AnAddressthat can validate itself, format for different locales, or calculate shipping zones has behavior. Behavior means class. -
It changes independently. If the author's biography changes, should every book record update? If yes,
Authoris a shared entity. If no, it is just a copied string.
Here is the decision as a quick flowchart:
Use this decision tree as a prompt for discussion, not as an automatic rule. One "yes" is evidence that a class may be useful; confirm the scope, lifecycle, and behavior before promoting it. If the concept is still simple and local to one entity, a field or value object may be the clearer choice.
The String trap
The most common entity-modeling mistake is representing complex concepts as Strings. String status should be an enum. String address should be a value object. String author might need to be a class. If you find yourself writing String for something with rules or validation, stop and reconsider.
Discovering relationships
Once you have your entities, you need to connect them. Relationships come from verbs and ownership semantics in the requirements.
Read the verbs
Go back to the requirements and underline the verbs this time:
"Members can borrow up to 5 books. A librarian can add or remove books. The system tracks fines."
Each verb implies a relationship:
- "borrow" connects Member to Book (through a Loan)
- "add/remove" connects Librarian to Book
- "tracks" connects the system to Fine (Fine belongs to a Loan)
Classify the relationship type
Use ownership and lifecycle to classify:
| Relationship | Test question | Example |
|---|---|---|
| Association | "Does A know about B, but neither controls the other's lifetime?" | Teacher knows Student |
| Aggregation | "Does A contain B, but B can exist without A?" | Department contains Employees (employees survive if dept is dissolved) |
| Composition | "Does A own B, and B dies when A dies?" | House owns Rooms (rooms disappear if house is demolished) |
| Inheritance | "Is B a specialized version of A?" | EBook is a Book |
For the library system, the relationships can be described as follows:
- Library composes Branches (destroy the library, branches go too)
- Branch aggregates Books (a book can be transferred between branches)
- Member associates with Book through Loan (neither owns the other)
- Loan composes Fine (no loan, no fine)
- Librarian is-a specialized Member, or a separate role/actor if permissions are orthogonal to membership
Composition and aggregation are useful shorthand for lifecycle intent, but implementations do not need to force a particular UML ownership form. If a library branch can be moved or managed independently, make that lifecycle assumption explicit and model the association accordingly.
Map the multiplicity
Every relationship needs a count on both sides. Ask: "How many Bs can one A have? How many As can one B belong to?"
| Relationship | Multiplicity | Reasoning |
|---|---|---|
| Library to Branch | 1 to many | One library, multiple branches |
| Branch to Book | 1 to many | One branch holds many books |
| Member to Loan | 1 to many | One member, up to 5 active loans |
| Loan to Book | 1 to 1 | Each loan is for exactly one book |
| Loan to Fine | 1 to 0..1 | A loan may or may not generate a fine |
Put all of this into a class diagram and you have your entity model:
That diagram can be derived quickly and gives the reader a compact view of the domain, relationships, multiplicity, and ownership assumptions.
Worked example: "Design a Library Management System"
Let me walk through the full process end to end, exactly as you would do it on a whiteboard.
Requirements (given by interviewer)
"Build a library management system. The library has branches in different locations. Each branch maintains a catalog of books. Members register with the library and can borrow books from any branch. There is a limit of 5 books per member. Books must be returned within 14 days or a fine is charged. Librarians manage the inventory. Members can also reserve books that are currently checked out."
Round 1: Noun extraction
I read through and highlight every noun:
library, branches, locations, catalog, books, members, library (dup), books (dup), branch (dup), limit, books (dup), member (dup), days, fine, librarians, inventory, members (dup), books (dup), reservation.
Deduplicated noun list: library, branch, location, catalog, book, member, limit, days, fine, librarian, inventory, reservation.
Round 2: Filter and classify
| Noun | Verdict | Reasoning |
|---|---|---|
| Library | Entity | Top-level aggregate |
| Branch | Entity | Has its own location, catalog, and identity |
| Location | Attribute | String/value on Branch |
| Catalog | Drop | Just "the books in a branch" |
| Book | Entity | Core domain object |
| Member | Entity | Actor with registration, borrowing rules |
| Limit | Drop | Business rule (constant = 5), not a thing |
| Days | Drop | Business rule (constant = 14) |
| Fine | Entity | Has amount, status, calculation logic |
| Librarian | Entity | Different permissions than Member |
| Inventory | Drop | Synonym for "books in a branch" |
| Reservation | Entity | Hidden in verb "reserve." Has status, dates, expiry logic. |
Round 3: Discover hidden entities from verbs
| Verb | Hidden entity | Why |
|---|---|---|
| borrow | Loan | Tracks borrow date, due date, return date, status |
| reserve | Reservation | Tracks reserved date, expiry, notification status |
| register | No | Registration is a one-time action, Member covers it |
| charge (a fine) | Fine (already found) |
Final entity list
Eight core entities: Library, Branch, Book, Member, Librarian, Loan, Reservation, Fine. Author remains optional here: promote it when author-level metadata or queries are in scope; otherwise keep the author value on Book.
This list is small enough to support the stated flows while still representing the important lifecycles. The exact count depends on scope: a narrower prompt may need fewer entities, while reservations, payments, or notifications may justify more.
Assigning attributes
For each entity, start with 3-5 attributes that drive the stated behavior. Add more only when a use case or invariant needs them.
public class Book {
private String isbn;
private String title;
private Author author;
private int publicationYear;
private BookStatus status; // AVAILABLE, CHECKED_OUT, RESERVED, LOST
}
public class Member {
private String memberId;
private String name;
private String email;
private List<Loan> activeLoans;
private List<Reservation> reservations;
}
public class Loan {
private Member member;
private Book book;
private LocalDate borrowDate;
private LocalDate dueDate;
private LocalDate returnDate;
private LoanStatus status; // ACTIVE, RETURNED, OVERDUE
}
public class Reservation {
private Member member;
private Book book;
private LocalDate reservedDate;
private LocalDate expiryDate;
private ReservationStatus status; // PENDING, FULFILLED, EXPIRED, CANCELLED
}
Notice the pattern: the stateful entities have identity, a status enum where a fixed lifecycle exists, and a few domain-relevant fields. Treat this as a starting template, not a requirement for every class.
Interview tip: use enums for status
When an entity has a small, fixed set of states (a loan that is active, returned, or overdue), an enum makes the lifecycle explicit. If each state later gains substantially different behavior, that enum can become a candidate for the State pattern.
The responsibility test
You have your entities and their attributes. Now stress-test the model. The responsibility test asks one question for every pair of entities:
"Do these two things change for different reasons?"
If yes, they should be separate classes. If they always change together and for the same reason, maybe they should merge.
This comes from the Single Responsibility Principle, but applied at the entity level rather than the method level.
Applying the test
| Pair | Change together? | Verdict |
|---|---|---|
| Book and Author | No. Author's biography changes independently of book data. | Separate classes. |
| Loan and Fine | Partially. A fine only exists because of a loan, but fine calculation rules change independently (e.g., new fine policy). | Separate classes, composed. |
| Member and Librarian | They share identity fields but have different permissions and operations. | Separate classes (or Librarian extends Member). |
| Branch and Library | A branch's catalog changes independently of other branches. Library just groups them. | Separate classes, composed. |
| Loan and Reservation | Different lifecycles. A reservation becomes a loan but they track different data. | Separate classes. |
If you find two entities that always change together and share the same lifecycle, merge them. For instance, if Address only ever appears as part of Branch and never independently, it might just be fields on Branch rather than its own class.
The inverse mistake is keeping things merged that should be separate. If you have a Book class with borrowerName, borrowDate, and dueDate fields directly on it, you have merged Book with Loan. Split them: a book can exist without being borrowed, and it can have many loans over time.
Trade-offs and adapting the model to constraints
Entity modeling is a scope decision as well as a naming exercise.
- Tight time or narrow scope: model the entities that participate in the core use cases first. Defer reporting, notifications, and infrastructure unless they change the domain behavior being discussed.
- Simple concept: keep a value as a field or value object when it has no independent lifecycle or relationship.
Branch.locationcan be a value object until the requirements introduce location-level behavior. - Stateful interaction: use a through entity when a relationship has its own dates, status, amounts, or history. If it has none of those, a direct association may be enough.
- Uncertain future behavior: do not create subclasses for hypothetical differences. Prefer an enum or composition until behavior—not just data—diverges.
- Overlapping roles: use a shared
User/role model or composition when one person can be both a member and a librarian. Use inheritance only when the subtype really is substitutable for the base type. - Changing requirements: re-run the noun, verb, and responsibility checks after a new use case. A good model is easy to extend because its boundaries match the current reasons to change.
30-second and 5-minute explanations
30-second explanation
"I treat nouns as candidates rather than automatically making each one a class. I filter vague, primitive, and duplicate terms, then promote concepts that have identity, behavior, an independent lifecycle, or meaningful relationships. Next I read the verbs to find associations and through entities such as Loan, assign multiplicity and ownership, and test the model against one core scenario."
5-minute explanation
Start with a short requirement and extract its nouns without judging them. Classify each as an entity, attribute/value object, duplicate, or constraint; then inspect verbs such as borrow, reserve, and pay for stateful interactions. For each surviving entity, assign only the fields needed by the use cases, map relationships and multiplicity, and apply the responsibility test. Walk through the library example: Member and Book connect through Loan, Reservation has its own lifecycle, and Fine is separate when its policy changes independently. Close by explaining when you would collapse a simple concept into a field or promote it as new behavior appears.
Common entity mistakes
These are common patterns that make an interview model harder to evolve or explain.
1. Splitting too early
Creating HardcoverBook, PaperbackBook, AudioBook as separate classes before you know whether the system treats them differently. Premature inheritance creates rigid hierarchies. Start with a single Book class and a BookFormat enum. Only split into subclasses when the behavior genuinely differs (e.g., AudioBook has a duration field and a streaming method that others do not).
The rule of thumb: if the only difference is data (fields), use composition or an enum. If the difference is behavior (methods), consider inheritance.
2. Merging too much
The opposite problem. Stuffing everything into three mega-classes: Library, Book, User. A class with 20 fields and 15 methods is a sign you missed entities. If your User class has borrowBook(), returnBook(), payFine(), reserveBook(), addBook(), removeBook(), you have merged Member and Librarian concerns.
Break it up. Each class should have one clear reason to exist.
3. Naming things wrong
Names matter more than candidates think. Common naming mistakes:
| Bad name | Problem | Better name |
|---|---|---|
Data | Meaningless | Name it by what data: BookRecord, LoanDetails |
Manager | Vague, becomes a god class | LoanService, CatalogManager with a focused scope |
Info | Same as Data | MemberProfile, BookMetadata |
Helper / Util | Dumping ground | Move methods to the entity they operate on |
Object suffix | Redundant (everything is an object) | Drop it: Book not BookObject |
Class names are part of the model's communication. BorrowRecord explains the domain concept; DataObject1 does not give the reader enough information to place the class.
4. Forgetting enums
When you see a concept with a fixed set of values (book status, loan state, member type), model it as an enum. Not as a String, not as an int, not as a boolean. Enums are self-documenting and type-safe.
public enum BookStatus {
AVAILABLE,
CHECKED_OUT,
RESERVED,
LOST,
UNDER_MAINTENANCE
}
This is a small choice that makes the allowed states explicit and prevents invalid string values.
5. Ignoring the "through" entity
"Members borrow books" does not necessarily mean Member has a direct reference to Book. The borrowing action itself (the Loan) is an entity. When two entities interact through a time-bound, stateful process, a "through" entity may be hiding in the verb.
Other examples: Enrollment between Student and Course. Payment between Customer and Order. Appointment between Doctor and Patient. Miss these and your model becomes a tangled web of direct many-to-many references.
Test Your Understanding
Quick recap
-
Entity discovery is a structured process with judgment. Extract nouns, filter noise, and promote hidden entities from verbs.
-
Use the noun-extraction technique: read requirements, highlight nouns, apply three filters (too vague, primitive attribute, duplicate).
-
Promote a noun to a class when it has its own identity, participates in multiple relationships, has behavior, or changes independently.
-
Discover relationships by reading verbs and classifying ownership: association (knows about), aggregation (contains but does not own), composition (owns, dies together).
-
Apply the responsibility test to every entity pair: "Do these change for different reasons?" If yes, keep them separate.
-
Watch for through entities hiding in verbs. "Borrow," "reserve," "enroll," and "pay" often produce their own class when the interaction carries state or history.
-
Name your classes after domain concepts (Book, Loan, Reservation), not technical roles (Manager, Helper, Data).
Related concepts
- OOD interview approach covers the full 5-step framework for LLD interviews, including how entity discovery fits into the bigger picture.
- Association explains the baseline relationship type where objects know about each other without ownership.
- Aggregation covers the "contains but does not own" relationship, with lifecycle semantics.
- Composition is the strongest relationship: the container owns and controls the contained object's lifetime.