우테코 3주 차 프리코스 회고 (lotto)

squareyun·2022년 11월 15일
0

회고

목록 보기
2/4

어렵다. 프리코스를 진행하면서 부족한 실력을 너무나도 실감한다. 기능적인 요구 사항 구현이 어렵다기보다, 프로그래밍 요구 사항을 지키기가 어렵다. 적절한 객체 분리 및 클래스 구성하는 것을 중점으로 구현하려고 노력하였다. 어떻게든 구현은 했지만 제대로 클래스 분리를 한 것인지도 잘 모르겠다. 다만, 이런 고민들이 나를 한 층 성장시켰다고 확신한다.

코드를 술술 써 내려가고 싶었지만, 모든 것을 한 번에 생각하려다 보니 시간이 많이 소요되었다. 일단 프로그램을 완성한 후 리팩토링을 거치는 방법이 좋을까? 고민이 된다. 과제 제출 날인 오늘 대규모 리팩토링을 진행했다. 패키지 분리하지 않았었고, 컨트롤러의 필요성을 느꼈기 때문이다. 급하게 구조를 변경하느라 완벽하게 리팩토링하지 못했고 만족스럽지 못하다. 다음 주 차에서는 더 신경 써서 구현하리라 다짐한다.

2 주차 공통 피드백

2주 차 피드백을 반영하도록 노력하였다. 인상 깊었던 피드백은 다음과 같다.

기능 목록을 업데이트한다. 죽은 문서가 아니라 살아있는 문서를 만들기 위해 노력한다.

변수 이름에 자료형은 사용하지 않는다.

처음부터 큰 단위의 테스트를 만들지 않는다.
테스트의 중요한 목적 중 하나는 내가 작성하는 코드에 대해 빠르게 피드백을 받는 것.
문제를 작게 나누고, 그 중 핵심 기능에 가까운 부분부터 작게 테스트를 만들어 나간다.

기능 목록

2주 차 피드백에서 기능 목록 업데이트를 하라고 했다. 기존에 기능 목록이 완벽해야 한다고 생각해서, 코드를 써 내려가지 못하고 기능 목록에만 집중했었다. 이와 달리 큰 기능 목록을 작성하고, 세부 기능 목록은 구현하면서 추가로 업데이트하는 방식으로 진행했다.

  • 로또 구입 금액을 입력 받기
    • 1,000원으로 나누어 떨어지지 않는 경우 예외 처리
    • 음수와 0 예외 처리
  • 당첨 번호를 입력 받기
    • 1부터 45 사이의 숫자가 아닌 경우 예외 처리
    • 서로 다른 6개의 숫자가 아닌 경우 예외 처리
    • 보너스 번호도 예외 처리
  • 로또 번호를 발행
    • 서로 다른 6개의 랜덤 숫자
    • 오름차순 정렬
  • 당첨 내역 확인
    • 당첨 결과 Enum 타입 생성
    • 몇 개의 자리가 일치하는지 확인
    • 보너스 볼 일치하는지 확인
  • 수익률 계산하기
    • 소수점 둘째 자리에서 반올림

Enum

Java Enum을 적용한다. (추가된 요구 사항 중)

Enum 클래스를 어떻게 적용할지 고민을 많이 했다. 단순하게 사용한 적은 있었지만, 이번 기회에 공부하면서 더 다양한 기능들이 있다는 사실을 알게 되었다.

적용할 만한 객체는 당첨 개수와 상금이었다. 직감적으로 당첨과 관련된 객체에 Enum을 적용하면 되겠다고 판단했다. Enum 클래스의 원소에 추가 속성을 부여하였다. 당첨 개수와 당첨 상금은 공통으로 붙어있는 속성이기 때문이다. 한편, 보너스 볼이라는 특수한 상황이 존재하기 때문에, Enum 원소를 결정할 때, 보너스 볼을 포함하는 경우를 고려하여야 하였다. valueOf 메소드를 재정의하여 이를 구현하였다.

public enum Winning {
    FAIL(0, 0),
    THREE(3, 5_000),
    FOUR(4, 50_000),
    FIVE(5, 1_500_000),
    BONUS(5, 30_000_000),
    SIX(6, 2_000_000_000);

    private final int correctCount;
    private final int rewards;

    Winning(int correctCount, int rewards) {
        this.correctCount = correctCount;
        this.rewards = rewards;
    }

    public static Winning valueOf(int correctCount, boolean isBonus) {
        if (correctCount == Winning.FIVE.correctCount) {
            return checkBonus(isBonus);
        }

        for (Winning winning : Winning.values()) {
            if (correctCount == winning.correctCount) {
                return winning;
            }
        }
        return FAIL;
    }

    private static Winning checkBonus(boolean isBonus) {
        if (isBonus) {
            return Winning.BONUS;
        }
        return Winning.FIVE;
    }
}

EnumMap

User가 추첨한 로또의 당첨 결과를 저장 후 분석해야 했다. 이를 위해 Map을 사용하는 것이 적절했는데, 그 중 EnumMap을 발견했다. HashMap과 EnumMap의 차이점은 다음 그림에 정리되어 있다. 간단하게 설명하자면, HashMap은 HashTable을 이용하지만, EnumMap은 배열을 이용한다. 따라서 배열을 이용해 순서대로 저장하기 때문에 충돌 가능성이 존재하지 않는다.

Test Coverage

테스트 코드 실행 버튼을 잘못 눌러 Run 'Application' With Coverage를 눌렀다. 그랬더니 작성했던 테스트 코드가 클래스의 어떤 부분을 Cover 했는지 비율을 알려줬다. 어떤 라인의 테스트를 진행하지 않았는 보여주면서 해당 라인에 하이라이트 기능을 제공한다. 이를 적극적으로 활용하자.

더 읽을 거리

profile
백엔드 엔지니어

0개의 댓글