Design Facebook - a social network
Published: 2024-07-02 23:03:26



**Problem definition**

Facebook is a social media platform for users to connect with people and engage with different types of media and content. Users can connect with other users by sending friend requests or using the direct messaging feature. Each user has a profile where they can create posts to share with their friends. Facebook also allows its users to create pages regarding a topic of interest and groups to form a community of similar people. Facebook generates a personalized feed for its users based on their friends, liked pages, groups, and the content they engage with to ensure the best experience.

**System Requirements**

We will focus on the following set of requirements while designing Facebook:

1. Each member should be able to add information about their basic profile, work experience, education, etc.

2. Any user of our system should be able to search other members, groups or pages by their name.

3. Members should be able to send and accept/reject friend requests from other members.

4. Members should be able to follow other members without becoming their friend.

5. Members should be able to create groups and pages, as well as join already created groups, and follow pages.

6. Members should be able to create new posts to share with their friends.

7. Members should be able to add comments to posts, as well as like or share a post or comment.

8. Members should be able to create privacy lists containing their friends. 

9. Members can link any post with a privacy list to make the post visible only to the members of that list.

10. Any member should be able to send messages to other members.

11. Any member should be able to add a recommendation for any page.

12. The system should send a notification to a member whenever there is a new message or friend request or comment on their post.

13. Members should be able to search through posts for a word.

**Extended Requirement**: Write a function to find a connection suggestion for a member.

**Use case diagram**

We have three main Actors in our system:

**Member**: All members can search for other members, groups, pages, or posts, as well as send friend requests, create posts, etc.

**Admin**: Mainly responsible for admin functions like blocking and unblocking a member, etc.

**System**: Mainly responsible for sending notifications for new messages, friend requests, etc.

Here are the top use cases of our system:

**Add/update profile**: Any member should be able to create their profile to reflect their work experiences, education, etc.

**Search**: Members can search for other members, groups or pages. Members can send a friend request to other members.

**Follow or Unfollow a member or a page**: Any member can follow or unfollow any other member or page.

**Send message**: Any member can send a message to any of their friends.

**Create post**: Any member can create a post to share with their friends and like or add comments to any post visible to them.

**Send notification**: The system can send notifications for new messages, friend requests, etc.

1. **Identify Core Entities**:

Based on the requirements, we can identify the following main entities:

- User
- Profile
- Post
- Comment
- Group
- Page
- Message
- Notification
- PrivacyList

Reasoning: These entities represent the main concepts in our domain. They are derived from the nouns in our requirements and represent the core objects that our system will manage.

2. **Define Relationships**:

- User has one Profile
- User can have many Posts
- User can have many Comments
- User can be a member of many Groups
- User can follow many Pages
- User can send/receive many Messages
- User can have many Notifications
- User can have many PrivacyLists
- Post can have many Comments
- Group can have many Users as members
- Page can have many Users as followers

Reasoning: These relationships define how our entities interact with each other. They're crucial for understanding the structure of our domain.

3. **Implement Core Entities**:

Let's start implementing our domain model in C#, discussing the reasoning behind each class:

```csharp
public class User
{
    public string Id { get; set; }
    public string Name { get; set; }
    public Profile Profile { get; set; }
    public List<User> Friends { get; set; }
    public List<User> Followers { get; set; }
    public List<User> Following { get; set; }
    public List<Group> Groups { get; set; }
    public List<Page> FollowedPages { get; set; }
    public List<PrivacyList> PrivacyLists { get; set; }

    public void SendFriendRequest(User user) { /* Implementation */ }
    public void AcceptFriendRequest(User user) { /* Implementation */ }
    public void RejectFriendRequest(User user) { /* Implementation */ }
    public void Follow(User user) { /* Implementation */ }
    public void Unfollow(User user) { /* Implementation */ }
    public void JoinGroup(Group group) { /* Implementation */ }
    public void FollowPage(Page page) { /* Implementation */ }
    public void CreatePost(string content, PrivacyList privacyList = null) { /* Implementation */ }
    public void SendMessage(User recipient, string content) { /* Implementation */ }
}
```

Reasoning: The User class is central to our system. It encapsulates user-related data and actions. We've included methods for friend requests, following, joining groups, etc., as these are user-initiated actions.

```csharp
public class Profile
{
    public string About { get; set; }
    public List<WorkExperience> WorkExperiences { get; set; }
    public List<Education> Educations { get; set; }
    // Other profile-related properties
}

public class WorkExperience
{
    public string Company { get; set; }
    public string Position { get; set; }
    public DateTime StartDate { get; set; }
    public DateTime? EndDate { get; set; }
}

public class Education
{
    public string Institution { get; set; }
    public string Degree { get; set; }
    public DateTime StartDate { get; set; }
    public DateTime? EndDate { get; set; }
}
```

Reasoning: We've separated Profile into its own class to encapsulate profile-specific information. WorkExperience and Education are separate classes to allow for multiple entries and to keep the Profile class clean.

```csharp
public class Post
{
    public string Id { get; set; }
    public User Author { get; set; }
    public string Content { get; set; }
    public DateTime CreatedAt { get; set; }
    public List<Comment> Comments { get; set; }
    public List<User> Likes { get; set; }
    public List<User> Shares { get; set; }
    public PrivacyList PrivacyList { get; set; }

    public void AddComment(User user, string content) { /* Implementation */ }
    public void Like(User user) { /* Implementation */ }
    public void Share(User user) { /* Implementation */ }
}

public class Comment
{
    public string Id { get; set; }
    public User Author { get; set; }
    public string Content { get; set; }
    public DateTime CreatedAt { get; set; }
    public List<User> Likes { get; set; }

    public void Like(User user) { /* Implementation */ }
}
```

Reasoning: Post and Comment are separate classes but share some common properties. We've included methods for adding comments, liking, and sharing directly in the Post class as these are post-specific actions.

```csharp
public class Group
{
    public string Id { get; set; }
    public string Name { get; set; }
    public User Admin { get; set; }
    public List<User> Members { get; set; }
    public List<Post> Posts { get; set; }

    public void AddMember(User user) { /* Implementation */ }
    public void RemoveMember(User user) { /* Implementation */ }
    public void CreatePost(User user, string content) { /* Implementation */ }
}

public class Page
{
    public string Id { get; set; }
    public string Name { get; set; }
    public User Admin { get; set; }
    public List<User> Followers { get; set; }
    public List<Post> Posts { get; set; }
    public List<string> Recommendations { get; set; }

    public void AddFollower(User user) { /* Implementation */ }
    public void RemoveFollower(User user) { /* Implementation */ }
    public void CreatePost(User admin, string content) { /* Implementation */ }
    public void AddRecommendation(User user, string recommendation) { /* Implementation */ }
}
```

Reasoning: Group and Page are similar in some ways (they both have members/followers and posts) but different in others (pages have recommendations). We've kept them as separate classes to allow for these differences.

```csharp
public class Message
{
    public string Id { get; set; }
    public User Sender { get; set; }
    public User Recipient { get; set; }
    public string Content { get; set; }
    public DateTime SentAt { get; set; }
}

public class Notification
{
    public string Id { get; set; }
    public User Recipient { get; set; }
    public string Content { get; set; }
    public DateTime CreatedAt { get; set; }
    public bool IsRead { get; set; }
}

public class PrivacyList
{
    public string Id { get; set; }
    public string Name { get; set; }
    public List<User> Members { get; set; }
}
```

Reasoning: Message, Notification, and PrivacyList are relatively simple classes that encapsulate their respective concepts.

4. **Implement the Search Functionality**:

```csharp
public class SearchService
{
    public List<User> SearchUsers(string query) { /* Implementation */ }
    public List<Group> SearchGroups(string query) { /* Implementation */ }
    public List<Page> SearchPages(string query) { /* Implementation */ }
    public List<Post> SearchPosts(string query) { /* Implementation */ }
}
```

Reasoning: We've centralized search functionality in a separate service class. This allows for easy expansion of search capabilities and keeps the search logic separate from our domain entities.

5. I**mplement the Notification System**:

```csharp
public class NotificationService
{
    public void SendNotification(User recipient, string content) { /* Implementation */ }
}
```

Reasoning: A separate notification service allows for centralized management of notifications and easy integration with external notification systems if needed.

6. **Implement the Connection Suggestion Functionality**:

```csharp
public class ConnectionSuggestionService
{
    public List<User> GetConnectionSuggestions(User user)
    {
        // Implementation could consider:
        // 1. Friends of friends
        // 2. Users with similar interests (based on liked pages, groups)
        // 3. Users with similar profile information (e.g., same school, workplace)
        // 4. Users who have interacted with similar posts
    }
}
```

Reasoning: This service encapsulates the logic for suggesting connections, which could be quite complex and involve multiple factors.

This design provides a solid foundation for the Facebook-like social network system. It encapsulates the main entities and their behaviors, defines clear relationships between classes, and separates concerns where appropriate.

Some trade-offs and considerations:

1. We've chosen to include methods like SendFriendRequest, AcceptFriendRequest in the User class. An alternative would be to have a separate FriendshipService to manage these operations. The trade-off is between having a more feature-rich User class versus a potentially more maintainable and scalable separate service.

2. We've kept the design relatively simple for clarity. In a real-world scenario, you might need to consider more complex scenarios like privacy settings, user roles, etc.

3. For scalability, you might want to consider separating read and write models (CQRS pattern) for high-traffic entities like Post.

4. In a real implementation, you'd need to carefully consider data consistency, especially for operations that modify multiple entities (like adding a comment, which affects both the Post and creates a new Comment).

5. This design doesn't address how data will be persisted. In a real-world scenario, you'd need to consider how these domain objects map to a database schema.