Bird
Raised Fist0

Design LinkedIn in OOP - Profile, Connection, Feed, Job, Recommendation

LLDmediumInterview freq: medium
Choose your preparation mode4 modes available
🏗️
Design LinkedIn in OOP - Profile, Connection, Feed, Job, Recommendation
Model LinkedIn core features with extensible, thread-safe Java classes emphasizing SOLID principles and concurrency correctness.
mediumSocial and Professional PlatformsFreq: medium
Prerequisites:OOP FundamentalsJava concurrency basicsSOLID principles
⚙️
Functional Requirements
  • Users can create and edit their profiles with professional details
  • Users can send, accept, and remove connections
  • Users can post feed updates visible to connections
  • Recruiters can post jobs and users can search and apply
  • System generates personalized recommendations for jobs and connections
  • Support concurrent updates to profiles and connections without data corruption
  • Feed updates should be consistent and reflect latest posts
👤
Use Cases
  • Create and update user profiles
  • Send and accept connection requests
  • Post and view feed updates
  • Post and search jobs
  • Generate job and connection recommendations
🧑‍💻
Actors
  • User
  • Recruiter
  • System Administrator
  • External Job Aggregator
❓
Clarifying Questions to Ask
  • How many concurrent users/threads are expected to update profiles or connections simultaneously?
  • Should the system support eventual consistency or strong consistency for feeds?
  • Is there a pricing or subscription model affecting job posting visibility?
  • How to handle edge cases like circular connections or duplicate connection requests?
  • Are recommendations computed synchronously or asynchronously?
Out of Scope
✗ Messaging between users
✗ End-to-end job application workflow
✗ Analytics and reporting
✗ Notification system
⚡
QPS Calculation
read qps5000
write qps1000
🖥️
Server Estimate
app servers20
db servers5
🔢
Enumerations
enum ConnectionStatus
PENDING | ACCEPTED | DECLINED | BLOCKED
Represents connection request states to prevent invalid states and enable exhaustive switch-case handling.
enum JobType
FULL_TIME | PART_TIME | CONTRACT | INTERNSHIP
Defines job categories to avoid string typos and support type-safe job filtering.
enum FeedPostType
TEXT | IMAGE | VIDEO | ARTICLE
Differentiates feed post content types for rendering and processing logic.
📦
UserProfile
7 fields
private final String userIdprivate volatile String nameprivate volatile String headlineprivate volatile String summaryprivate volatile List<String> skillsprivate volatile List<Education> educationListprivate volatile List<Experience> experienceList
Maintain user professional details with thread-safe updates and provide profile data access.
public synchronized void updateHeadline(String newHeadline)Atomically updates the user's headline to prevent race conditions.
public synchronized void addSkill(String skill)Adds a skill to the profile ensuring thread-safe modification of the skills list.
public synchronized String getProfileSummary()Returns a consistent snapshot of the profile summary.
📦
Connection
5 fields
private final String connectionIdprivate final String userId1private final String userId2private volatile ConnectionStatus statusprivate final long createdTimestamp
Represents a connection relationship between two users with status management.
public synchronized boolean acceptConnection()Atomically changes status from PENDING to ACCEPTED.
public synchronized boolean declineConnection()Atomically changes status from PENDING to DECLINED.
public ConnectionStatus getStatus()Returns the current connection status.
📦
FeedPost
5 fields
private final String postIdprivate final String authorUserIdprivate volatile String contentprivate final FeedPostType postTypeprivate final long timestamp
Represents a feed post with content and metadata, supporting thread-safe content updates.
public synchronized void updateContent(String newContent)Updates the post content atomically.
public String getContent()Returns the current content of the post.
📦
JobPosting
7 fields
private final String jobIdprivate final String recruiterUserIdprivate volatile String titleprivate volatile String descriptionprivate volatile JobType jobTypeprivate volatile String locationprivate final long postedTimestamp
Stores job posting details with thread-safe updates for recruiter modifications.
public synchronized void updateJobDescription(String newDescription)Atomically updates the job description.
public synchronized String getJobSummary()Returns a consistent snapshot of job details.
📦
RecommendationEngine
2 fields
private volatile Map<String, List<String>> userJobRecommendationsprivate volatile Map<String, List<String>> userConnectionRecommendations
Generates and caches job and connection recommendations per user with thread-safe updates.
public synchronized void updateJobRecommendations(String userId, List<String> jobIds)Atomically updates job recommendations for a user.
public synchronized List<String> getJobRecommendations(String userId)Returns current job recommendations for a user.
public synchronized void updateConnectionRecommendations(String userId, List<String> userIds)Atomically updates connection recommendations for a user.
📦
Education
4 fields
private final String institutionprivate final String degreeprivate final int startYearprivate final int endYear
Immutable value object representing education details.
📦
Experience
4 fields
private final String companyprivate final String roleprivate final int startYearprivate final int endYear
Immutable value object representing work experience.
🔗
Relationships
UserProfile──►Connection[1..*]
association
🗄️
UserProfiles
PK: userId
userId STRINGname STRINGheadline STRINGsummary STRINGskills LIST<STRING>education LIST<STRUCT>experience LIST<STRUCT>
🗄️
Connections
PK: userId1
connectionId STRINGuserId1 STRINGuserId2 STRINGstatus STRINGcreatedTimestamp BIGINT
🔌
/user/profile/updateHeadline
Request
{
  "userId": "String",
  "newHeadline": "String"
}
Response
{
  "success": "boolean",
  "message": "String"
}
Updates the headline of a user profile atomically.
🔌
/connection/request
Request
{
  "fromUserId": "String",
  "toUserId": "String"
}
Response
{
  "success": "boolean",
  "message": "String"
}
Sends a connection request from one user to another.
🔌
/job/search
Request
{
  "keywords": "String",
  "location": "String",
  "jobType": "JobType"
}
Response
{
  "jobPostings": "List<JobPosting>"
}
Searches job postings based on filters.

Practice

(1/5)
1. In the Online Stock Brokerage system, the TradeManager class has a private constructor and a static synchronized getInstance() method. Which design pattern is applied here and why is this the correct choice?
easy
A. Prototype pattern, to clone existing trade instances for faster processing.
B. Factory pattern, because it controls object creation centrally for different trade types.
C. Builder pattern, to incrementally construct complex trade objects with validation.
D. Singleton pattern, to ensure only one instance manages all trades and avoid inconsistent state.

Solution

  1. Step 1: Identify the pattern from constructor and method

    The private constructor prevents external instantiation, and the static synchronized getInstance() method ensures a single instance is created and accessed thread-safely.
  2. Step 2: Why Singleton fits this scenario

    TradeManager must coordinate all trades globally to maintain consistent state; multiple instances would cause conflicting trade states.
  3. Final Answer:

    Option D -> Option D
  4. Quick Check:

    Private constructor + synchronized getInstance() -> Singleton pattern [check]
Hint: Private constructor + static synchronized getInstance() -> Singleton [check]
Common Mistakes:
2. In a UML class diagram, should Vehicle be modeled as an abstract class or an interface if it has state like speed and behavior like accelerate()? Why?
easy
A. Interface, because it allows multiple inheritance and defines behavior without state.
B. Abstract class, because it can hold shared state and provide default behavior implementations.
C. Interface, because state can be stored externally and behavior defined via default methods.
D. Abstract class, because interfaces cannot declare methods with parameters.

Solution

  1. Step 1: Analyze state and behavior requirements

    Vehicle has state (speed) and behavior (accelerate()), so it needs a construct that supports instance variables and method implementations.
  2. Step 2: Evaluate abstract class vs interface

    Abstract classes can hold state and provide default behavior; interfaces cannot hold instance state (only constants) and default methods can't maintain state.
  3. Final Answer:

    Option B -> Option B
  4. Quick Check:

    State + behavior with shared code -> abstract class [check]
Hint: Stateful base class -> abstract class, not interface [check]
Common Mistakes:
3. You want to add a WeekendBonusRule that gives players extra moves on weekends without modifying existing classes. Which SOLID principle guides the minimal change, and what is the correct approach?
medium
A. Single Responsibility Principle: add weekend logic inside the Player class.
B. Open/Closed Principle: create a new class implementing a MoveRule interface and inject it into the game engine.
C. Liskov Substitution Principle: subclass Player to WeekendPlayer with bonus logic.
D. Dependency Inversion Principle: make Player depend on concrete WeekendBonusRule.

Solution

  1. Step 1: Identify SOLID principle for extension without modification

    Open/Closed Principle (OCP) states software entities should be open for extension but closed for modification.
  2. Step 2: Evaluate approaches

    Subclassing Player to WeekendPlayer allows extension without modifying Player; injecting new MoveRule class also respects OCP but requires interface design.
  3. Final Answer:

    Option C -> Option C
  4. Quick Check:

    Subclassing extends behavior without modifying base class [check]
Hint: Extend via subclass or interface, don't modify existing classes [check]
Common Mistakes:
4. In the Blackjack game, if the placeBet() method is not synchronized, which exact thread interleaving causes a player to double-bet?
medium
A. Thread 1 places bet, Thread 2 waits for Thread 1 to finish, then places bet safely
B. Thread 1 reads balance, Thread 2 reads balance, both update balance simultaneously without conflict
C. Thread 1 checks balance sufficient -> true, context switch, Thread 2 checks balance sufficient -> true, both place bets reducing balance incorrectly
D. Thread 1 and Thread 2 both fail to update balance due to deadlock

Solution

  1. Step 1: Identify check-then-act race condition

    Without synchronization, Thread 1 reads balance sufficient and is preempted before updating; Thread 2 also reads balance sufficient and proceeds.
  2. Step 2: Both threads place bets reducing balance twice, causing double-bet

    This classic check-then-act gap leads to inconsistent state and double deduction.
  3. Final Answer:

    Option C -> Option C
  4. Quick Check:

    Unsynchronized check-then-act -> double bet race condition [check]
Hint: Check balance -> context switch -> both bet -> double deduction [check]
Common Mistakes:
5. You want to add a WeekendFeeStrategy to calculate weekend parking fees without modifying existing classes. Which SOLID principle guides the minimum change, and what is the correct approach?
medium
A. Modify the ParkingLot class to add weekend fee logic, enforcing Single Responsibility Principle.
B. Add weekend fee logic inside existing FeeStrategy implementations, following Dependency Inversion Principle.
C. Create a WeekendFeeStrategy subclass of ParkingLot to override fee calculation, following Liskov Substitution Principle.
D. Create a new WeekendFeeStrategy class implementing FeeStrategy interface, and inject it where needed, following Open/Closed Principle.

Solution

  1. Step 1: Identify the SOLID principle for extensibility

    Open/Closed Principle (OCP) requires adding new functionality without modifying existing code.
  2. Step 2: Evaluate approaches

    Creating a new FeeStrategy implementation and injecting it respects OCP and DIP; modifying ParkingLot or existing strategies violates OCP or mixes responsibilities.
  3. Final Answer:

    Option B -> Option B
  4. Quick Check:

    New FeeStrategy class + injection -> OCP and DIP respected [check]
Hint: New strategy class + injection -> Open/Closed Principle [check]
Common Mistakes:
Recommended

Ready to prove it?

Pass the test and this pattern moves unknown strong while earning +1 Grip toward your certificate.

10 questions~5 mineasy hard