web study/Spring
단일책임원칙 위배 트러블 슈팅 ApplicationEventPublisher와 EventListner
65살까지 코딩
2022. 4. 5. 02:41
728x90
반응형
단일책임원칙이란 SOLID 원칙에서의 S로 하나의 메소드, 클래스는 하나의 책임만을 가져야 한다는 원칙이다.
이번 프로젝트를하면서 SOLID원칙을 지키고자 했지만 사실 빨리 개발하느라 바뻐 SOLID원칙은 거의 지키지 못한것 같다.
이번 프로젝트에서 어떤 로직을 충족하면 점수를 주거나 알람을 보내는 로직이 있었다.
일정 로직이 충족되는 로직과 알람을보내거나 점수를 보내는 로직이 한 메소드 안에 들어있어 코드가 너무 복잡했고 절대로 남이 봐서는 이해할수 없을 것 같은 코드였다.
이에 대한 해결책으로 ApplicationEventPubliser을 이용해 Event를 만들고 EventListener를 통해 일정 이벤트가 충족되었을때 새로운 일정 로직이 시작되도록 하여 한 메소드를 이벤트 기준으로 나누었다.
즉 하나의 트렌젝션에서 실행되던 메소드가 두 트랙잭션으로 나눠져서 실행되는 것이다.
예를들어
@Transactional
public ResponseEntity<?> writeComment(Long answerId, CommentRequestDto commentRequestDto, User user) {
Answer findAnswer = answerRepository.findById(answerId).orElseThrow(
() -> new AnswerNotFoundException("해당 답글이 존재하지 않습니다.")
);
String commentContent = commentRequestDto.getComment();
Long parentCommentId = commentRequestDto.getParentCommentId();
Comment comment = null;
if (parentCommentId == null) {
String timestamp = commentRequestDto.getTimestamp();
comment = new Comment(commentContent, findAnswer, user, timestamp);
user.getCommentList().add(comment);
if (!findAnswer.getUser().equals(comment.getUser())) {
Alarm alarm = new Alarm(findAnswer.getUser(), comment.getUser().getNickName(), Type.comment, findAnswer.getId(), findAnswer.getTitle());
Alarm save1 = alarmRepository.save(alarm);
alarmService.alarmByMessage(new MessageDto(save1));
}
} else {
comment = new Comment(commentContent, parentCommentId, findAnswer, user);
user.getCommentList().add(comment);
//알람로직.
Comment findcomment = commentRepository.findById(parentCommentId).orElseThrow(
() -> new CommentNotFoundException("댓글 없습니다.")
);
if (!findcomment.getUser().equals(comment.getUser())) {
Alarm alarm1 = new Alarm(findcomment.getUser(), comment.getUser().getNickName(), Type.child, parentCommentId, findcomment.getContent());
Alarm save2 = alarmRepository.save(alarm1);
alarmService.alarmByMessage(new MessageDto(save2));
}
}
Comment save = commentRepository.save(comment);
CommentResponseDto commentResponseDto = new CommentResponseDto(save, answerId);
// 업적획득 로직
User achievementUser = userRepository.findById(user.getId()).orElseThrow(
() -> new IllegalArgumentException("업적 달성 유저가 존재하지 않습니다."));
achievementUser.getAchievement().setAchievement6(1);
return ResponseEntity.ok().body(commentResponseDto);
}
2주전 코드인데 굉장히 지저분하다...
일단 코드를 보면 댓글 작성이 완료가 되면
1. 유저에게 알람을보내준다
2. 유저에게 업적을 회득시킨다.
라는 2가지 기능이 더 추가된다.
나는 댓글 작성완료와 그 후에 실행되는 것 총 2가지 책임으로 나누어
해결하였다.
댓글작성로직
public CommentResponseDto writeComment(Long answerId, CommentRequestDto commentRequestDto, User user) {
Answer findAnswer = ComfortMethods.getAnswer(answerId);
Long parentCommentId = commentRequestDto.getParentCommentId();
Comment comment = null;
if (parentCommentId == null) {
String timestamp = commentRequestDto.getTimestamp();
comment = new Comment(
commentRequestDto.getComment(),
findAnswer,
user,
timestamp
);
//이벤트 발동!
applicationEventPublisher.publishEvent(new CommentWriteEvent(findAnswer.getUser(), user,findAnswer, AlarmType.comment));
} else {
Comment parentComment = ComfortMethods.getComment(parentCommentId);
comment = new Comment(
commentRequestDto.getComment(),
parentComment,
findAnswer,
user);
//이벤트 발동!
applicationEventPublisher.publishEvent(new CommentWriteEvent(parentComment.getUser(), user, comment, AlarmType.child));
}
Comment save = commentRepository.save(comment);
return new CommentResponseDto(save, answerId);
}
댓글 작성완료후 로직
@TransactionalEventListener(phase = TransactionPhase.AFTER_COMMIT)
public void commentWriteEvent(CommentWriteEvent commentWriteEvent) {
User receiver = commentWriteEvent.getReceiver();
User sender = commentWriteEvent.getSender();
Object object = commentWriteEvent.getObject();
AlarmType alarmType = commentWriteEvent.getAlarmType();
//알람보내기
if (!receiver.getNickName().equals(sender.getNickName())) {
if(alarmType.equals(AlarmType.comment)) {
answerAlarm(receiver, sender, (Answer) object, alarmType);
}else if(alarmType.equals(AlarmType.child)){
Comment comment = (Comment) object;
Long parentCommentId = comment.getParentComment().getId();
Optional<Comment> parent = commentRepository.findById(parentCommentId);
Comment comment1 = parent.get();
commentAlarm(receiver,sender, comment1, alarmType);
}
}
//업적획득
User findUser = ComfortMethods.getUser(sender.getId());
if(findUser.getAchievement().getAchievement6() == 0) {
findUser.getAchievement().setAchievement6(1);
achieveAlarm(findUser,"리액션HAMA");
}
}
728x90
반응형