Stack Overflow

This I have written as part of my LLD Practice. Please let me know further improvements that can be done.

Also current design is Strong/Average/Lean Hire

Other Design Problems

/*

User Management: Users can ask questions, answer, comment, and vote.
Questions & Answers: Users can post questions and answers. Each question can have multiple answers, and one accepted answer.
Voting: Users can upvote or downvote questions and answers. Reputation is updated accordingly.
Comments: Users can comment on both questions and answers.
Tags: Questions can be tagged for categorization.
Reputation: Users gain or lose reputation based on votes and accepted answers.
Accepted Answer: The question author can mark one answer as accepted.

 */


import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.Map;

/* ========== Domain Layer ========== */


enum VoteType{
    UpVote, DownVote;
}

class User{
    String id;
    String userName;
    List<String> questionsIds;
    List<String> answerIds;
    List<String> commentIds;
    int reputation=0;
}

class Question{
    String id;
    String userId;
    String title;
    String description;
    List<String> answerIds;
    List<String> commentIds;
    List<String> tags;
    int upVote;
    int downVote;
    String acceptedAnswerId;
}

class Answer{
    String id;
    String userId;
    String questionId;
    String text;
    List<String> commentIds;
    int upVote;
    int downVote;
}

class Comment{
    String id;
    String userId;
    String parentId; //can be question/answer
    String text;
}

/* ========== Repository Layer ========== */

class UserRepository{
    Map<String,User> usersDb;

    void addUser(User user){

    }

    User getUser(String id){

    }
}

class QuestionRepository{
    Map<String,Question> questionDb;

    void addQuestion(Question question){

    }

    Question getQuestion(String id){

    }

    List<Question> findAll(){
        return new ArrayList<>(questionDb.values());
    }
}

class AnswerRepository{
    Map<String,Answer> answerDb;

    void addAnswer(Answer answer){

    }

    Answer getAnswer(String id){

    }
}

class CommentRepository{
    Map<String,Comment> commentDb;

    void addComment(Comment comment){

    }

    Comment getComment(String id){

    }
}

/* ========== Service Layer ========== */

interface SearchStretegy{
    List<Question> search(List<Question> questions, String query);
}

class KeyWordSeach implements SearchStrategy{
    @Override
    public List<Question> search(List<Question> questions, String query){

    }
}

class TagSeach implements SearchStrategy{
    @Override
    public  List<Question> search(List<Question> questions, String query){

    }
}

class SearchService{
    SearchStrategy strategy;
    QuestionRepository questionRepository;

    void setStrategy(SearchStrategy strategy){
        this.strategy=strategy;
    }

    List<Question> search(String query){
        return strategy.search(questionRepository.findAll(),query);
    }
}

// this can be seperated to 5 different services
class StackOverFlowService{
    UserRepository userRepository;
    QuestionRepository questionRepository;
    AnswerRepository answerRepository;
    CommentRepository commentRepository;

    User createUser(String name){
        User user=new User();
        user.userName=name;
        userRepository.addUser(user);
        return user;
    }

    Question postQuestion(String userId, String title, String desc, List<String> tags){
        Question q=new Question();
        q.userId=userId;
        q.title=title;
        q.description=desc;
        q.tags=tags;
        questionRepository.addQuestion(q);
        userRepository.getUser(userId).questionsIds.add(q.id);
        return q;
    }

    Answer postAnswer(String userId, String qId, String text){
        Answer answer=new Answer();
        answer.text=text;
        answer.questionId=qId;
        answerRepository.addAnswer(answer);
        userRepository.getUser(userId).answerIds.add(answer.id);
        questionRepository.getQuestion(qId).answerIds.add(answer.id);
        return answer;
    }

    Comment postComment(String userId, String parentId, String text){
        Comment comment=new Comment();
        comment.parentId=parentId;
        comment.text=text;
        commentRepository.addComment(comment);
        userRepository.getUser(userId).commentIds.add(comment.id);
        return comment;
    }

    void voteQuestion(String quesId, VoteType voteType){
        Question q=questionRepository.getQuestion(quesId);
        if(voteType==VoteType.UpVote){
            q.upVote++;
            userRepository.getUser(q.userId).reputation++;
        }
        else{
            q.downVote++;
            userRepository.getUser(q.userId).reputation--;
        }
    }

    void voteAnswer(String ansId, VoteType voteType){
        Answer a=answerRepository.getAnswer(ansId);
        if(voteType==VoteType.UpVote){
            a.upVote++;
            userRepository.getUser(a.userId).reputation++;
        }
        else{
            a.downVote++;
            userRepository.getUser(a.userId).reputation--;
        }
    }

    void acceptAnswer(String quesId, String ansId){
        Question q=questionRepository.getQuestion(quesId);
        q.acceptedAnswerId=ansId;
    }
}

/* ========== Controller Layer ========== */

class StackOverFlowController{
    StackOverFlowService stackOverFlowService;
    SearchService searchService;

    User createUser(String name){
        return stackOverFlowService.createUser(name);
    }

    Question postQuestion(String userId, String title, String desc, List<String> tags){
        return stackOverFlowService.postQuestion(userId,title,desc,tags);
    }

    Answer postAnswer(String userId, String qId, String text){
        return stackOverFlowService.postAnswer(userId,qId,text);
    }

    Comment postComment(String userId, String parentId, String text){
        return stackOverFlowService.postComment(userId,parentId,text);
    }

    List<Question> searchByKeyWord(String query){
        searchService.strategy=new KeyWordSeach();
        return searchService.search(query);
    }

    List<Question> searchByTag(String query){
        searchService.strategy=new TagSeach();
        return searchService.search(query);
    }

    void voteQuestion(String quesId, VoteType voteType){
        stackOverFlowService.voteQuestion(quesId,voteType);
    }

    void voteAnswer(String ansId, VoteType voteType){
        stackOverFlowService.voteAnswer(ansId,voteType);
    }

    void acceptAnswer(String quesId, String ansId){
        stackOverFlowService.acceptAnswer(quesId,ansId);
    }
}

public class StackOverFlow {
    public static void main(String[] args) {
        StackOverFlowController controller=new StackOverFlowController();

        User u1=controller.createUser("Nikhil");
        Question q1=controller.postQuestion(u1.id, "What is LLD?","How to tackle its problems", Arrays.asList("LLD","Design"));

        User u2=controller.createUser("Mukul");
        controller.postAnswer(u2.id, q1.id, "OOPs+Solid Principle");
    }
}
Comments (1)