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

[BE] EntryCode 도메인을 개선한다. #399

Closed
seokjin8678 opened this issue Aug 30, 2023 · 0 comments · Fixed by #401
Closed

[BE] EntryCode 도메인을 개선한다. #399

seokjin8678 opened this issue Aug 30, 2023 · 0 comments · Fixed by #401
Assignees
Labels
BE 백엔드에 관련된 작업 ⚙️ 리팩터링 리팩터링에 관련된 작업 🙋‍♀️ 제안 제안에 관한 작업

Comments

@seokjin8678
Copy link
Collaborator

seokjin8678 commented Aug 30, 2023

✨ 세부 내용

EntryCode 도메인에 다음과 같은 문제가 있습니다.

EntryCode의 생성은 create 정적 메서드에만 의존합니다.

또한 create 정적 메서드의 파라미터로 EntryCodeProvider가 필요합니다.

해당 이유는 만료 시간의 필요 때문인데, 만료 시간을 구하려면 EntryCode의 period와 offset이 필요합니다.

하지만 EntryCode의 period와 offset를 가져오려면, 인스턴스를 만들어야 하고, 인스턴스를 만드려면 EntryCodeProvider 에서 생성한 코드가 필요합니다.

닭이 먼저냐, 달걀이 먼저냐 하는 문제가 발생합니다.

따라서 해당 문제를 해결하려고 EntryCode의 create() 정적 메서드를 통해 EntryCode를 생성합니다.

EntryCode를 생성하는 것은 EntryCode의 정적 변수인 DEFAULT_PERIOD, DEFAULT_OFFSET을 토대로 구하므로, create 메소드에 EntryCodeProviderMemberTicket을 포함하는 것은 코드의 흐름을 읽는 데 복잡성을 증가시킨다 생각합니다.

또한 정적 변수에 의존하므로, 추후 동적으로 만료 시간을 변경하기가 힘듭니다.

따라서 다음과 같이 개선해 볼 수 있을것 같습니다.

public class EntryCodeTime {

    private static final long DEFAULT_PERIOD = 30;
    private static final long DEFAULT_OFFSET = 10;
    private static final int MILLISECOND_FACTOR = 1000;
    private static final int MINIMUM_PERIOD = 0;
    private static final int MINIMUM_OFFSET = 0;

    private final long period;
    private final long offset;

    public EntryCodeTime() {
        this(DEFAULT_PERIOD, DEFAULT_OFFSET);
    }

    public EntryCodeTime(long period, long offset) {
        validate(period, offset);
        this.period = period;
        this.offset = offset;
    }

    private void validate(long period, long offset) {
        if (period <= MINIMUM_PERIOD) {
            throw new InternalServerException(ErrorCode.INVALID_ENTRY_CODE_PERIOD);
        }
        if (isNegative(offset)) {
            throw new InternalServerException(ErrorCode.INVALID_ENTRY_CODE_OFFSET);
        }
    }

    private boolean isNegative(long offset) {
        return offset < MINIMUM_OFFSET;
    }

    public Date getExpiredAt(long currentTimeMillis) {
        return new Date(currentTimeMillis + (period + offset) * MILLISECOND_FACTOR);
    }

    public long getPeriod() {
        return period;
    }

    public long getOffset() {
        return offset;
    }
}
public class EntryCode {

    private final String code;
    private final EntryCodeTime entryCodeTime;

    public EntryCode(String code, EntryCodeTime entryCodeTime) {
        this.code = code;
        this.entryCodeTime = entryCodeTime;
    }

    public String getCode() {
        return code;
    }

    public long getPeriod() {
        return entryCodeTime.getPeriod();
    }

    public long getOffset() {
        return entryCodeTime.getOffset();
    }
}
public EntryCodeResponse createEntryCode(Long memberId, Long memberTicketId) {
    MemberTicket memberTicket = findMemberTicket(memberTicketId);
    if (!memberTicket.isOwner(memberId)) {
        throw new BadRequestException(ErrorCode.NOT_MEMBER_TICKET_OWNER);
    }
    if (!memberTicket.canEntry(LocalDateTime.now())) {
        throw new BadRequestException(ErrorCode.NOT_ENTRY_TIME);
    }
    EntryCodeTime entryCodeTime = new EntryCodeTime();
    String code = entryCodeProvider.provide(EntryCodePayload.from(memberTicket),
        entryCodeTime.getExpiredAt(new Date().getTime()));
    EntryCode entryCode = new EntryCode(code, entryCodeTime);
    return EntryCodeResponse.of(entryCode);
}

시간에 관련된 부분을 EntryCodeTime 객체로 분리하여, 코드 생성 전 EntryCodeProvider에서 만료시간을 받을 수 있게 합니다.
그 뒤 EntryCode의 생성자로 코드와 시간에 관련된 객체를 주입하여 EntryCode를 생성합니다.

또한 개선할 부분이 EntryCodeProvider.provide() 메서드인데, 굳이 매개변수로 EntryCodePayload를 받을 필요가 없고, 바로 MemberTicket을 받아도 될 것 같습니다.

String code = entryCodeProvider.provide(memberTicket, entryCodeTime.getExpiredAt(new Date().getTime()));

또한 추후 Clock 사용을 한다면 다음과 같이 변경 할 수 있겠네요!

entryCodeProvider.provide(memberTicket, entryCodeTime.getExpiredAt(clock.millis()));

⏰ 예상 소요 시간

3시간

@seokjin8678 seokjin8678 added BE 백엔드에 관련된 작업 ⚙️ 리팩터링 리팩터링에 관련된 작업 🙋‍♀️ 제안 제안에 관한 작업 labels Aug 30, 2023
@seokjin8678 seokjin8678 self-assigned this Aug 30, 2023
@seokjin8678 seokjin8678 linked a pull request Aug 30, 2023 that will close this issue
seokjin8678 added a commit that referenced this issue Sep 14, 2023
* refactor: EntryCode에서 시간에 관련된 부분 분리

* refactor: EntryCodeProvider 파라미터 수정

- EntryCodePayload -> MemberTicket

* test: JwtEntryCodeProvider 테스트 코드 개선

* feat: JwtEntryCodeExtractor null 검사 추가

* refactor: create 정적 메서드로 생성 변경

* refactor: EntryCodeProvider 매개변수 EntryCodePayload로 변경

* refactor: EntryCodeManager 추가, 사용

* refactor: 단위에 언더스코어 추가
@github-project-automation github-project-automation bot moved this from Todo to Done in 2023-festa-go Sep 14, 2023
BGuga pushed a commit that referenced this issue Oct 17, 2023
* refactor: EntryCode에서 시간에 관련된 부분 분리

* refactor: EntryCodeProvider 파라미터 수정

- EntryCodePayload -> MemberTicket

* test: JwtEntryCodeProvider 테스트 코드 개선

* feat: JwtEntryCodeExtractor null 검사 추가

* refactor: create 정적 메서드로 생성 변경

* refactor: EntryCodeProvider 매개변수 EntryCodePayload로 변경

* refactor: EntryCodeManager 추가, 사용

* refactor: 단위에 언더스코어 추가
BGuga pushed a commit that referenced this issue Oct 17, 2023
* refactor: EntryCode에서 시간에 관련된 부분 분리

* refactor: EntryCodeProvider 파라미터 수정

- EntryCodePayload -> MemberTicket

* test: JwtEntryCodeProvider 테스트 코드 개선

* feat: JwtEntryCodeExtractor null 검사 추가

* refactor: create 정적 메서드로 생성 변경

* refactor: EntryCodeProvider 매개변수 EntryCodePayload로 변경

* refactor: EntryCodeManager 추가, 사용

* refactor: 단위에 언더스코어 추가
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
BE 백엔드에 관련된 작업 ⚙️ 리팩터링 리팩터링에 관련된 작업 🙋‍♀️ 제안 제안에 관한 작업
Projects
Status: Done
Development

Successfully merging a pull request may close this issue.

1 participant