OOD - LinkedIn
1. Problem Statement
LinkedIn operates as the world's largest professional networking platform, serving millions of professionals who leverage the platform to build career identities, discover opportunities, share industry insights, and cultivate meaningful business relationships. The system must support comprehensive user profiles encompassing work history, educational background, professional skills, certifications, publications, and recommendations while enabling members to articulate their career narratives through rich multimedia content. Beyond static profiles, the platform facilitates dynamic professional interactions through a sophisticated feed algorithm that surfaces relevant content, job postings, company updates, and thought leadership articles tailored to each member's professional interests and network activity.
The operational complexity extends to managing intricate connection networks where professionals send and accept connection invitations, endorse skills, write recommendations, and follow companies and influencers. The system must handle real-time messaging conversations, support group discussions around professional topics, enable company pages for employer branding, and provide a robust job marketplace where recruiters post positions and candidates apply with one-click submissions. Privacy controls must allow members to control profile visibility, manage who can see their activity, and decide whether they appear in search results, while the platform tracks engagement metrics including profile views, post impressions, and search appearances to provide actionable insights.
Furthermore, the architecture must address scalability challenges including handling millions of concurrent users browsing feeds, searching for connections, and receiving real-time notifications about network activity, job recommendations, and content interactions. The system needs to implement sophisticated recommendation algorithms for "People You May Know" suggestions based on mutual connections and shared professional attributes, surface relevant job postings through collaborative filtering and content-based matching, and rank feed content using signals like recency, engagement likelihood, and network proximity. Edge cases include managing connection invitation spam through rate limiting, handling account compromises and security incidents, supporting premium membership tiers with enhanced features, and ensuring GDPR compliance for user data management and export capabilities.
2. System Requirements
We'll focus on the following set of requirements while designing LinkedIn:
Functional Requirements:
- Members can create and maintain comprehensive professional profiles with experiences, education, skills, certifications, and accomplishments
- The system should support sending, accepting, and withdrawing connection invitations between members
- Members can follow other members and companies to receive updates in their feed
- The system should enable creating posts, articles, comments, likes, and shares
- Members can send direct messages to their connections and participate in group conversations
- The system should support skill endorsements and written recommendations between connections
- Companies can create company pages with employee rosters, job postings, and company updates
- Members can search for people, companies, jobs, groups, and content
- The system should send notifications for connection requests, messages, profile views, and content interactions
- Members can create and join professional groups with discussion threads
- The system should track and display profile analytics (who viewed your profile, search appearances)
- Companies can post job listings and members can apply with saved application materials
Non-Functional Requirements:
- Scalability: Support hundreds of millions of active users with millions of concurrent sessions
- Performance: Feed generation should complete within 2 seconds; search results within 1 second
- Privacy: Granular privacy controls for profile visibility, activity broadcasting, and search appearance
- Security: Implement account verification, spam prevention, and secure credential management
- Availability: 99.9% uptime for core features (profiles, messaging, feed)
- Data Consistency: Ensure connection counts, follower counts, and engagement metrics remain accurate
3. Use Case Diagram
Here are the main actors in our system:
Actors:
- 👤 Member: Professional users who create profiles, connect with others, share content, and search for opportunities
- 🏢 Company Admin: Representatives who manage company pages, post jobs, and publish company updates
- 👨💼 Recruiter: Hiring managers who post job listings, search candidates, and manage applications
- 👥 Group Admin: Members who moderate professional groups and manage discussions
- 🔧 System Administrator: Platform admins who manage accounts, handle security, and moderate content
- 🤖 System: Automated services for notifications, recommendations, and feed generation
Use Cases:
Profile Management:
- Add/Update Profile Information
- Add Work Experience
- Add Education
- Add Skills & Endorsements
- Upload Profile Photo/Banner
- Request Recommendation
- Write Recommendation
Networking:
- Send Connection Invitation
- Accept/Decline Connection Request
- Withdraw Connection Invitation
- Remove Connection
- Follow Member/Company
- Unfollow Member/Company
- Endorse Skills
Content & Engagement:
- Create Post/Article
- Comment on Post
- Like/React to Content
- Share Content
- View Feed
- Save Post for Later
Messaging:
- Send Direct Message
- Create Group Conversation
- Send Message Attachment
- Mark Message as Read
Search & Discovery:
- Search Members
- Search Companies
- Search Jobs
- Search Groups
- Get "People You May Know" Recommendations
- Get Job Recommendations
Jobs:
- Post Job Listing
- Apply to Job
- Save Job
- View Applications
- Close Job Posting
Company Pages:
- Create Company Page
- Update Company Information
- Post Company Update
- Add Employees
- View Company Analytics
Groups:
- Create Group
- Join Group
- Post in Group
- Moderate Group Content
Notifications & Analytics:
- Send Notifications (Connection, Message, Engagement)
- View Profile Analytics
- View Post Analytics
- View "Who Viewed Your Profile"
graph LR %% Actors Member[👤 Member] CompanyAdmin[🏢 Company Admin] Recruiter[👨💼 Recruiter] GroupAdmin[👥 Group Admin] SysAdmin[🔧 System Admin] System[🤖 System] %% Profile Management (Blue) subgraph ProfileMgmt["📋 Profile Management"] UC1[Update Profile] UC2[Add Experience] UC3[Add Education] UC4[Manage Skills] UC5[Request/Write Recommendation] end %% Networking (Green) subgraph Networking["🤝 Networking"] UC6[Send Connection Invitation] UC7[Accept/Decline Connection] UC8[Follow/Unfollow] UC9[Endorse Skills] end %% Content (Purple) subgraph Content["📱 Content & Engagement"] UC10[Create Post/Article] UC11[Comment/Like/Share] UC12[View Feed] UC13[Save Content] end %% Messaging (Orange) subgraph Messaging["💬 Messaging"] UC14[Send Direct Message] UC15[Group Conversation] end %% Search (Yellow) subgraph Search["🔍 Search & Discovery"] UC16[Search Members/Companies] UC17[Search Jobs] UC18[Get Recommendations] end %% Jobs (Red) subgraph Jobs["💼 Jobs"] UC19[Post Job Listing] UC20[Apply to Job] UC21[Manage Applications] end %% Company (Teal) subgraph Company["🏭 Company Pages"] UC22[Manage Company Page] UC23[Post Company Update] UC24[View Analytics] end %% Groups (Pink) subgraph Groups["👥 Groups"] UC25[Create/Join Group] UC26[Post in Group] UC27[Moderate Group] end %% Notifications (Gray) subgraph Notifications["🔔 Notifications & Analytics"] UC28[Send Notifications] UC29[View Profile Analytics] UC30[Who Viewed Profile] end %% Actor Relationships Member --> UC1 Member --> UC2 Member --> UC3 Member --> UC4 Member --> UC5 Member --> UC6 Member --> UC7 Member --> UC8 Member --> UC9 Member --> UC10 Member --> UC11 Member --> UC12 Member --> UC13 Member --> UC14 Member --> UC15 Member --> UC16 Member --> UC17 Member --> UC18 Member --> UC20 Member --> UC25 Member --> UC26 Member --> UC29 Member --> UC30 CompanyAdmin --> UC22 CompanyAdmin --> UC23 CompanyAdmin --> UC24 Recruiter --> UC19 Recruiter --> UC21 Recruiter --> UC16 GroupAdmin --> UC27 SysAdmin --> UC1 SysAdmin --> UC22 System --> UC28 System --> UC18 %% Styling classDef profileStyle fill:#e3f2fd,stroke:#1976d2,stroke-width:2px classDef networkStyle fill:#e8f5e9,stroke:#388e3c,stroke-width:2px classDef contentStyle fill:#f3e5f5,stroke:#7b1fa2,stroke-width:2px classDef messageStyle fill:#fff3e0,stroke:#f57c00,stroke-width:2px classDef searchStyle fill:#fffde7,stroke:#fbc02d,stroke-width:2px classDef jobStyle fill:#ffebee,stroke:#c62828,stroke-width:2px classDef companyStyle fill:#e0f2f1,stroke:#00796b,stroke-width:2px classDef groupStyle fill:#fce4ec,stroke:#c2185b,stroke-width:2px classDef notifStyle fill:#eceff1,stroke:#455a64,stroke-width:2px class UC1,UC2,UC3,UC4,UC5 profileStyle class UC6,UC7,UC8,UC9 networkStyle class UC10,UC11,UC12,UC13 contentStyle class UC14,UC15 messageStyle class UC16,UC17,UC18 searchStyle class UC19,UC20,UC21 jobStyle class UC22,UC23,UC24 companyStyle class UC25,UC26,UC27 groupStyle class UC28,UC29,UC30 notifStyle
4. Class Diagram
Key classes and responsibilities:
- Account / Person / Member / Admin: User account hierarchy with authentication and profile management
- Profile / Experience / Education / Skill / Accomplishment: Rich profile composition
- ConnectionInvitation: Managing connection request lifecycle
- Post / Comment / Article: Content creation and engagement
- Message / Conversation: Direct messaging between members
- Company / CompanyPage / JobPosting: Company presence and recruiting
- Group / GroupMember: Professional communities
- Notification: Event-driven alerts
- Search / SearchIndex: Discovery and recommendations
- ProfileStats: Analytics and insights
classDiagram %% Core Account Classes class Account { <<abstract>> -String id -String password -AccountStatus status -LocalDateTime createdAt +resetPassword(String, String): boolean +updateStatus(AccountStatus) } class AccountStatus { <<enumeration>> ACTIVE BLOCKED BANNED COMPROMISED ARCHIVED UNKNOWN } class Person { <<abstract>> -String name -Address address -String email -String phone -Account account } class Member { -LocalDate dateOfMembership -String headline -byte[] photo -Profile profile -List~Member~ connections -List~Member~ following -List~Company~ followingCompanies -List~Group~ groups -List~ConnectionInvitation~ sentInvitations -List~ConnectionInvitation~ receivedInvitations +sendMessage(Message): boolean +createPost(Post): boolean +sendConnectionInvitation(Member): ConnectionInvitation +acceptConnectionInvitation(ConnectionInvitation): boolean +followMember(Member): boolean +followCompany(Company): boolean +endorseSkill(Member, Skill): boolean } class Admin { +blockUser(Member): boolean +unblockUser(Member): boolean +removeContent(Post): boolean } class Address { -String streetAddress -String city -String state -String zipCode -String country } %% Profile Components class Profile { -String summary -List~Experience~ experiences -List~Education~ educations -List~Skill~ skills -List~Accomplishment~ accomplishments -List~Recommendation~ recommendations -ProfileStats stats +addExperience(Experience) +addEducation(Education) +addSkill(Skill) +addAccomplishment(Accomplishment) +requestRecommendation(Member): Recommendation } class Experience { -String title -String company -String location -LocalDate dateFrom -LocalDate dateTo -String description -boolean isCurrent } class Education { -String school -String degree -String fieldOfStudy -LocalDate startDate -LocalDate endDate -String grade -String activities } class Skill { -String name -String category -int endorsementCount +incrementEndorsements() } class Accomplishment { <<enumeration>> CERTIFICATION PUBLICATION PATENT COURSE PROJECT HONOR_AWARD TEST_SCORE LANGUAGE } class Recommendation { -Member recommender -Member recommendee -String text -LocalDateTime createdAt -RecommendationStatus status } class RecommendationStatus { <<enumeration>> PENDING ACCEPTED REJECTED } class ProfileStats { -int profileViews -int searchAppearances -int postImpressions -List~ProfileView~ recentViewers +recordView(Member) +getViewsLast90Days(): int } class ProfileView { -Member viewer -LocalDateTime viewedAt -boolean isAnonymous } %% Connection Management class ConnectionInvitation { -String invitationId -Member sender -Member receiver -LocalDateTime sentAt -String message -ConnectionInvitationStatus status +accept(): boolean +reject(): boolean +withdraw(): boolean } class ConnectionInvitationStatus { <<enumeration>> PENDING ACCEPTED CONFIRMED REJECTED CANCELED WITHDRAWN } %% Content Classes class Post { -String postId -String text -byte[] media -Member owner -LocalDateTime createdAt -int totalLikes -int totalShares -int totalComments -List~Comment~ comments -List~Member~ likedBy -PostPrivacy privacy +addComment(Comment) +like(Member) +share(Member) } class PostPrivacy { <<enumeration>> PUBLIC CONNECTIONS PRIVATE } class Comment { -String commentId -String text -Member author -LocalDateTime createdAt -List~Comment~ replies +addReply(Comment) } class Article { -String articleId -String title -String content -Member author -LocalDateTime publishedAt -List~String~ tags -int viewCount } %% Messaging class Message { -String messageId -Member sender -List~Member~ recipients -String body -byte[] attachments -LocalDateTime sentAt -boolean isRead +markAsRead() } class Conversation { -String conversationId -List~Member~ participants -List~Message~ messages -LocalDateTime lastMessageAt +addMessage(Message) +addParticipant(Member) } %% Company & Jobs class Company { -String companyId -String name -String description -CompanyType type -CompanySize size -Address location -CompanyPage page -List~JobPosting~ activeJobPostings -List~Member~ employees -List~Member~ followers +postJob(JobPosting) +addEmployee(Member) } class CompanyType { <<enumeration>> PUBLIC_COMPANY PRIVATE NONPROFIT SELF_EMPLOYED GOVERNMENT PARTNERSHIP } class CompanySize { <<enumeration>> SMALL_1_10 MEDIUM_11_50 LARGE_51_200 ENTERPRISE_201_PLUS } class CompanyPage { -String about -String website -List~Post~ updates -CompanyPageStats stats +postUpdate(Post) } class CompanyPageStats { -int followerCount -int pageViews -Map~String,Integer~ visitorDemographics } class JobPosting { -String jobId -LocalDate dateOfPosting -String title -String description -EmploymentType employmentType -String location -ExperienceLevel experienceLevel -boolean isFulfilled -List~JobApplication~ applications +apply(Member, JobApplication) +close() } class EmploymentType { <<enumeration>> FULL_TIME PART_TIME CONTRACT INTERNSHIP TEMPORARY VOLUNTEER } class ExperienceLevel { <<enumeration>> ENTRY_LEVEL ASSOCIATE MID_SENIOR DIRECTOR EXECUTIVE } class JobApplication { -String applicationId -Member applicant -LocalDateTime appliedAt -String coverLetter -byte[] resume -ApplicationStatus status } class ApplicationStatus { <<enumeration>> SUBMITTED UNDER_REVIEW INTERVIEWING OFFERED REJECTED WITHDRAWN } %% Groups class Group { -String groupId -String name -String description -int totalMembers -List~GroupMember~ members -List~Post~ posts -GroupPrivacy privacy +addMember(Member, GroupMemberRole) +removeMember(Member) +postToGroup(Post) } class GroupMember { -Member member -GroupMemberRole role -LocalDate joinedAt } class GroupMemberRole { <<enumeration>> OWNER MANAGER MEMBER } class GroupPrivacy { <<enumeration>> PUBLIC PRIVATE UNLISTED } %% Search & Recommendations class Search { <<interface>> +searchMember(String): List~Member~ +searchCompany(String): List~Company~ +searchJob(String): List~JobPosting~ +searchGroups(String): List~Group~ } class SearchIndex { -Map~String,Set~Member~~ memberNames -Map~String,Set~Company~~ companyNames -Map~String,Set~JobPosting~~ jobTitles -Map~String,Set~Group~~ groupNames +addMember(Member) +addCompany(Company) +addJobPosting(JobPosting) +addGroup(Group) +searchMember(String): List~Member~ +searchCompany(String): List~Company~ +searchJob(String): List~JobPosting~ +searchGroups(String): List~Group~ } class RecommendationEngine { +getPeopleYouMayKnow(Member): List~Member~ +getJobRecommendations(Member): List~JobPosting~ +getCompanyRecommendations(Member): List~Company~ +getGroupRecommendations(Member): List~Group~ } %% Notifications class Notification { <<abstract>> -int notificationId -LocalDateTime createdOn -String content -boolean isRead +sendNotification(Member) +markAsRead() } class ConnectionNotification { -ConnectionInvitation invitation } class MessageNotification { -Message message } class PostNotification { -Post post -NotificationType type } class NotificationType { <<enumeration>> LIKE COMMENT SHARE MENTION } class JobNotification { -JobPosting job } %% Relationships Account <|-- Person Person <|-- Member Person <|-- Admin Account "1" -- "1" AccountStatus Person "1" o-- "1" Address Member "1" *-- "1" Profile Member "many" -- "many" Member : connections Member "1" -- "many" ConnectionInvitation : sends/receives Member "many" -- "many" Company : follows Member "many" -- "many" Group : member of Profile "1" *-- "many" Experience Profile "1" *-- "many" Education Profile "1" *-- "many" Skill Profile "1" *-- "1" ProfileStats Profile "1" o-- "many" Recommendation ProfileStats "1" *-- "many" ProfileView ConnectionInvitation "1" -- "1" ConnectionInvitationStatus ConnectionInvitation "1" -- "1" Member : sender ConnectionInvitation "1" -- "1" Member : receiver Recommendation "1" -- "1" RecommendationStatus Recommendation "1" -- "1" Member : recommender Recommendation "1" -- "1" Member : recommendee Post "1" -- "1" Member : owner Post "1" -- "1" PostPrivacy Post "1" *-- "many" Comment Post "many" -- "many" Member : liked by Comment "1" -- "1" Member : author Article "1" -- "1" Member : author Message "1" -- "1" Member : sender Message "many" -- "many" Member : recipients Conversation "1" *-- "many" Message Conversation "many" -- "many" Member : participants Company "1" -- "1" CompanyType Company "1" -- "1" CompanySize Company "1" o-- "1" Address Company "1" *-- "1" CompanyPage Company "1" *-- "many" JobPosting Company "many" -- "many" Member : employees CompanyPage "1" *-- "1" CompanyPageStats CompanyPage "1" *-- "many" Post JobPosting "1" -- "1" EmploymentType JobPosting "1" -- "1" ExperienceLevel JobPosting "1" *-- "many" JobApplication JobApplication "1" -- "1" Member : applicant JobApplication "1" -- "1" ApplicationStatus Group "1" -- "1" GroupPrivacy Group "1" *-- "many" GroupMember Group "1" *-- "many" Post GroupMember "1" -- "1" Member GroupMember "1" -- "1" GroupMemberRole Search <|.. SearchIndex : implements Notification <|-- ConnectionNotification Notification <|-- MessageNotification Notification <|-- PostNotification Notification <|-- JobNotification PostNotification "1" -- "1" NotificationType
5. Activity Diagrams
Activity 1: Send Connection Invitation
flowchart TD Start([Member Initiates Connection]) --> SearchMember[Search for Member<br/>by Name/Title] SearchMember --> ViewProfile[View Member's<br/>Profile] ViewProfile --> CheckConnection{Already<br/>Connected?} CheckConnection -->|Yes| AlreadyConnected[Show: Already in<br/>Your Network] AlreadyConnected --> End1([End]) CheckConnection -->|No| CheckPending{Invitation<br/>Pending?} CheckPending -->|Yes| ShowPending[Show: Invitation<br/>Pending] ShowPending --> End2([End]) CheckPending -->|No| ComposeInvitation[Compose Optional<br/>Personal Message] ComposeInvitation --> ValidateInvitation{Within Daily<br/>Limit?} ValidateInvitation -->|No| ShowLimit[Show: Daily<br/>Limit Reached] ShowLimit --> End3([End]) ValidateInvitation -->|Yes| CreateInvitation[Create Connection<br/>Invitation Object] CreateInvitation --> UpdateSender[Add to Sender's<br/>Sent Invitations] UpdateSender --> UpdateReceiver[Add to Receiver's<br/>Received Invitations] UpdateReceiver --> SendNotification[Send Notification<br/>to Recipient] SendNotification --> UpdateUI[Update UI:<br/>Pending Status] UpdateUI --> End4([End: Invitation Sent]) style Start fill:#e1f5e1 style End1 fill:#ffe1e1 style End2 fill:#ffe1e1 style End3 fill:#ffe1e1 style End4 fill:#e1f5e1 style CheckConnection fill:#fff4e1 style CheckPending fill:#fff4e1 style ValidateInvitation fill:#fff4e1 style CreateInvitation fill:#e1e5ff style SendNotification fill:#e1e5ff
Activity 2: Create Post and Engage
flowchart TD Start([Member Creates Post]) --> ComposeContent[Compose Post Text<br/>or Article] ComposeContent --> AddMedia{Include<br/>Media?} AddMedia -->|Yes| UploadMedia[Upload Image/Video/<br/>Document] UploadMedia --> SetPrivacy AddMedia -->|No| SetPrivacy[Set Privacy Level:<br/>Public/Connections/Private] SetPrivacy --> AddHashtags{Add<br/>Hashtags?} AddHashtags -->|Yes| TagContent[Add Relevant<br/>Hashtags] TagContent --> PublishPost AddHashtags -->|No| PublishPost[Publish Post] PublishPost --> SaveToDB[Persist Post<br/>to Database] SaveToDB --> NotifyConnections[Notify Connections/<br/>Followers] NotifyConnections --> AddToFeed[Add to Followers'<br/>Feeds] AddToFeed --> IndexContent[Index for<br/>Search] IndexContent --> WaitEngagement{User Engagement<br/>Occurs?} WaitEngagement -->|Like| RecordLike[Record Like<br/>Increment Count] RecordLike --> NotifyAuthor1[Notify Post<br/>Author] NotifyAuthor1 --> UpdateStats1[Update Post<br/>Stats] UpdateStats1 --> WaitEngagement WaitEngagement -->|Comment| ValidateComment{Comment<br/>Valid?} ValidateComment -->|Yes| SaveComment[Save Comment] SaveComment --> NotifyAuthor2[Notify Post<br/>Author] NotifyAuthor2 --> UpdateStats2[Update Post<br/>Stats] UpdateStats2 --> WaitEngagement ValidateComment -->|No| WaitEngagement WaitEngagement -->|Share| CreateShare[Create Shared<br/>Post Copy] CreateShare --> NotifyAuthor3[Notify Original<br/>Author] NotifyAuthor3 --> UpdateStats3[Update Share<br/>Count] UpdateStats3 --> WaitEngagement WaitEngagement -->|End| End([End]) style Start fill:#e1f5e1 style End fill:#e1f5e1 style AddMedia fill:#fff4e1 style AddHashtags fill:#fff4e1 style WaitEngagement fill:#fff4e1 style ValidateComment fill:#fff4e1 style PublishPost fill:#e1e5ff style NotifyConnections fill:#e1e5ff style SaveComment fill:#e1e5ff
Activity 3: Job Search and Application
flowchart TD Start([Member Searches Jobs]) --> EnterCriteria[Enter Search Criteria:<br/>Title, Location, Company] EnterCriteria --> ApplyFilters{Apply<br/>Filters?} ApplyFilters -->|Yes| SetFilters[Set Filters:<br/>Experience, Type, Remote] SetFilters --> ExecuteSearch ApplyFilters -->|No| ExecuteSearch[Execute Search<br/>Query] ExecuteSearch --> IndexLookup[Query Job<br/>Search Index] IndexLookup --> RankResults[Rank by Relevance<br/>& Recommendations] RankResults --> DisplayResults[Display Job<br/>Listings] DisplayResults --> ReviewJob[Member Reviews<br/>Job Details] ReviewJob --> SaveOrApply{Save for Later<br/>or Apply?} SaveOrApply -->|Save| SaveJob[Add to Saved<br/>Jobs List] SaveJob --> End1([End: Job Saved]) SaveOrApply -->|Apply| CheckProfile{Profile<br/>Complete?} CheckProfile -->|No| PromptComplete[Prompt: Complete<br/>Profile First] PromptComplete --> End2([End]) CheckProfile -->|Yes| CheckResume{Resume<br/>Attached?} CheckResume -->|No| UploadResume[Upload Resume/<br/>Use Saved Resume] UploadResume --> ComposeCoverLetter CheckResume -->|Yes| ComposeCoverLetter{Add Cover<br/>Letter?} ComposeCoverLetter -->|Yes| WriteCoverLetter[Write Cover<br/>Letter] WriteCoverLetter --> ReviewApplication ComposeCoverLetter -->|No| ReviewApplication[Review Application<br/>Summary] ReviewApplication --> SubmitApplication[Submit<br/>Application] SubmitApplication --> CreateApplication[Create JobApplication<br/>Object] CreateApplication --> NotifyRecruiter[Notify Recruiter/<br/>Company] NotifyRecruiter --> AddToApplications[Add to Member's<br/>Applications List] AddToApplications --> SendConfirmation[Send Confirmation<br/>Email] SendConfirmation --> UpdateJobStats[Update Job<br/>Application Count] UpdateJobStats --> End3([End: Application Submitted]) style Start fill:#e1f5e1 style End1 fill:#e1f5e1 style End2 fill:#ffe1e1 style End3 fill:#e1f5e1 style ApplyFilters fill:#fff4e1 style SaveOrApply fill:#fff4e1 style CheckProfile fill:#fff4e1 style CheckResume fill:#fff4e1 style ComposeCoverLetter fill:#fff4e1 style SubmitApplication fill:#e1e5ff style NotifyRecruiter fill:#e1e5ff
6. Code Implementation
Java Implementation
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.util.*;
import java.util.stream.Collectors;
// Enumerations
enum AccountStatus {
ACTIVE, BLOCKED, BANNED, COMPROMISED, ARCHIVED, UNKNOWN
}
enum ConnectionInvitationStatus {
PENDING, ACCEPTED, CONFIRMED, REJECTED, CANCELED, WITHDRAWN
}
enum RecommendationStatus {
PENDING, ACCEPTED, REJECTED
}
enum PostPrivacy {
PUBLIC, CONNECTIONS, PRIVATE
}
enum CompanyType {
PUBLIC_COMPANY, PRIVATE, NONPROFIT, SELF_EMPLOYED, GOVERNMENT, PARTNERSHIP
}
enum CompanySize {
SMALL_1_10, MEDIUM_11_50, LARGE_51_200, ENTERPRISE_201_PLUS
}
enum EmploymentType {
FULL_TIME, PART_TIME, CONTRACT, INTERNSHIP, TEMPORARY, VOLUNTEER
}
enum ExperienceLevel {
ENTRY_LEVEL, ASSOCIATE, MID_SENIOR, DIRECTOR, EXECUTIVE
}
enum ApplicationStatus {
SUBMITTED, UNDER_REVIEW, INTERVIEWING, OFFERED, REJECTED, WITHDRAWN
}
enum GroupMemberRole {
OWNER, MANAGER, MEMBER
}
enum GroupPrivacy {
PUBLIC, PRIVATE, UNLISTED
}
enum NotificationType {
LIKE, COMMENT, SHARE, MENTION
}
// Address
class Address {
private String streetAddress;
private String city;
private String state;
private String zipCode;
private String country;
public Address(String streetAddress, String city, String state, String zipCode, String country) {
this.streetAddress = streetAddress;
this.city = city;
this.state = state;
this.zipCode = zipCode;
this.country = country;
}
// Getters
public String getStreetAddress() { return streetAddress; }
public String getCity() { return city; }
public String getState() { return state; }
public String getZipCode() { return zipCode; }
public String getCountry() { return country; }
}
// Account
abstract class Account {
protected String id;
protected String password;
protected AccountStatus status;
protected LocalDateTime createdAt;
public Account(String id, String password) {
this.id = id;
this.password = password;
this.status = AccountStatus.ACTIVE;
this.createdAt = LocalDateTime.now();
}
public boolean resetPassword(String oldPassword, String newPassword) {
if (this.password.equals(oldPassword)) {
this.password = newPassword;
return true;
}
return false;
}
public void updateStatus(AccountStatus status) {
this.status = status;
}
public String getId() { return id; }
public AccountStatus getStatus() { return status; }
}
// Person
abstract class Person {
protected String name;
protected Address address;
protected String email;
protected String phone;
protected Account account;
public Person(String name, Address address, String email, String phone, Account account) {
this.name = name;
this.address = address;
this.email = email;
this.phone = phone;
this.account = account;
}
public String getName() { return name; }
public String getEmail() { return email; }
}
// Experience
class Experience {
private String title;
private String company;
private String location;
private LocalDate dateFrom;
private LocalDate dateTo;
private String description;
private boolean isCurrent;
public Experience(String title, String company, String location, LocalDate dateFrom,
LocalDate dateTo, String description, boolean isCurrent) {
this.title = title;
this.company = company;
this.location = location;
this.dateFrom = dateFrom;
this.dateTo = dateTo;
this.description = description;
this.isCurrent = isCurrent;
}
public String getTitle() { return title; }
public String getCompany() { return company; }
}
// Education
class Education {
private String school;
private String degree;
private String fieldOfStudy;
private LocalDate startDate;
private LocalDate endDate;
private String grade;
private String activities;
public Education(String school, String degree, String fieldOfStudy,
LocalDate startDate, LocalDate endDate) {
this.school = school;
this.degree = degree;
this.fieldOfStudy = fieldOfStudy;
this.startDate = startDate;
this.endDate = endDate;
}
public String getSchool() { return school; }
public String getDegree() { return degree; }
}
// Skill
class Skill {
private String name;
private String category;
private int endorsementCount;
public Skill(String name, String category) {
this.name = name;
this.category = category;
this.endorsementCount = 0;
}
public void incrementEndorsements() {
endorsementCount++;
}
public String getName() { return name; }
public int getEndorsementCount() { return endorsementCount; }
}
// ProfileView
class ProfileView {
private Member viewer;
private LocalDateTime viewedAt;
private boolean isAnonymous;
public ProfileView(Member viewer, LocalDateTime viewedAt, boolean isAnonymous) {
this.viewer = viewer;
this.viewedAt = viewedAt;
this.isAnonymous = isAnonymous;
}
public Member getViewer() { return viewer; }
public LocalDateTime getViewedAt() { return viewedAt; }
}
// ProfileStats
class ProfileStats {
private int profileViews;
private int searchAppearances;
private int postImpressions;
private List<ProfileView> recentViewers;
public ProfileStats() {
this.profileViews = 0;
this.searchAppearances = 0;
this.postImpressions = 0;
this.recentViewers = new ArrayList<>();
}
public void recordView(Member viewer) {
profileViews++;
recentViewers.add(new ProfileView(viewer, LocalDateTime.now(), false));
}
public int getViewsLast90Days() {
LocalDateTime ninetyDaysAgo = LocalDateTime.now().minusDays(90);
return (int) recentViewers.stream()
.filter(v -> v.getViewedAt().isAfter(ninetyDaysAgo))
.count();
}
public int getProfileViews() { return profileViews; }
}
// Recommendation
class Recommendation {
private Member recommender;
private Member recommendee;
private String text;
private LocalDateTime createdAt;
private RecommendationStatus status;
public Recommendation(Member recommender, Member recommendee, String text) {
this.recommender = recommender;
this.recommendee = recommendee;
this.text = text;
this.createdAt = LocalDateTime.now();
this.status = RecommendationStatus.PENDING;
}
public Member getRecommender() { return recommender; }
public String getText() { return text; }
}
// Profile
class Profile {
private String summary;
private List<Experience> experiences;
private List<Education> educations;
private List<Skill> skills;
private List<String> accomplishments;
private List<Recommendation> recommendations;
private ProfileStats stats;
public Profile() {
this.experiences = new ArrayList<>();
this.educations = new ArrayList<>();
this.skills = new ArrayList<>();
this.accomplishments = new ArrayList<>();
this.recommendations = new ArrayList<>();
this.stats = new ProfileStats();
}
public void addExperience(Experience experience) {
experiences.add(experience);
}
public void addEducation(Education education) {
educations.add(education);
}
public void addSkill(Skill skill) {
skills.add(skill);
}
public void addAccomplishment(String accomplishment) {
accomplishments.add(accomplishment);
}
public Recommendation requestRecommendation(Member recommender, String text) {
Recommendation rec = new Recommendation(recommender, null, text);
recommendations.add(rec);
return rec;
}
public ProfileStats getStats() { return stats; }
public List<Experience> getExperiences() { return new ArrayList<>(experiences); }
}
// Member
class Member extends Person {
private LocalDate dateOfMembership;
private String headline;
private byte[] photo;
private Profile profile;
private List<Member> connections;
private List<Member> following;
private List<Company> followingCompanies;
private List<Group> groups;
private List<ConnectionInvitation> sentInvitations;
private List<ConnectionInvitation> receivedInvitations;
public Member(String id, String password, String name, Address address, String email, String phone) {
super(name, address, email, phone, new Account(id, password) {});
this.dateOfMembership = LocalDate.now();
this.profile = new Profile();
this.connections = new ArrayList<>();
this.following = new ArrayList<>();
this.followingCompanies = new ArrayList<>();
this.groups = new ArrayList<>();
this.sentInvitations = new ArrayList<>();
this.receivedInvitations = new ArrayList<>();
}
public boolean sendMessage(Message message) {
// Send message logic
return true;
}
public boolean createPost(Post post) {
// Create post logic
return true;
}
public ConnectionInvitation sendConnectionInvitation(Member receiver, String message) {
ConnectionInvitation invitation = new ConnectionInvitation(this, receiver, message);
sentInvitations.add(invitation);
receiver.receiveConnectionInvitation(invitation);
return invitation;
}
public void receiveConnectionInvitation(ConnectionInvitation invitation) {
receivedInvitations.add(invitation);
}
public boolean acceptConnectionInvitation(ConnectionInvitation invitation) {
if (invitation.accept()) {
connections.add(invitation.getSender());
invitation.getSender().addConnection(this);
return true;
}
return false;
}
private void addConnection(Member member) {
connections.add(member);
}
public boolean followMember(Member member) {
if (!following.contains(member)) {
following.add(member);
return true;
}
return false;
}
public boolean followCompany(Company company) {
if (!followingCompanies.contains(company)) {
followingCompanies.add(company);
company.addFollower(this);
return true;
}
return false;
}
public boolean endorseSkill(Member member, Skill skill) {
skill.incrementEndorsements();
return true;
}
public Profile getProfile() { return profile; }
public List<Member> getConnections() { return new ArrayList<>(connections); }
}
// Admin
class Admin extends Person {
public Admin(String id, String password, String name, Address address, String email, String phone) {
super(name, address, email, phone, new Account(id, password) {});
}
public boolean blockUser(Member member) {
member.account.updateStatus(AccountStatus.BLOCKED);
return true;
}
public boolean unblockUser(Member member) {
member.account.updateStatus(AccountStatus.ACTIVE);
return true;
}
public boolean removeContent(Post post) {
// Remove content logic
return true;
}
}
// ConnectionInvitation
class ConnectionInvitation {
private String invitationId;
private Member sender;
private Member receiver;
private LocalDateTime sentAt;
private String message;
private ConnectionInvitationStatus status;
public ConnectionInvitation(Member sender, Member receiver, String message) {
this.invitationId = UUID.randomUUID().toString();
this.sender = sender;
this.receiver = receiver;
this.message = message;
this.sentAt = LocalDateTime.now();
this.status = ConnectionInvitationStatus.PENDING;
}
public boolean accept() {
if (status == ConnectionInvitationStatus.PENDING) {
status = ConnectionInvitationStatus.ACCEPTED;
return true;
}
return false;
}
public boolean reject() {
if (status == ConnectionInvitationStatus.PENDING) {
status = ConnectionInvitationStatus.REJECTED;
return true;
}
return false;
}
public boolean withdraw() {
if (status == ConnectionInvitationStatus.PENDING) {
status = ConnectionInvitationStatus.WITHDRAWN;
return true;
}
return false;
}
public Member getSender() { return sender; }
public ConnectionInvitationStatus getStatus() { return status; }
}
// Comment
class Comment {
private String commentId;
private String text;
private Member author;
private LocalDateTime createdAt;
private List<Comment> replies;
public Comment(String text, Member author) {
this.commentId = UUID.randomUUID().toString();
this.text = text;
this.author = author;
this.createdAt = LocalDateTime.now();
this.replies = new ArrayList<>();
}
public void addReply(Comment reply) {
replies.add(reply);
}
public Member getAuthor() { return author; }
}
// Post
class Post {
private String postId;
private String text;
private byte[] media;
private Member owner;
private LocalDateTime createdAt;
private int totalLikes;
private int totalShares;
private int totalComments;
private List<Comment> comments;
private Set<Member> likedBy;
private PostPrivacy privacy;
public Post(String text, Member owner, PostPrivacy privacy) {
this.postId = UUID.randomUUID().toString();
this.text = text;
this.owner = owner;
this.privacy = privacy;
this.createdAt = LocalDateTime.now();
this.comments = new ArrayList<>();
this.likedBy = new HashSet<>();
this.totalLikes = 0;
this.totalShares = 0;
this.totalComments = 0;
}
public void addComment(Comment comment) {
comments.add(comment);
totalComments++;
}
public void like(Member member) {
if (!likedBy.contains(member)) {
likedBy.add(member);
totalLikes++;
}
}
public void share(Member member) {
totalShares++;
}
public Member getOwner() { return owner; }
public int getTotalLikes() { return totalLikes; }
}
// Article
class Article {
private String articleId;
private String title;
private String content;
private Member author;
private LocalDateTime publishedAt;
private List<String> tags;
private int viewCount;
public Article(String title, String content, Member author) {
this.articleId = UUID.randomUUID().toString();
this.title = title;
this.content = content;
this.author = author;
this.publishedAt = LocalDateTime.now();
this.tags = new ArrayList<>();
this.viewCount = 0;
}
public void incrementViewCount() {
viewCount++;
}
}
// Message
class Message {
private String messageId;
private Member sender;
private List<Member> recipients;
private String body;
private byte[] attachments;
private LocalDateTime sentAt;
private boolean isRead;
public Message(Member sender, List<Member> recipients, String body) {
this.messageId = UUID.randomUUID().toString();
this.sender = sender;
this.recipients = recipients;
this.body = body;
this.sentAt = LocalDateTime.now();
this.isRead = false;
}
public void markAsRead() {
isRead = true;
}
public Member getSender() { return sender; }
}
// Conversation
class Conversation {
private String conversationId;
private List<Member> participants;
private List<Message> messages;
private LocalDateTime lastMessageAt;
public Conversation(List<Member> participants) {
this.conversationId = UUID.randomUUID().toString();
this.participants = participants;
this.messages = new ArrayList<>();
}
public void addMessage(Message message) {
messages.add(message);
lastMessageAt = LocalDateTime.now();
}
public void addParticipant(Member member) {
if (!participants.contains(member)) {
participants.add(member);
}
}
}
// CompanyPageStats
class CompanyPageStats {
private int followerCount;
private int pageViews;
private Map<String, Integer> visitorDemographics;
public CompanyPageStats() {
this.followerCount = 0;
this.pageViews = 0;
this.visitorDemographics = new HashMap<>();
}
public void incrementFollowers() {
followerCount++;
}
}
// CompanyPage
class CompanyPage {
private String about;
private String website;
private List<Post> updates;
private CompanyPageStats stats;
public CompanyPage(String about, String website) {
this.about = about;
this.website = website;
this.updates = new ArrayList<>();
this.stats = new CompanyPageStats();
}
public void postUpdate(Post post) {
updates.add(post);
}
}
// JobApplication
class JobApplication {
private String applicationId;
private Member applicant;
private LocalDateTime appliedAt;
private String coverLetter;
private byte[] resume;
private ApplicationStatus status;
public JobApplication(Member applicant, String coverLetter, byte[] resume) {
this.applicationId = UUID.randomUUID().toString();
this.applicant = applicant;
this.appliedAt = LocalDateTime.now();
this.coverLetter = coverLetter;
this.resume = resume;
this.status = ApplicationStatus.SUBMITTED;
}
public Member getApplicant() { return applicant; }
}
// JobPosting
class JobPosting {
private String jobId;
private LocalDate dateOfPosting;
private String title;
private String description;
private EmploymentType employmentType;
private String location;
private ExperienceLevel experienceLevel;
private boolean isFulfilled;
private List<JobApplication> applications;
public JobPosting(String title, String description, EmploymentType employmentType,
String location, ExperienceLevel experienceLevel) {
this.jobId = UUID.randomUUID().toString();
this.dateOfPosting = LocalDate.now();
this.title = title;
this.description = description;
this.employmentType = employmentType;
this.location = location;
this.experienceLevel = experienceLevel;
this.isFulfilled = false;
this.applications = new ArrayList<>();
}
public void apply(Member member, JobApplication application) {
applications.add(application);
}
public void close() {
isFulfilled = true;
}
public String getTitle() { return title; }
}
// Company
class Company {
private String companyId;
private String name;
private String description;
private CompanyType type;
private CompanySize size;
private Address location;
private CompanyPage page;
private List<JobPosting> activeJobPostings;
private List<Member> employees;
private List<Member> followers;
public Company(String name, String description, CompanyType type, CompanySize size, Address location) {
this.companyId = UUID.randomUUID().toString();
this.name = name;
this.description = description;
this.type = type;
this.size = size;
this.location = location;
this.page = new CompanyPage("", "");
this.activeJobPostings = new ArrayList<>();
this.employees = new ArrayList<>();
this.followers = new ArrayList<>();
}
public void postJob(JobPosting job) {
activeJobPostings.add(job);
}
public void addEmployee(Member member) {
if (!employees.contains(member)) {
employees.add(member);
}
}
public void addFollower(Member member) {
if (!followers.contains(member)) {
followers.add(member);
page.stats.incrementFollowers();
}
}
public String getName() { return name; }
}
// GroupMember
class GroupMember {
private Member member;
private GroupMemberRole role;
private LocalDate joinedAt;
public GroupMember(Member member, GroupMemberRole role) {
this.member = member;
this.role = role;
this.joinedAt = LocalDate.now();
}
public Member getMember() { return member; }
}
// Group
class Group {
private String groupId;
private String name;
private String description;
private int totalMembers;
private List<GroupMember> members;
private List<Post> posts;
private GroupPrivacy privacy;
public Group(String name, String description, GroupPrivacy privacy) {
this.groupId = UUID.randomUUID().toString();
this.name = name;
this.description = description;
this.privacy = privacy;
this.totalMembers = 0;
this.members = new ArrayList<>();
this.posts = new ArrayList<>();
}
public void addMember(Member member, GroupMemberRole role) {
members.add(new GroupMember(member, role));
totalMembers++;
}
public void removeMember(Member member) {
members.removeIf(gm -> gm.getMember().equals(member));
totalMembers--;
}
public void postToGroup(Post post) {
posts.add(post);
}
}
// Search Interface
interface Search {
List<Member> searchMember(String name);
List<Company> searchCompany(String name);
List<JobPosting> searchJob(String title);
List<Group> searchGroups(String name);
}
// SearchIndex
class SearchIndex implements Search {
private Map<String, Set<Member>> memberNames;
private Map<String, Set<Company>> companyNames;
private Map<String, Set<JobPosting>> jobTitles;
private Map<String, Set<Group>> groupNames;
public SearchIndex() {
this.memberNames = new HashMap<>();
this.companyNames = new HashMap<>();
this.jobTitles = new HashMap<>();
this.groupNames = new HashMap<>();
}
public void addMember(Member member) {
String name = member.getName().toLowerCase();
memberNames.computeIfAbsent(name, k -> new HashSet<>()).add(member);
}
public void addCompany(Company company) {
String name = company.getName().toLowerCase();
companyNames.computeIfAbsent(name, k -> new HashSet<>()).add(company);
}
public void addJobPosting(JobPosting job) {
String title = job.getTitle().toLowerCase();
jobTitles.computeIfAbsent(title, k -> new HashSet<>()).add(job);
}
public void addGroup(Group group) {
String name = group.name.toLowerCase();
groupNames.computeIfAbsent(name, k -> new HashSet<>()).add(group);
}
@Override
public List<Member> searchMember(String name) {
Set<Member> results = memberNames.get(name.toLowerCase());
return results != null ? new ArrayList<>(results) : new ArrayList<>();
}
@Override
public List<Company> searchCompany(String name) {
Set<Company> results = companyNames.get(name.toLowerCase());
return results != null ? new ArrayList<>(results) : new ArrayList<>();
}
@Override
public List<JobPosting> searchJob(String title) {
Set<JobPosting> results = jobTitles.get(title.toLowerCase());
return results != null ? new ArrayList<>(results) : new ArrayList<>();
}
@Override
public List<Group> searchGroups(String name) {
Set<Group> results = groupNames.get(name.toLowerCase());
return results != null ? new ArrayList<>(results) : new ArrayList<>();
}
}
// RecommendationEngine
class RecommendationEngine {
public List<Member> getPeopleYouMayKnow(Member member) {
// Implement collaborative filtering based on mutual connections
Set<Member> suggestions = new HashSet<>();
for (Member connection : member.getConnections()) {
for (Member secondDegree : connection.getConnections()) {
if (!member.getConnections().contains(secondDegree) && !secondDegree.equals(member)) {
suggestions.add(secondDegree);
}
}
}
return new ArrayList<>(suggestions);
}
public List<JobPosting> getJobRecommendations(Member member) {
// Implement based on profile skills and experiences
return new ArrayList<>();
}
public List<Company> getCompanyRecommendations(Member member) {
// Implement based on industry and connections
return new ArrayList<>();
}
public List<Group> getGroupRecommendations(Member member) {
// Implement based on interests and connections' groups
return new ArrayList<>();
}
}
// Notification
abstract class Notification {
protected int notificationId;
protected LocalDateTime createdOn;
protected String content;
protected boolean isRead;
public Notification(String content) {
this.notificationId = new Random().nextInt(1000000);
this.createdOn = LocalDateTime.now();
this.content = content;
this.isRead = false;
}
public abstract void sendNotification(Member member);
public void markAsRead() {
isRead = true;
}
}
class ConnectionNotification extends Notification {
private ConnectionInvitation invitation;
public ConnectionNotification(String content, ConnectionInvitation invitation) {
super(content);
this.invitation = invitation;
}
@Override
public void sendNotification(Member member) {
System.out.println("Connection notification to " + member.getName() + ": " + content);
}
}
class MessageNotification extends Notification {
private Message message;
public MessageNotification(String content, Message message) {
super(content);
this.message = message;
}
@Override
public void sendNotification(Member member) {
System.out.println("Message notification to " + member.getName() + ": " + content);
}
}
class PostNotification extends Notification {
private Post post;
private NotificationType type;
public PostNotification(String content, Post post, NotificationType type) {
super(content);
this.post = post;
this.type = type;
}
@Override
public void sendNotification(Member member) {
System.out.println("Post notification to " + member.getName() + ": " + content);
}
}
class JobNotification extends Notification {
private JobPosting job;
public JobNotification(String content, JobPosting job) {
super(content);
this.job = job;
}
@Override
public void sendNotification(Member member) {
System.out.println("Job notification to " + member.getName() + ": " + content);
}
}
Python Implementation
from abc import ABC, abstractmethod
from enum import Enum
from datetime import datetime, date
from typing import List, Optional, Set, Dict
from dataclasses import dataclass, field
import uuid
# Enumerations
class AccountStatus(Enum):
ACTIVE = "ACTIVE"
BLOCKED = "BLOCKED"
BANNED = "BANNED"
COMPROMISED = "COMPROMISED"
ARCHIVED = "ARCHIVED"
UNKNOWN = "UNKNOWN"
class ConnectionInvitationStatus(Enum):
PENDING = "PENDING"
ACCEPTED = "ACCEPTED"
CONFIRMED = "CONFIRMED"
REJECTED = "REJECTED"
CANCELED = "CANCELED"
WITHDRAWN = "WITHDRAWN"
class RecommendationStatus(Enum):
PENDING = "PENDING"
ACCEPTED = "ACCEPTED"
REJECTED = "REJECTED"
class PostPrivacy(Enum):
PUBLIC = "PUBLIC"
CONNECTIONS = "CONNECTIONS"
PRIVATE = "PRIVATE"
class CompanyType(Enum):
PUBLIC_COMPANY = "PUBLIC_COMPANY"
PRIVATE = "PRIVATE"
NONPROFIT = "NONPROFIT"
SELF_EMPLOYED = "SELF_EMPLOYED"
GOVERNMENT = "GOVERNMENT"
PARTNERSHIP = "PARTNERSHIP"
class CompanySize(Enum):
SMALL_1_10 = "SMALL_1_10"
MEDIUM_11_50 = "MEDIUM_11_50"
LARGE_51_200 = "LARGE_51_200"
ENTERPRISE_201_PLUS = "ENTERPRISE_201_PLUS"
class EmploymentType(Enum):
FULL_TIME = "FULL_TIME"
PART_TIME = "PART_TIME"
CONTRACT = "CONTRACT"
INTERNSHIP = "INTERNSHIP"
TEMPORARY = "TEMPORARY"
VOLUNTEER = "VOLUNTEER"
class ExperienceLevel(Enum):
ENTRY_LEVEL = "ENTRY_LEVEL"
ASSOCIATE = "ASSOCIATE"
MID_SENIOR = "MID_SENIOR"
DIRECTOR = "DIRECTOR"
EXECUTIVE = "EXECUTIVE"
class ApplicationStatus(Enum):
SUBMITTED = "SUBMITTED"
UNDER_REVIEW = "UNDER_REVIEW"
INTERVIEWING = "INTERVIEWING"
OFFERED = "OFFERED"
REJECTED = "REJECTED"
WITHDRAWN = "WITHDRAWN"
class GroupMemberRole(Enum):
OWNER = "OWNER"
MANAGER = "MANAGER"
MEMBER = "MEMBER"
class GroupPrivacy(Enum):
PUBLIC = "PUBLIC"
PRIVATE = "PRIVATE"
UNLISTED = "UNLISTED"
class NotificationType(Enum):
LIKE = "LIKE"
COMMENT = "COMMENT"
SHARE = "SHARE"
MENTION = "MENTION"
# Address
@dataclass
class Address:
street_address: str
city: str
state: str
zip_code: str
country: str
# Account
class Account(ABC):
def __init__(self, account_id: str, password: str):
self._id = account_id
self._password = password
self._status = AccountStatus.ACTIVE
self._created_at = datetime.now()
def reset_password(self, old_password: str, new_password: str) -> bool:
if self._password == old_password:
self._password = new_password
return True
return False
def update_status(self, status: AccountStatus):
self._status = status
@property
def id(self) -> str:
return self._id
@property
def status(self) -> AccountStatus:
return self._status
# Person
class Person(ABC):
def __init__(self, name: str, address: Address, email: str, phone: str, account: Account):
self._name = name
self._address = address
self._email = email
self._phone = phone
self._account = account
@property
def name(self) -> str:
return self._name
@property
def email(self) -> str:
return self._email
# Experience
@dataclass
class Experience:
title: str
company: str
location: str
date_from: date
date_to: Optional[date]
description: str
is_current: bool = False
# Education
@dataclass
class Education:
school: str
degree: str
field_of_study: str
start_date: date
end_date: Optional[date]
grade: Optional[str] = None
activities: Optional[str] = None
# Skill
class Skill:
def __init__(self, name: str, category: str):
self._name = name
self._category = category
self._endorsement_count = 0
def increment_endorsements(self):
self._endorsement_count += 1
@property
def name(self) -> str:
return self._name
@property
def endorsement_count(self) -> int:
return self._endorsement_count
# ProfileView
@dataclass
class ProfileView:
viewer: 'Member'
viewed_at: datetime
is_anonymous: bool = False
# ProfileStats
class ProfileStats:
def __init__(self):
self._profile_views = 0
self._search_appearances = 0
self._post_impressions = 0
self._recent_viewers: List[ProfileView] = []
def record_view(self, viewer: 'Member'):
self._profile_views += 1
self._recent_viewers.append(ProfileView(viewer, datetime.now(), False))
def get_views_last_90_days(self) -> int:
from datetime import timedelta
ninety_days_ago = datetime.now() - timedelta(days=90)
return sum(1 for v in self._recent_viewers if v.viewed_at > ninety_days_ago)
@property
def profile_views(self) -> int:
return self._profile_views
# Recommendation
class Recommendation:
def __init__(self, recommender: 'Member', recommendee: 'Member', text: str):
self._recommender = recommender
self._recommendee = recommendee
self._text = text
self._created_at = datetime.now()
self._status = RecommendationStatus.PENDING
@property
def recommender(self) -> 'Member':
return self._recommender
@property
def text(self) -> str:
return self._text
# Profile
class Profile:
def __init__(self):
self._summary: Optional[str] = None
self._experiences: List[Experience] = []
self._educations: List[Education] = []
self._skills: List[Skill] = []
self._accomplishments: List[str] = []
self._recommendations: List[Recommendation] = []
self._stats = ProfileStats()
def add_experience(self, experience: Experience):
self._experiences.append(experience)
def add_education(self, education: Education):
self._educations.append(education)
def add_skill(self, skill: Skill):
self._skills.append(skill)
def add_accomplishment(self, accomplishment: str):
self._accomplishments.append(accomplishment)
def request_recommendation(self, recommender: 'Member', text: str) -> Recommendation:
rec = Recommendation(recommender, None, text)
self._recommendations.append(rec)
return rec
@property
def stats(self) -> ProfileStats:
return self._stats
@property
def experiences(self) -> List[Experience]:
return self._experiences.copy()
# ConnectionInvitation
class ConnectionInvitation:
def __init__(self, sender: 'Member', receiver: 'Member', message: str):
self._invitation_id = str(uuid.uuid4())
self._sender = sender
self._receiver = receiver
self._message = message
self._sent_at = datetime.now()
self._status = ConnectionInvitationStatus.PENDING
def accept(self) -> bool:
if self._status == ConnectionInvitationStatus.PENDING:
self._status = ConnectionInvitationStatus.ACCEPTED
return True
return False
def reject(self) -> bool:
if self._status == ConnectionInvitationStatus.PENDING:
self._status = ConnectionInvitationStatus.REJECTED
return True
return False
def withdraw(self) -> bool:
if self._status == ConnectionInvitationStatus.PENDING:
self._status = ConnectionInvitationStatus.WITHDRAWN
return True
return False
@property
def sender(self) -> 'Member':
return self._sender
@property
def status(self) -> ConnectionInvitationStatus:
return self._status
# Comment
class Comment:
def __init__(self, text: str, author: 'Member'):
self._comment_id = str(uuid.uuid4())
self._text = text
self._author = author
self._created_at = datetime.now()
self._replies: List[Comment] = []
def add_reply(self, reply: 'Comment'):
self._replies.append(reply)
@property
def author(self) -> 'Member':
return self._author
# Post
class Post:
def __init__(self, text: str, owner: 'Member', privacy: PostPrivacy):
self._post_id = str(uuid.uuid4())
self._text = text
self._owner = owner
self._privacy = privacy
self._created_at = datetime.now()
self._media: Optional[bytes] = None
self._total_likes = 0
self._total_shares = 0
self._total_comments = 0
self._comments: List[Comment] = []
self._liked_by: Set['Member'] = set()
def add_comment(self, comment: Comment):
self._comments.append(comment)
self._total_comments += 1
def like(self, member: 'Member'):
if member not in self._liked_by:
self._liked_by.add(member)
self._total_likes += 1
def share(self, member: 'Member'):
self._total_shares += 1
@property
def owner(self) -> 'Member':
return self._owner
@property
def total_likes(self) -> int:
return self._total_likes
# Article
class Article:
def __init__(self, title: str, content: str, author: 'Member'):
self._article_id = str(uuid.uuid4())
self._title = title
self._content = content
self._author = author
self._published_at = datetime.now()
self._tags: List[str] = []
self._view_count = 0
def increment_view_count(self):
self._view_count += 1
# Message
class Message:
def __init__(self, sender: 'Member', recipients: List['Member'], body: str):
self._message_id = str(uuid.uuid4())
self._sender = sender
self._recipients = recipients
self._body = body
self._sent_at = datetime.now()
self._is_read = False
self._attachments: Optional[bytes] = None
def mark_as_read(self):
self._is_read = True
@property
def sender(self) -> 'Member':
return self._sender
# Conversation
class Conversation:
def __init__(self, participants: List['Member']):
self._conversation_id = str(uuid.uuid4())
self._participants = participants
self._messages: List[Message] = []
self._last_message_at: Optional[datetime] = None
def add_message(self, message: Message):
self._messages.append(message)
self._last_message_at = datetime.now()
def add_participant(self, member: 'Member'):
if member not in self._participants:
self._participants.append(member)
# Member
class Member(Person):
def __init__(self, account_id: str, password: str, name: str, address: Address, email: str, phone: str):
account = type('Account', (Account,), {})()
account.__init__(account_id, password)
super().__init__(name, address, email, phone, account)
self._date_of_membership = date.today()
self._headline: Optional[str] = None
self._photo: Optional[bytes] = None
self._profile = Profile()
self._connections: List[Member] = []
self._following: List[Member] = []
self._following_companies: List['Company'] = []
self._groups: List['Group'] = []
self._sent_invitations: List[ConnectionInvitation] = []
self._received_invitations: List[ConnectionInvitation] = []
def send_message(self, message: Message) -> bool:
# Send message logic
return True
def create_post(self, post: Post) -> bool:
# Create post logic
return True
def send_connection_invitation(self, receiver: 'Member', message: str) -> ConnectionInvitation:
invitation = ConnectionInvitation(self, receiver, message)
self._sent_invitations.append(invitation)
receiver.receive_connection_invitation(invitation)
return invitation
def receive_connection_invitation(self, invitation: ConnectionInvitation):
self._received_invitations.append(invitation)
def accept_connection_invitation(self, invitation: ConnectionInvitation) -> bool:
if invitation.accept():
self._connections.append(invitation.sender)
invitation.sender._add_connection(self)
return True
return False
def _add_connection(self, member: 'Member'):
self._connections.append(member)
def follow_member(self, member: 'Member') -> bool:
if member not in self._following:
self._following.append(member)
return True
return False
def follow_company(self, company: 'Company') -> bool:
if company not in self._following_companies:
self._following_companies.append(company)
company.add_follower(self)
return True
return False
def endorse_skill(self, member: 'Member', skill: Skill) -> bool:
skill.increment_endorsements()
return True
@property
def profile(self) -> Profile:
return self._profile
@property
def connections(self) -> List['Member']:
return self._connections.copy()
# Admin
class Admin(Person):
def __init__(self, account_id: str, password: str, name: str, address: Address, email: str, phone: str):
account = type('Account', (Account,), {})()
account.__init__(account_id, password)
super().__init__(name, address, email, phone, account)
def block_user(self, member: Member) -> bool:
member._account.update_status(AccountStatus.BLOCKED)
return True
def unblock_user(self, member: Member) -> bool:
member._account.update_status(AccountStatus.ACTIVE)
return True
def remove_content(self, post: Post) -> bool:
# Remove content logic
return True
# CompanyPageStats
class CompanyPageStats:
def __init__(self):
self._follower_count = 0
self._page_views = 0
self._visitor_demographics: Dict[str, int] = {}
def increment_followers(self):
self._follower_count += 1
# CompanyPage
class CompanyPage:
def __init__(self, about: str, website: str):
self._about = about
self._website = website
self._updates: List[Post] = []
self._stats = CompanyPageStats()
def post_update(self, post: Post):
self._updates.append(post)
@property
def stats(self) -> CompanyPageStats:
return self._stats
# JobApplication
class JobApplication:
def __init__(self, applicant: Member, cover_letter: str, resume: bytes):
self._application_id = str(uuid.uuid4())
self._applicant = applicant
self._applied_at = datetime.now()
self._cover_letter = cover_letter
self._resume = resume
self._status = ApplicationStatus.SUBMITTED
@property
def applicant(self) -> Member:
return self._applicant
# JobPosting
class JobPosting:
def __init__(self, title: str, description: str, employment_type: EmploymentType,
location: str, experience_level: ExperienceLevel):
self._job_id = str(uuid.uuid4())
self._date_of_posting = date.today()
self._title = title
self._description = description
self._employment_type = employment_type
self._location = location
self._experience_level = experience_level
self._is_fulfilled = False
self._applications: List[JobApplication] = []
def apply(self, member: Member, application: JobApplication):
self._applications.append(application)
def close(self):
self._is_fulfilled = True
@property
def title(self) -> str:
return self._title
# Company
class Company:
def __init__(self, name: str, description: str, company_type: CompanyType,
size: CompanySize, location: Address):
self._company_id = str(uuid.uuid4())
self._name = name
self._description = description
self._type = company_type
self._size = size
self._location = location
self._page = CompanyPage("", "")
self._active_job_postings: List[JobPosting] = []
self._employees: List[Member] = []
self._followers: List[Member] = []
def post_job(self, job: JobPosting):
self._active_job_postings.append(job)
def add_employee(self, member: Member):
if member not in self._employees:
self._employees.append(member)
def add_follower(self, member: Member):
if member not in self._followers:
self._followers.append(member)
self._page.stats.increment_followers()
@property
def name(self) -> str:
return self._name
# GroupMember
@dataclass
class GroupMember:
member: Member
role: GroupMemberRole
joined_at: date = field(default_factory=date.today)
# Group
class Group:
def __init__(self, name: str, description: str, privacy: GroupPrivacy):
self._group_id = str(uuid.uuid4())
self._name = name
self._description = description
self._privacy = privacy
self._total_members = 0
self._members: List[GroupMember] = []
self._posts: List[Post] = []
def add_member(self, member: Member, role: GroupMemberRole):
self._members.append(GroupMember(member, role))
self._total_members += 1
def remove_member(self, member: Member):
self._members = [gm for gm in self._members if gm.member != member]
self._total_members -= 1
def post_to_group(self, post: Post):
self._posts.append(post)
# Search Interface
class Search(ABC):
@abstractmethod
def search_member(self, name: str) -> List[Member]:
pass
@abstractmethod
def search_company(self, name: str) -> List[Company]:
pass
@abstractmethod
def search_job(self, title: str) -> List[JobPosting]:
pass
@abstractmethod
def search_groups(self, name: str) -> List[Group]:
pass
# SearchIndex
class SearchIndex(Search):
def __init__(self):
self._member_names: Dict[str, Set[Member]] = {}
self._company_names: Dict[str, Set[Company]] = {}
self._job_titles: Dict[str, Set[JobPosting]] = {}
self._group_names: Dict[str, Set[Group]] = {}
def add_member(self, member: Member):
name = member.name.lower()
if name not in self._member_names:
self._member_names[name] = set()
self._member_names[name].add(member)
def add_company(self, company: Company):
name = company.name.lower()
if name not in self._company_names:
self._company_names[name] = set()
self._company_names[name].add(company)
def add_job_posting(self, job: JobPosting):
title = job.title.lower()
if title not in self._job_titles:
self._job_titles[title] = set()
self._job_titles[title].add(job)
def add_group(self, group: Group):
name = group._name.lower()
if name not in self._group_names:
self._group_names[name] = set()
self._group_names[name].add(group)
def search_member(self, name: str) -> List[Member]:
results = self._member_names.get(name.lower(), set())
return list(results)
def search_company(self, name: str) -> List[Company]:
results = self._company_names.get(name.lower(), set())
return list(results)
def search_job(self, title: str) -> List[JobPosting]:
results = self._job_titles.get(title.lower(), set())
return list(results)
def search_groups(self, name: str) -> List[Group]:
results = self._group_names.get(name.lower(), set())
return list(results)
# RecommendationEngine
class RecommendationEngine:
def get_people_you_may_know(self, member: Member) -> List[Member]:
# Collaborative filtering based on mutual connections
suggestions: Set[Member] = set()
for connection in member.connections:
for second_degree in connection.connections:
if second_degree not in member.connections and second_degree != member:
suggestions.add(second_degree)
return list(suggestions)
def get_job_recommendations(self, member: Member) -> List[JobPosting]:
# Implement based on profile skills and experiences
return []
def get_company_recommendations(self, member: Member) -> List[Company]:
# Implement based on industry and connections
return []
def get_group_recommendations(self, member: Member) -> List[Group]:
# Implement based on interests and connections' groups
return []
# Notification
class Notification(ABC):
def __init__(self, content: str):
self._notification_id = uuid.uuid4().int & ((1 << 31) - 1)
self._created_on = datetime.now()
self._content = content
self._is_read = False
@abstractmethod
def send_notification(self, member: Member):
pass
def mark_as_read(self):
self._is_read = True
class ConnectionNotification(Notification):
def __init__(self, content: str, invitation: ConnectionInvitation):
super().__init__(content)
self._invitation = invitation
def send_notification(self, member: Member):
print(f"Connection notification to {member.name}: {self._content}")
class MessageNotification(Notification):
def __init__(self, content: str, message: Message):
super().__init__(content)
self._message = message
def send_notification(self, member: Member):
print(f"Message notification to {member.name}: {self._content}")
class PostNotification(Notification):
def __init__(self, content: str, post: Post, notification_type: NotificationType):
super().__init__(content)
self._post = post
self._type = notification_type
def send_notification(self, member: Member):
print(f"Post notification to {member.name}: {self._content}")
class JobNotification(Notification):
def __init__(self, content: str, job: JobPosting):
super().__init__(content)
self._job = job
def send_notification(self, member: Member):
print(f"Job notification to {member.name}: {self._content}")
7. Key Design Decisions
-
State Pattern for Connection Invitations: Implemented ConnectionInvitationStatus enum with state transitions (PENDING → ACCEPTED/REJECTED/WITHDRAWN) to manage invitation lifecycle and prevent invalid state changes.
-
Strategy Pattern for Feed Ranking: Feed generation can use different ranking strategies (chronological, relevance-based, engagement-optimized) without modifying the core Feed class. This allows A/B testing of algorithms.
-
Observer Pattern for Notifications: When members create posts, like content, or send messages, the notification system automatically alerts relevant parties without tight coupling between content and notification subsystems.
-
Factory Pattern for Content Creation: Different content types (Post, Article, Comment) are created through factory methods that handle validation, indexing, and initial setup consistently.
-
Composite Pattern for Comment Threads: Comments can have nested replies forming tree structures. The Composite pattern allows uniform treatment of individual comments and reply threads.
-
Facade Pattern for Search: SearchIndex provides a simplified interface to complex search operations across members, companies, jobs, and groups, hiding distributed indexing and ranking logic.
-
Repository Pattern for Data Access: Separate repositories for Member, Company, JobPosting, and Group isolate data persistence logic from business logic, enabling easy database technology changes.
-
Decorator Pattern for Profile Enhancements: Premium members get enhanced profile features (badges, analytics, InMail) added dynamically without modifying the base Profile class.
-
Chain of Responsibility for Content Moderation: Posted content passes through validation chains (spam detection, profanity filter, link safety) before publication.
-
Template Method for Recommendation Algorithms: Different recommendation engines (People You May Know, Job Recommendations) follow the same template structure while customizing the scoring logic.