Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

refactor: notification을 타입계층으로 리팩터링 #929

Merged
merged 14 commits into from
Jan 8, 2025
Merged
6 changes: 3 additions & 3 deletions backend/src/main/java/com/ody/mate/service/MateService.java
Original file line number Diff line number Diff line change
Expand Up @@ -55,14 +55,14 @@ public MateSaveResponseV2 saveAndSendNotifications(
Mate mate = saveMateAndEta(mateSaveRequest, member, meeting);

FcmTopic fcmTopic = new FcmTopic(meeting);
sendEntry(meeting, mate, fcmTopic);
sendEntry(mate, fcmTopic);
notificationService.subscribeTopic(member.getDeviceToken(), fcmTopic);
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

... Entry 알림을 발송 + 구독 + DepartureReminder 알림을 발송 하는 식으로 MateService 로직에 종속적인 로직이 구현되어 있습니다.

그러나, 위의 로직은 MateService에서 드러나야 하는 로직이지, 알림 서비스가 알고 있어야할 내용이 아니라 생각했습니다.

[질문] 노션에 작성해주신 부분 중에 해당 로직을 MateService 로직에 종속적인 로직이라고 본 이유가 있나요?

저는 콜리와 반대로 '토픽을 구독한다'를 MateService가 알고 있을 필요가 없다고 생각하는데, 그 이유는 토픽을 구독하는 것은 모임원 모두에게 알림을 보내기 위한 방법이라서 입니다. MateService는 모두에게 알림을 보낸다 정도만 알아도 충분하다고 생각해서 오히려 내부 구현 + fcm 관련 배경 지식이 노출된 느낌이 들어요.

Copy link
Contributor Author

@coli-geonwoo coli-geonwoo Jan 7, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

첫째로, 해당 메서드가 약속 참여 플로우 이외에 그 어떤 비즈니스 로직에도 확장성있게 사용될수가 없었어요. 참여 알림 보내고 + 구독하고 + 약속리마인더 알림을 보낸다 -> 라는 흐름은 약속 참여시 약속을 보내는 방법이지 알림 서비스가 알아야할 약속 참여 시 필요한 알림 로직이 아니라 생각했습니다.

두번째로, saveAndSendNotification으로 추상화된 메서드 명을 보면 그저 알림을 저장하고 보내는 것으로 생각이 되는데, 저장을 하는 알림이 약속 리마인더와 출발알림으로 정해져 있습니다. 다른 알림은 저장될수가 없고 보낼수도 없습니다. mateService 참여 시 필요한 알림을 해당 메서드에서 보내고 있었습니다.

세번째로, fcm 구현이 밖으로 드러나있다는 점에 대해서는 동의합니다. 해당 구현을 캡슐화하기 위해 sendToDevice, sendToTopic 등의 메서드를 만들어주어 subscribe를 드러내지 않는 것은 동의합니다. 그러나, notificationService가 특정 알림 객체를 위한 메서드를 가지는 것은 비즈니스 로직상 어떤 알림을 보냈는지를 상위 서비스가 아니라 하위 서비스인 notificationService가 알게된다는 점에서 너무 많은 것을 알고 있다고 생각합니다. 또한, 기존에 notificationServic가 unsubscribe라는 메서드를 가지고 있다는 점, fcmTopic 필드를 meeting이 가지고 있다는 점에서 fcm 로직을 도메인들도 알고 있다고 판단한 부분도 있습니다.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

오 납득했습니다!! 자세하게 설명해주어 고마워요 🥦🙇‍♀️

sendDepartureReminder(meeting, mate, fcmTopic);
return MateSaveResponseV2.from(meeting);
}

private void sendEntry(Meeting meeting, Mate mate, FcmTopic fcmTopic) {
Entry entry = new Entry(mate, meeting, fcmTopic);
private void sendEntry(Mate mate, FcmTopic fcmTopic) {
Entry entry = new Entry(mate, fcmTopic);
notificationService.saveAndSchedule(entry.toNotification());
}

Expand Down
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

~ 👍

Original file line number Diff line number Diff line change
Expand Up @@ -61,7 +61,7 @@ public Notification(
}

public boolean isDepartureReminder() {
return this.type.isDepartureReminder();
return type.isDepartureReminder();
}

public boolean isStatusDismissed() {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,26 +6,26 @@
import com.ody.notification.domain.NotificationStatus;
import com.ody.notification.domain.NotificationType;
import java.time.LocalDateTime;
import lombok.AllArgsConstructor;

@AllArgsConstructor
public abstract class AbstractNotification {

private final Long id;
private final Mate mate;
private final NotificationType type;
private final LocalDateTime sendAt;
private final NotificationStatus status;
private final FcmTopic fcmTopic;

public AbstractNotification(
protected AbstractNotification(
Mate mate,
NotificationType type,
LocalDateTime sendAt,
NotificationStatus status,
FcmTopic fcmTopic
) {
this(null, mate, type, calculateSendAt(sendAt), status, fcmTopic);
this.mate = mate;
this.type = getType();
this.sendAt = calculateSendAt(sendAt);
this.status = status;
this.fcmTopic = fcmTopic;
}

private static LocalDateTime calculateSendAt(LocalDateTime sendAt) {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

[제안]
static 키워드 이제는 제거해주어도 되겠네요! 이 부분은 제가 코드 수정하면서 반영하겠습니다ㅎㅎ

Suggested change
private static LocalDateTime calculateSendAt(LocalDateTime sendAt) {
private LocalDateTime calculateSendAt(LocalDateTime sendAt) {

Expand All @@ -35,7 +35,9 @@ private static LocalDateTime calculateSendAt(LocalDateTime sendAt) {
return sendAt;
}

abstract NotificationType getType();

public Notification toNotification() {
return new Notification(id, mate, type, sendAt, status, fcmTopic);
return new Notification(null, mate, type, sendAt, status, fcmTopic);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

[제안]
Notification id를 받지 않은 생성자에서 null을 넣어주고 있으니 제거해주어도 되겠네요! 괜찮으시면 이 부분도 제가 추후에 반영해두겠습니다~

Suggested change
return new Notification(null, mate, type, sendAt, status, fcmTopic);
return new Notification(mate, type, sendAt, status, fcmTopic);

}
}
Original file line number Diff line number Diff line change
Expand Up @@ -8,9 +8,12 @@

public class DepartureReminder extends AbstractNotification {

private static final NotificationType type = NotificationType.DEPARTURE_REMINDER;

public DepartureReminder(Mate mate, DepartureTime departureTime, FcmTopic fcmTopic) {
super(mate, type, departureTime.getValue(), NotificationStatus.PENDING, fcmTopic);
super(mate, departureTime.getValue(), NotificationStatus.PENDING, fcmTopic);
}

@Override
public NotificationType getType() {
return NotificationType.DEPARTURE_REMINDER;
}
}
Original file line number Diff line number Diff line change
@@ -1,18 +1,20 @@
package com.ody.notification.domain.types;

import com.ody.mate.domain.Mate;
import com.ody.meeting.domain.Meeting;
import com.ody.notification.domain.FcmTopic;
import com.ody.notification.domain.NotificationStatus;
import com.ody.notification.domain.NotificationType;
import java.time.LocalDateTime;

public class Entry extends AbstractNotification {

private static final NotificationType type = NotificationType.ENTRY;
public Entry(Mate mate, FcmTopic fcmTopic) {
super(mate, LocalDateTime.now(), NotificationStatus.DONE, fcmTopic);
}

public Entry(Mate mate, Meeting meeting, FcmTopic fcmTopic) {
super(mate, type, LocalDateTime.now(), NotificationStatus.DONE, fcmTopic);
@Override
public NotificationType getType() {
return NotificationType.ENTRY;
}
}

Original file line number Diff line number Diff line change
Expand Up @@ -7,9 +7,12 @@

public class MateLeave extends AbstractNotification {

private static final NotificationType type = NotificationType.LEAVE;

public MateLeave(Mate mate) {
super(mate, type, LocalDateTime.now(), NotificationStatus.DONE, null);
super(mate, LocalDateTime.now(), NotificationStatus.DONE, null);
}

@Override
public NotificationType getType() {
return NotificationType.LEAVE;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -7,9 +7,12 @@

public class MemberDeletion extends AbstractNotification {

private static final NotificationType type = NotificationType.MEMBER_DELETION;

public MemberDeletion(Mate mate) {
super(mate, type, LocalDateTime.now(), NotificationStatus.DONE, null);
super(mate, LocalDateTime.now(), NotificationStatus.DONE, null);
}

@Override
public NotificationType getType() {
return NotificationType.MEMBER_DELETION;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -7,9 +7,12 @@

public class Nudge extends AbstractNotification {

private static final NotificationType type = NotificationType.NUDGE;

public Nudge(Mate nudgeMate) {
super(nudgeMate, type, LocalDateTime.now(), NotificationStatus.DONE, null);
super(nudgeMate, LocalDateTime.now(), NotificationStatus.DONE, null);
}

@Override
public NotificationType getType() {
return NotificationType.NUDGE;
}
}
Original file line number Diff line number Diff line change
@@ -1,8 +1,6 @@
package com.ody.notification.domain.types;

import static org.assertj.core.api.Assertions.assertThat;
import static org.mockito.ArgumentMatchers.any;
import static org.mockito.ArgumentMatchers.eq;

import com.ody.common.Fixture;
import com.ody.mate.domain.Mate;
Expand Down Expand Up @@ -33,5 +31,4 @@ void sendImmediatelyIfDepartureTimeIsPast() {

assertThat(actualSendTime).isEqualTo(now);
}

}
Loading