Design Example: Stack Overflow
Stack Overflow is a community-driven Q&A platform that relies on a complex reputation system, user-generated content, and a robust notification engine.
Step 1: Requirements Gathering
Core Use Cases:
- Questions: Users can post questions with tags.
- Answers: Users can provide answers to questions.
- Voting: Users can upvote or downvote questions and answers.
- Reputation: Users gain or lose reputation based on community interactions.
- Comments: Users can add comments to questions or answers.
- Bounties: Users can offer reputation points to reward high-quality answers.
- Moderation: High-reputation users can flag or close questions.
Reputation Rules:
- Answer accepted: +15
- Question upvoted: +10
- Answer upvoted: +10
- Question/Answer downvoted: -2
Step 2: Identify Core Objects
- User: Represents a community member with a reputation score.
- Question: The main content piece containing text and tags.
- Answer: A response to a specific question.
- Comment: A short text piece attached to a question or answer.
- Vote: Records a user's upvote/downvote action.
- Badge: A reward for specific achievements (e.g., "Great Answer").
- Notification: Alerts users about new answers or comments.
Step 3: Design Class Diagram
Step 4: Implementation in TypeScript
enum QuestionStatus { OPEN, CLOSED, BOUNTY, DELETED }
class User {
private reputation: number = 0;
constructor(public id: string, public name: string) {}
public updateReputation(delta: number) {
this.reputation += delta;
}
}
class Question {
private answers: Answer[] = [];
private comments: Comment[] = [];
private votes: Vote[] = [];
constructor(
public id: string,
public creator: User,
public title: string,
public content: string
) {}
public addAnswer(answer: Answer) {
this.answers.push(answer);
}
}
class Vote {
constructor(public userId: string, public value: number) {}
}Deep Dive: Observer Pattern for Notifications
When a question is answered, the original poster and anyone following the question should be notified.
interface Observer {
update(message: string): void;
}
class UserObserver implements Observer {
constructor(private user: User) {}
update(message: string) {
console.log(`Notification for ${this.user.name}: ${message}`);
}
}
class NotificationSystem {
private observers: Map<string, Observer[]> = new Map();
public subscribe(questionId: string, observer: Observer) {
const list = this.observers.get(questionId) || [];
list.push(observer);
this.observers.set(questionId, list);
}
public notify(questionId: string, message: string) {
this.observers.get(questionId)?.forEach(obs => obs.update(message));
}
}Wrap Up
Designing Stack Overflow is a lesson in State and Integrity. The reputation system must be deterministic, and the relationship between content (Questions, Answers, Comments) requires careful structuring to allow for efficient searching and notification delivery.
[!TIP] Use a Search Strategy pattern to allow switching between simple text search and complex tag-based filtering.