우테코 프리코스 3주차

쿠우·2022년 11월 16일
0

우테코프리코스

목록 보기
3/4

3주차 미션 요약

로또 게임 기능을 구현해야 한다.

  • 로또 번호의 숫자 범위는 1~45까지이다.
  • 1개의 로또를 발행할 때 중복되지 않는 6개의 숫자를 뽑는다.
  • 당첨 번호 추첨 시 중복되지 않는 숫자 6개와 보너스 번호 1개를 뽑는다.
  • 당첨은 1등부터 5등까지 있다. 당첨 기준과 금액은 아래와 같다.
    - 1등: 6개 번호 일치 / 2,000,000,000원
    - 2등: 5개 번호 + 보너스 번호 일치 / 30,000,000원
    - 3등: 5개 번호 일치 / 1,500,000원
    - 4등: 4개 번호 일치 / 50,000원
    - 5등: 3개 번호 일치 / 5,000원
    -로또 구입 금액을 입력하면 구입 금액에 해당하는 만큼 로또를 발행해야 한다./로또 1장의 가격은 1,000원
    -당첨 번호와 보너스 번호를 입력받는다.
  • 사용자가 구매한 로또 번호와 당첨 번호를 비교 당첨 내역 및 수익률을 출력하고 로또 게임을 종료
  • 사용자가 잘못된 값을 입력할 경우 IllegalArgumentException를 발생시키고, "[ERROR]"로 시작하는 에러 메시지를 출력 후 종료

입출력 요구사항

입력부
금액 입력부
-금액에 대한 입력
-금액에 대한 계산(로또 횟수)
당첨번호 입력부 (쉼표 기준 구분)
보너스 번호 입력 부

출력부
발행한 로또 수량 및 번호를 출력(오름차순 정렬)
당첨 내역을 출력
수익률 계산 및 안내 (수익률은 소수점 둘째 자리에서 반올림)

예외부
사용자가 잘못된 값을 입력 (1000원단위로 입력받는지 / )
예외 상황 시 에러 문구를 출력(에러 문구는 "[ERROR]"로 시작)하고 IllegalArgumentException발생 후 종료


Enum에 대한 고민

-사실상 사용한적이 거의 없어 지식이 전무했었다. Enum을 사용할 때 어떻게 선언하고 어떻게 불러오는지 기본 사용을 했던 시간이었다. 그러나 적절한 방법으로 사용하지 못했다고 생각한다. 더 효율적으로 적절하게 어떻게 사용할지도 고민해보는 것이 좋겠다.

https://techblog.woowahan.com/2527/ <우아한형제들 기술블로그에 Enum 설명서
(변수와 메소드들등 어디쪽이 책임지는 것이 좋을까 고민하면서 설계하자)

https://effortguy.tistory.com/25 > Enum에 대해 잘 정리되어있다

https://k3068.tistory.com/55 > Enum에 대해 잘 정리되어있다

https://pjh3749.tistory.com/279 > Enum 조회에 대해서 잘 정리되었다. 하지만 map에 대해 완벽하게 이해가 안되서 리팩토링하면서 사용해보자꾸나

-unmodifiableMap 읽기 전용의 맵을 만든다.
-Stream.of() 스트림 객체를 바로 생성
-collect() Stream의 데이터를 변형 등의 처리를 하고 원하는 자료형으로 변환


테스트에 대한 고민

예외의 경우와 각 타입별로 그리고 로직별로 테스트를 어떻게 진행하면 좋을까 고민하고 찾아보았다.

        String InputTestCase1 = "10";
        System.setIn(new ByteArrayInputStream(InputTestCase1.getBytes()));
        assertThat(bonusWinningNumber.putBonusNum(testValue)).isEqualTo(Integer.parseInt(InputTestCase1));
  • 예외에 대한 단위 테스트
        assertThatIllegalArgumentException()
                .isThrownBy(() -> bonusWinningNumber.putBonusNum(testValue));
  • 예외에 대한 로그를 어떻게 남기면 좋을까
    https://blog.naver.com/cbq3737/222356274792 > 예외 로그에 대한 설명이 잘되어있는 블로그 하지만 일단 out.println 으로 처리했다..

소감문

처음에 패키지와 기능에 따른 클래스를 나누고 비즈니스 로직 순서에 따라 간단하게 흐름을 가져가는 구조로 잡아야겠다고 생각하고 설계한 뒤 제작에 들어갔습니다.

하지만 진행하다 보니 Lotto 클래스를 도메인의 DTO라고 판단하고 MVC 패턴을 적용하면 좋겠다는 깨달음과 함께 왜 MVC 패턴이 웹 프로그래밍의 전반적인 구조를 차지하는지 깨닫게 되었습니다.
많은 개발자분들이 쌓아놓은 경험에 의해 만들어진 패턴이고 그만큼 효율적이며 체계적으로 공용화되어 흐름 파악에도 도움이 되는구나 느꼈습니다.

Enum 사용법을 익히고 생각해 보는 시간과 테스트를 직접 작성하면서 어떻게 테스트하면 좋을지 그리고 테스트의 중요성 또한 깨닫게 되었습니다.

다만 아직 리팩토링을 위한 시간 배분과 리팩토링에 대한 개념 그리고 방법에 대해서는 공부가 필요하고 프로그램 성능과 테스트까지 고려하지 못하고 있다는 점까지 발전해야 하는 부분으로 다가왔습니다.

나의 요번 과제

https://github.com/koo9b9h/java-lotto/tree/koo9b9h

+정적인 영역과 인스턴스 영역에서의 메소드 선언도 어떻게 하면 좋을지 연습해야 된다 느꼈다.


공통 피드백

-함수(메서드) 라인에 대한 기준

main() 함수에도 해당된다. 공백 라인도 한 라인에 해당한다. 15라인이 넘어간다면 함수 분리 (ok)

-발생할 수 있는 예외 상황에 대해 고민

예외 상황을 고려해 프로그래밍하는 습관을 들인다. (ok)

-비즈니스 로직과 UI 로직을 분리

비즈니스 로직과 UI 로직을 한 클래스가 담당하지 않도록 한다. 단일 책임의 원칙에도 위배 현재 객체의 상태를 보기 위한 로그 메시지 성격이 강하다면 toString()을 통해 구현한다. View에서 사용할 데이터라면 getter 메서드를 통해 데이터를 전달한다. (ok)

-연관성이 있는 상수는 static final 대신 enum을 활용/ final 키워드를 사용해 값의 변경을 막는다

최근에 등장하는 프로그래밍 언어들은 기본이 불변 값이다. 자바는 final 키워드를 활용해 값의 변경을 막을 수 있다 (ok)

-객체의 상태 접근을 제한한다

인스턴스 변수의 접근 제어자는 private으로 구현

-객체는 객체스럽게 사용한다!!!

https://tecoble.techcourse.co.kr/post/2020-04-28-ask-instead-of-getter/ < 간략하게 getter 대신 객체에 맞는 데이터를 던지라는 말인데 밥먹고 다시 봐야겠다.. 이것이 지금 나한테는 되게 중요한 부분!

-필드(인스턴스 변수)의 수를 줄이기 위해 노력한다

필드(인스턴스 변수)의 수가 많은 것은 객체의 복잡도를 높이고, 버그 발생 가능성을 높일 수 있다. 필드에 중복이 있거나, 불필요한 필드가 없는지 확인해 필드의 수를 최소화한다.

예를 들어 총 상금 및 수익률을 구하는 다음 객체를 보자.

public class LottoResult {
    private Map<Rank, Integer> result = new HashMap<>();
    private double profitRate;
    private int totalPrize;
}

아래와 같이 필드를 줄인다.

public class LottoResult {
    private Map<Rank, Integer> result = new HashMap<>();

    public double calculateProfitRate() { ... }
   
    public int calculateTotalPrize() { ... }
}

-성공하는 케이스 뿐만 아니라 예외에 대한 케이스도 테스트한다

프로그램에서 결함이 자주 발생하는 부분 중 하나는 경계값이므로 이 부분을 꼼꼼하게 확인해야 한다.

-테스트 코드도 코드다

테스트 코드도 코드이므로 리팩터링을 통해 개선해나가야 한다.

-테스트를 위한 코드는 구현 코드에서 분리되어야 한다!

테스트를 위한 편의 메서드를 구현 코드에 구현하지 마라.

  • 테스트를 위해 접근 제어자를 바꾸는 경우.
  • 테스트 코드에서만 사용되는 메서드

-단위 테스트하기 어려운 코드를 단위 테스트하기

어려운 부분은 분리하고 테스트 가능한 부분을 단위 테스트한다. 테스트하기 어려운 부분은 단위 테스트하지 않아도 된다.
https://tecoble.techcourse.co.kr/post/2020-05-07-appropriate_method_for_test_by_parameter/ 참고 블로그

-private 함수를 테스트 하고 싶다면 클래스(객체) 분리를 고려

가독성의 이유만으로 분리한 private 함수의 경우 public으로도 검증 가능하다고 여겨질 수 있다. public 함수가 private 함수를 사용하고 있기 때문에 자연스럽게 테스트 범위에 포함된다. 하지만 가독성 이상의 역할을 하는 경우, 테스트하기 쉽게 구현하기 위해서는 해당 역할을 수행하는 다른 객체를 만들 타이밍이 아닐지 고민해 볼 수 있다. 다음 단계를 진행할 때에는 너무 많은 역할을 하고 있는 함수나 객체를 어떻게 의미 있는 단위로 분할할지에 초점을 맞춰 진행한다.

profile
일단 흐자

0개의 댓글