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
/*
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");
}
}