Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

Mo-bile/java-lotto

Repository files navigation

로또

진행 방법

  • 로또 요구사항을 파악한다.
  • 요구사항에 대한 구현을 완료한 후 자신의 github 아이디에 해당하는 브랜치에 Pull Request(이하 PR)를 통해 코드 리뷰 요청을 한다.
  • 코드 리뷰 피드백에 대한 개선 작업을 하고 다시 PUSH한다.
  • 모든 피드백을 완료하면 다음 단계를 도전하고 앞의 과정을 반복한다.

온라인 코드 리뷰 과정

프로젝트

  • 문자열 사칙 연산 계산기 구현

요구 사항

  • 사용자가 입력한 문자열 값에 따라 사칙연산을 수행할 수 있는 계산기를 구현해야 한다.
  • 입력 문자열의 숫자사칙 연산 사이에는 반드시 빈 공백 문자열이 있다고 가정한다.
  • 나눗셈의 경우 결과 값을 정수로 떨어지는 값으로 한정한다.
  • 문자열 계산기는 사칙연산의 계산 우선순위가 아닌 입력 값에 따라 계산 순서가 결정된다. (즉, 수학에서는 곱셈, 나눗셈이 덧셈, 뺄셈 보다 먼저 계산해야 하지만 이를 무시한다.)
  • 예를 들어 2 + 3 * 4 / 2와 같은 문자열을 입력할 경우 2 + 3 * 4 / 2 실행 결과인 10을 출력

기능 목록

입력

  • 사용자가 문자열을 입력한다.
    • 사칙 연산을 모두 포함하는 기능 구현
    • 입력 값이 null이거나 빈 공백 문자일 경우 IllegalArgumentException throw
    • 사칙연산 기호가 아닌 경우 IllegalArgumentException throw
  • 입력받은 문자열을 처리한다
    • 공백 문자열을 빈 공백 문자로 분리하려면 String 클래스의 split(" ") 메소드

처리

  • 반복적인 패턴을 찾아 반복문으로 구현

연산단위

  • 덧셈
  • 뺄셈
  • 곱셈
  • 나눗셈

2단계 - 로또 (자동)

기능목록

  • : 로또 금액을 입력한다.
  • : 입력받은 금액으로 로또 n개 생성
    • : 1장의 가격은 1000원
    • : 로또 생성 시 Collections.shuffle() 로 생성
    • : Collections.sort() 로 로또 내부 번호 6자리 정렬
  • : 지난 주 당첨번호를 입력한다
    • : ArrayList의 contains() 로 어떤 값이 존재하는지 유무를 판단가능
      • : 3개, 4개, 5개, 6개 일치를 찾는다
    • : 총 가격대비 얼마 이득인지 수익률을 계산한다

클래스 다이어그램 설계

도메인 목록과 역할

  • Process : 로또 진행 흐름을 담당 (입력받은 금액을 갯수로 바꾼다.)
  • Lottos : 입력받은 갯수에 따라 Lotto 객체 생성
  • Lotto : 로또 역할, 입력받은 당첨번호로 당첨인지 확인
  • WinnerCount : 당첨번호 입력 및 당첨 통계 추리기

리팩터링

WinnerCount

  • WinnerCount를 Process 객체의 멤버로 넣어야 할 것인가?
    • 그러나 Process 내부 다른 Lottos필드와 와 생명주기가 다름
    • Lottos는 초반에 생기지만, WinnerCount 후반에 생김
    • WinnerCount 에 있는 calculateTotalReturn() 메서드에 인자로 pay를 넣는게 바람직한가 고민이 듬
      • 왜냐하면 Process 필드로 pay가 있는데 이것을 활용하지 못하고, controller에서 입력받은 pay를 활용해서 넣기 때문임
  • 3,4,5,6개 일치관련 enum 처리
    • switch 대신에 대안은 -> enum으로 행동넣기

3단계 - 로또 (2등)

기본 안내

기능 요구사항

2등을 위해 추가 번호를 하나 더 추첨한다. 당첨 통계에 2등도 추가해야 한다.

핵심 요구 사항

  • 2등을 위해 추가 번호를 하나 더 추첨한다.
  • 당첨 통계에 2등도 추가해야 한다.

기능목록

  • : 2등 당첨을 위해 로또 입력(보너스 볼)을 한번 더 받는다
    • : 당첨 방식에서 2, 3 등 차이를 같은 5개일치 + 보너스볼 일치로 차이를 둔다.
  • : enum
    • : 상수 명을 일치 갯수에서 등수로 변경한다
    • : MISS 추가한다
  • : 출력문 변경

클래스 다이어그램 설계

도메인 목록과 역할

  • 기존

    • LottoGame : 로또 진행 흐름을 담당 (입력받은 금액을 갯수로 바꾼다.)
    • Lottos : 입력받은 갯수에 따라 Lotto 객체 생성
    • Lotto : 로또 역할, 입력받은 당첨번호로 당첨인지 확인
    • WinningResult : 당첨번호 입력 및 당첨 통계 추리기
    • Pay : 입력받은 지불 금액에 대한 객체
    • Rank : 당첨 수와 금액의 정보를 가지고, 당첨에 필요한 매치넘버를 관리하는 객체
  • 추가

    • Bonus : 추가 수를 받아서 추가로 부합하는지 검증하는 객체

1차 피드백 리팩터링

  • : Bonus 에 필드 불변으로 변경
  • : Lotto 와 Bonus 간에 메시지를 주는 객체간 관계 재조정 및 테스트 제거
  • : findMatchCount 접근제어자 private 로 변경하면서 테스트 제거
  • : rankDecideByBonusNumber 메서드의 주체 변경
    • 이유 : 메서드 시그니쳐가 모두 Rank 가 있는데,,, 이정도면 충분히 Rank 에게 주어야하는 역할임
  • : Array 를 List 로 변경(Ai 검색 도움)
  • : 주요 메서드 명 변경 (Ai 도움)
    • 이유 : 의도를 명확히 드러내기 위해서

2차 피드백 후 리팩터링

  • : Lotto 문자열도 입력 받을 수있는 생성자 만들기
  • : Lotto 에서 WinningLotto로 당첨 판단에 대한 지식을 옮긴다.
    • : Lotto 에서 일치여부만 판단하는 것을 남긴다.
    • : Rank 와 Lotto 간 순환구조를 끊는다.
      • : 이를 위해서 Rank 내부에 매치 카운트에 2,3 등 부분까지 포함한다
  • : 생성자 리팩터링
  • : 반복문 stream API 로 변경

역할 정리

Lotto : 기본적인 로또 번호 역할 + 로또 번호가 일치하는지 WinningLotto : Lotto 에서 일치갯수와 보너스 맞는지 받아와 Rank 에 전달하여 당첨 결과를 WinningResult 에 전달 Rank : 규칙 정의 및 등수 판단

별도 메모

  • RankLotto 순환참조 없애기
    • indent 가 2여서 그러는건데 이 경우에 스트림 쓰기 추천
  • bonus 가 모든 번호 검증 -> 필요한거만
  • 쓰지않는 패키지(ctl + opt + O)와, 포매팅 정리 (opt + cmd + L)

추가 개인 과제

  • 난수생성에 대한 테스트 통제 (보류)
    • 현재 난수생성 방식은 static 메서드로 구현하여서 테스트 코드 내에서 Override가 불가능하다.

3차 피드백 후 리팩터링

  • : LottoNumber는 매번 인스턴스가 생성되기 때문에 인스턴스의 갯수가 너무 많아져 성능이 떨어질 수 있다. LottoNumber 인스턴스를 생성한 후 '재사용'할 수 있도록 구현한다. Map과 같은 곳에 인스턴스를 생성한 후 재사용하는 방법을 찾으면 됨 -> 방식 : 캐싱 구현

객체 그래프

 Pay → LottoGame
 ↘
 LottoTickets → List<Lotto> → List<LottoNumber> ← LottoNumberCache
 ↘
 WinningLotto (Lotto + bonus LottoNumber)
 ↓
 Rank → WinningResult (Map<Rank, Integer>)
  • 최종
    • Pay : 입력받은 지불 금액에 대한 객체
    • LottoGame : 로또 진행 흐름을 담당 (입력받은 금액을 갯수로 바꾼다.)
    • LottoTickets : 입력받은 갯수에 따라 Lotto 객체 생성
    • Lotto : 로또 역할, 입력받은 번호가 몇개 일치하는지 확인
    • LottoNumber : 로또의 각 수에 대한 포장 객체
    • LottoNumberCache : 로또 번호를 캐싱하여 로또번호 재생산 막는 역할
    • WinningLotto : 당첨번호 관리 (Lotto + LottoNumber)
    • Rank : 당첨 수와 금액의 정보를 가지고, 일치 갯수를 가지고 등수를 결정
    • WinningResult : 당첨 당첨 통계 추리기

4단계 - 로또 (수동)

기본 안내

기능 요구사항

  • 현재 로또 생성기는 자동 생성 기능만 제공한다. 사용자가 수동으로 추첨 번호를 입력할 수 있도록 해야 한다.
  • 입력한 금액, 자동 생성 숫자, 수동 생성 번호를 입력하도록 해야 한다.

핵심 요구 사항

  • 구매 로또 시 수동으로 추첨하는 기능 추가
  • 자동 생성 숫자, 수동 생성 번호 추가

기능목록

  • : 수동으로 구매 할 로또 수 입력
    • : 수동으로 구매하는 로또가 총 구매가능 수 보다 적은지
      • :로또 곧바로 자동 생성이 아닌 총 구매 가능 수 제시
        • : 넘었을 경우 다시 입력 유도
  • : 수동으로 구매할 로또 번호 입력
    • : 수동 로또 수만큼 반복입력한다
      • : 중복 입력, 1 ~ 45 범위 넘겨서 입력 시 다시 입력 유도
      • 고민 : 입력 한번 할 때 마다 제시 or 모아서 넘기기
      • : 모아서 넘기기
  • : 로또 발행 결과 수동, 자동 갯수 카운트
    • : 수동부터 먼저 제시

클래스 다이어그램 설계

도메인 목록과 역할

기존

  • Pay : 입력받은 지불 금액에 대한 객체
  • LottoGame : 로또 진행 흐름을 담당 (입력받은 금액을 갯수로 바꾼다.)
  • LottoTickets : 입력받은 갯수에 따라 Lotto 객체 생성
  • Lotto : 로또 역할, 입력받은 번호가 몇개 일치하는지 확인
  • LottoNumber : 로또의 각 수에 대한 포장 객체
  • LottoNumberCache : 로또 번호를 캐싱하여 로또번호 재생산 막는 역할
  • WinningLotto : 당첨번호 관리 (Lotto + LottoNumber)
  • Rank : 당첨 수와 금액의 정보를 가지고, 일치 갯수를 가지고 등수를 결정
  • WinningResult : 당첨 당첨 통계 추리기

추가

  • BuyLotto : 로또 구매(자동 + 수동) 에 대한 관리
  • manualLotto : 수동구매하는 로또와 그 갯수 관리

1차 피드백 후 리팩터링

  • : 로또를 생성하는 부분 인터페이스로 분리해 보는 연습
  • : of 메서드를 활용하면 LottoNumber 객체가 재사용되는 것을 보장하지 못함
    • LottoNumber 객체가 캐싱을 통해 재사용하는 것을 강제할 수 있도록 리팩터링
    • LottoNumberLottoNumberCache를 통합

2차 피드백 후 리팩터링

  • : 오히려 복잡해진 인터페이스 분리를 단순화하여서 구현
    • 이유

       1. 이전에는 인터페이스 구현체들은 필드가 모두 같아야한다는 것으로 잘못된 이해를 한점
       - 그 이유는 인터페이스 이용을 스프링 bean 생성 때만 주로 해봤기 때문
      
        1. 필드가 같아야한다는 잘못된 이해로 메서드 인자는 모두 같게, 그 내부 로직을 달리해서 구현한 점
    • 이러한 이유 때문에 오히려 인터페이스가 더 복잡해짐
  • : Controller 에서 분기 처리에 따라 인터페이스 구현체 갈아끼우는 것 제거하기
    • 조건문으로 같은 일(모드, 도메인)의 규칙 갈아끼우기에 불과함
  • 이렇게 인터페이스 분리하면 장점
    • 클라이언트 코드가 당장 필요한 구현체로 쉽게 갈아끼울수 있게 변경

3차 피드백 후 리팩터링

  • : LottoGenerator 가 LottoBuy 가 아닌 LottoTickets 을 생성하게 하기
  • : LottoGenerator 구현체에서 바로 LottoTickets를 생성하도록 접근하기
  • : LottoManulGenerator 에서 불필요한 pay 제거
    • 자동, 수동, 혼합 간에 필드는 비슷하게 pay, pay + lotto, lotto 각각 상황에 따라 인자가 달라짐
      • 즉 충분히 필드가 다를 수있다.

4차 피드백 후 리팩터링

  • : 이미 LottoAutoGenerator, LottoManualGenerator 각각의 구현체가 있는데 굳이 수동 자동관련 Auto, Manual 객체가 필요한지 고민할 것
    • 고민 : 기존에는 Auto, Manual 이 필요할 수있었다. 그러나 인터페이스 구현체가 그 역할을 대체한다
  • : composite 패턴을 이용해 part 인 구현체 LottoAutoGenerator, LottoManualGenerator 를 합친 composite 인 LottoCombineGenerator 를 이용한다
    • 그러면 필드도 두개 구현체를 합친 인터페이스의 List로 한다 그리고 기존 생성도 두개를 각각 넣어주는 방식으로 구현한다
    • 즉 여러 LottoGenerator 를 묶어서 두개를 하나처럼 쓸 수 있게 됨

About

로또 게임 구현을 관리하는 저장소

Resources

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published

Languages

  • Java 100.0%

AltStyle によって変換されたページ (->オリジナル) /